1""" 2This LLDB module contains miscellaneous utilities. 3Some of the test suite takes advantage of the utility functions defined here. 4They can also be useful for general purpose lldb scripting. 5""" 6 7from __future__ import print_function 8from __future__ import absolute_import 9 10# System modules 11import errno 12import os 13import re 14import sys 15import subprocess 16 17# Third-party modules 18from six import StringIO as SixStringIO 19import six 20 21# LLDB modules 22import lldb 23from . import lldbtest_config 24from . import configuration 25 26# How often failed simulator process launches are retried. 27SIMULATOR_RETRY = 3 28 29# =================================================== 30# Utilities for locating/checking executable programs 31# =================================================== 32 33def is_exe(fpath): 34 """Returns True if fpath is an executable.""" 35 return os.path.isfile(fpath) and os.access(fpath, os.X_OK) 36 37 38def which(program): 39 """Returns the full path to a program; None otherwise.""" 40 fpath, fname = os.path.split(program) 41 if fpath: 42 if is_exe(program): 43 return program 44 else: 45 for path in os.environ["PATH"].split(os.pathsep): 46 exe_file = os.path.join(path, program) 47 if is_exe(exe_file): 48 return exe_file 49 return None 50 51def mkdir_p(path): 52 try: 53 os.makedirs(path) 54 except OSError as e: 55 if e.errno != errno.EEXIST: 56 raise 57 if not os.path.isdir(path): 58 raise OSError(errno.ENOTDIR, "%s is not a directory"%path) 59 60 61# ============================ 62# Dealing with SDK and triples 63# ============================ 64 65def get_xcode_sdk(os, env): 66 # Respect --apple-sdk <path> if it's specified. If the SDK is simply 67 # mounted from some disk image, and not actually installed, this is the 68 # only way to use it. 69 if configuration.apple_sdk: 70 return configuration.apple_sdk 71 if os == "ios": 72 if env == "simulator": 73 return "iphonesimulator" 74 if env == "macabi": 75 return "macosx" 76 return "iphoneos" 77 elif os == "tvos": 78 if env == "simulator": 79 return "appletvsimulator" 80 return "appletvos" 81 elif os == "watchos": 82 if env == "simulator": 83 return "watchsimulator" 84 return "watchos" 85 return os 86 87 88def get_xcode_sdk_version(sdk): 89 return subprocess.check_output( 90 ['xcrun', '--sdk', sdk, '--show-sdk-version']).rstrip().decode('utf-8') 91 92 93def get_xcode_sdk_root(sdk): 94 return subprocess.check_output(['xcrun', '--sdk', sdk, '--show-sdk-path' 95 ]).rstrip().decode('utf-8') 96 97 98def get_xcode_clang(sdk): 99 return subprocess.check_output(['xcrun', '-sdk', sdk, '-f', 'clang' 100 ]).rstrip().decode("utf-8") 101 102 103# =================================================== 104# Disassembly for an SBFunction or an SBSymbol object 105# =================================================== 106 107 108def disassemble(target, function_or_symbol): 109 """Disassemble the function or symbol given a target. 110 111 It returns the disassembly content in a string object. 112 """ 113 buf = SixStringIO() 114 insts = function_or_symbol.GetInstructions(target) 115 for i in insts: 116 print(i, file=buf) 117 return buf.getvalue() 118 119# ========================================================== 120# Integer (byte size 1, 2, 4, and 8) to bytearray conversion 121# ========================================================== 122 123 124def int_to_bytearray(val, bytesize): 125 """Utility function to convert an integer into a bytearray. 126 127 It returns the bytearray in the little endian format. It is easy to get the 128 big endian format, just do ba.reverse() on the returned object. 129 """ 130 import struct 131 132 if bytesize == 1: 133 return bytearray([val]) 134 135 # Little endian followed by a format character. 136 template = "<%c" 137 if bytesize == 2: 138 fmt = template % 'h' 139 elif bytesize == 4: 140 fmt = template % 'i' 141 elif bytesize == 4: 142 fmt = template % 'q' 143 else: 144 return None 145 146 packed = struct.pack(fmt, val) 147 return bytearray(packed) 148 149 150def bytearray_to_int(bytes, bytesize): 151 """Utility function to convert a bytearray into an integer. 152 153 It interprets the bytearray in the little endian format. For a big endian 154 bytearray, just do ba.reverse() on the object before passing it in. 155 """ 156 import struct 157 158 if bytesize == 1: 159 return bytes[0] 160 161 # Little endian followed by a format character. 162 template = "<%c" 163 if bytesize == 2: 164 fmt = template % 'h' 165 elif bytesize == 4: 166 fmt = template % 'i' 167 elif bytesize == 4: 168 fmt = template % 'q' 169 else: 170 return None 171 172 unpacked = struct.unpack_from(fmt, bytes) 173 return unpacked[0] 174 175 176# ============================================================== 177# Get the description of an lldb object or None if not available 178# ============================================================== 179def get_description(obj, option=None): 180 """Calls lldb_obj.GetDescription() and returns a string, or None. 181 182 For SBTarget, SBBreakpointLocation, and SBWatchpoint lldb objects, an extra 183 option can be passed in to describe the detailed level of description 184 desired: 185 o lldb.eDescriptionLevelBrief 186 o lldb.eDescriptionLevelFull 187 o lldb.eDescriptionLevelVerbose 188 """ 189 method = getattr(obj, 'GetDescription') 190 if not method: 191 return None 192 tuple = (lldb.SBTarget, lldb.SBBreakpointLocation, lldb.SBWatchpoint) 193 if isinstance(obj, tuple): 194 if option is None: 195 option = lldb.eDescriptionLevelBrief 196 197 stream = lldb.SBStream() 198 if option is None: 199 success = method(stream) 200 else: 201 success = method(stream, option) 202 if not success: 203 return None 204 return stream.GetData() 205 206 207# ================================================= 208# Convert some enum value to its string counterpart 209# ================================================= 210 211def state_type_to_str(enum): 212 """Returns the stateType string given an enum.""" 213 if enum == lldb.eStateInvalid: 214 return "invalid" 215 elif enum == lldb.eStateUnloaded: 216 return "unloaded" 217 elif enum == lldb.eStateConnected: 218 return "connected" 219 elif enum == lldb.eStateAttaching: 220 return "attaching" 221 elif enum == lldb.eStateLaunching: 222 return "launching" 223 elif enum == lldb.eStateStopped: 224 return "stopped" 225 elif enum == lldb.eStateRunning: 226 return "running" 227 elif enum == lldb.eStateStepping: 228 return "stepping" 229 elif enum == lldb.eStateCrashed: 230 return "crashed" 231 elif enum == lldb.eStateDetached: 232 return "detached" 233 elif enum == lldb.eStateExited: 234 return "exited" 235 elif enum == lldb.eStateSuspended: 236 return "suspended" 237 else: 238 raise Exception("Unknown StateType enum") 239 240 241def stop_reason_to_str(enum): 242 """Returns the stopReason string given an enum.""" 243 if enum == lldb.eStopReasonInvalid: 244 return "invalid" 245 elif enum == lldb.eStopReasonNone: 246 return "none" 247 elif enum == lldb.eStopReasonTrace: 248 return "trace" 249 elif enum == lldb.eStopReasonBreakpoint: 250 return "breakpoint" 251 elif enum == lldb.eStopReasonWatchpoint: 252 return "watchpoint" 253 elif enum == lldb.eStopReasonExec: 254 return "exec" 255 elif enum == lldb.eStopReasonFork: 256 return "fork" 257 elif enum == lldb.eStopReasonVFork: 258 return "vfork" 259 elif enum == lldb.eStopReasonVForkDone: 260 return "vforkdone" 261 elif enum == lldb.eStopReasonSignal: 262 return "signal" 263 elif enum == lldb.eStopReasonException: 264 return "exception" 265 elif enum == lldb.eStopReasonPlanComplete: 266 return "plancomplete" 267 elif enum == lldb.eStopReasonThreadExiting: 268 return "threadexiting" 269 else: 270 raise Exception("Unknown StopReason enum") 271 272 273def symbol_type_to_str(enum): 274 """Returns the symbolType string given an enum.""" 275 if enum == lldb.eSymbolTypeInvalid: 276 return "invalid" 277 elif enum == lldb.eSymbolTypeAbsolute: 278 return "absolute" 279 elif enum == lldb.eSymbolTypeCode: 280 return "code" 281 elif enum == lldb.eSymbolTypeData: 282 return "data" 283 elif enum == lldb.eSymbolTypeTrampoline: 284 return "trampoline" 285 elif enum == lldb.eSymbolTypeRuntime: 286 return "runtime" 287 elif enum == lldb.eSymbolTypeException: 288 return "exception" 289 elif enum == lldb.eSymbolTypeSourceFile: 290 return "sourcefile" 291 elif enum == lldb.eSymbolTypeHeaderFile: 292 return "headerfile" 293 elif enum == lldb.eSymbolTypeObjectFile: 294 return "objectfile" 295 elif enum == lldb.eSymbolTypeCommonBlock: 296 return "commonblock" 297 elif enum == lldb.eSymbolTypeBlock: 298 return "block" 299 elif enum == lldb.eSymbolTypeLocal: 300 return "local" 301 elif enum == lldb.eSymbolTypeParam: 302 return "param" 303 elif enum == lldb.eSymbolTypeVariable: 304 return "variable" 305 elif enum == lldb.eSymbolTypeVariableType: 306 return "variabletype" 307 elif enum == lldb.eSymbolTypeLineEntry: 308 return "lineentry" 309 elif enum == lldb.eSymbolTypeLineHeader: 310 return "lineheader" 311 elif enum == lldb.eSymbolTypeScopeBegin: 312 return "scopebegin" 313 elif enum == lldb.eSymbolTypeScopeEnd: 314 return "scopeend" 315 elif enum == lldb.eSymbolTypeAdditional: 316 return "additional" 317 elif enum == lldb.eSymbolTypeCompiler: 318 return "compiler" 319 elif enum == lldb.eSymbolTypeInstrumentation: 320 return "instrumentation" 321 elif enum == lldb.eSymbolTypeUndefined: 322 return "undefined" 323 324 325def value_type_to_str(enum): 326 """Returns the valueType string given an enum.""" 327 if enum == lldb.eValueTypeInvalid: 328 return "invalid" 329 elif enum == lldb.eValueTypeVariableGlobal: 330 return "global_variable" 331 elif enum == lldb.eValueTypeVariableStatic: 332 return "static_variable" 333 elif enum == lldb.eValueTypeVariableArgument: 334 return "argument_variable" 335 elif enum == lldb.eValueTypeVariableLocal: 336 return "local_variable" 337 elif enum == lldb.eValueTypeRegister: 338 return "register" 339 elif enum == lldb.eValueTypeRegisterSet: 340 return "register_set" 341 elif enum == lldb.eValueTypeConstResult: 342 return "constant_result" 343 else: 344 raise Exception("Unknown ValueType enum") 345 346 347# ================================================== 348# Get stopped threads due to each stop reason. 349# ================================================== 350 351def sort_stopped_threads(process, 352 breakpoint_threads=None, 353 crashed_threads=None, 354 watchpoint_threads=None, 355 signal_threads=None, 356 exiting_threads=None, 357 other_threads=None): 358 """ Fills array *_threads with threads stopped for the corresponding stop 359 reason. 360 """ 361 for lst in [breakpoint_threads, 362 watchpoint_threads, 363 signal_threads, 364 exiting_threads, 365 other_threads]: 366 if lst is not None: 367 lst[:] = [] 368 369 for thread in process: 370 dispatched = False 371 for (reason, list) in [(lldb.eStopReasonBreakpoint, breakpoint_threads), 372 (lldb.eStopReasonException, crashed_threads), 373 (lldb.eStopReasonWatchpoint, watchpoint_threads), 374 (lldb.eStopReasonSignal, signal_threads), 375 (lldb.eStopReasonThreadExiting, exiting_threads), 376 (None, other_threads)]: 377 if not dispatched and list is not None: 378 if thread.GetStopReason() == reason or reason is None: 379 list.append(thread) 380 dispatched = True 381 382# ================================================== 383# Utility functions for setting breakpoints 384# ================================================== 385 386def run_break_set_by_script( 387 test, 388 class_name, 389 extra_options=None, 390 num_expected_locations=1): 391 """Set a scripted breakpoint. Check that it got the right number of locations.""" 392 test.assertTrue(class_name is not None, "Must pass in a class name.") 393 command = "breakpoint set -P " + class_name 394 if extra_options is not None: 395 command += " " + extra_options 396 397 break_results = run_break_set_command(test, command) 398 check_breakpoint_result(test, break_results, num_locations=num_expected_locations) 399 return get_bpno_from_match(break_results) 400 401def run_break_set_by_file_and_line( 402 test, 403 file_name, 404 line_number, 405 extra_options=None, 406 num_expected_locations=1, 407 loc_exact=False, 408 module_name=None): 409 """Set a breakpoint by file and line, returning the breakpoint number. 410 411 If extra_options is not None, then we append it to the breakpoint set command. 412 413 If num_expected_locations is -1, we check that we got AT LEAST one location. If num_expected_locations is -2, we don't 414 check the actual number at all. Otherwise, we check that num_expected_locations equals the number of locations. 415 416 If loc_exact is true, we check that there is one location, and that location must be at the input file and line number.""" 417 418 if file_name is None: 419 command = 'breakpoint set -l %d' % (line_number) 420 else: 421 command = 'breakpoint set -f "%s" -l %d' % (file_name, line_number) 422 423 if module_name: 424 command += " --shlib '%s'" % (module_name) 425 426 if extra_options: 427 command += " " + extra_options 428 429 break_results = run_break_set_command(test, command) 430 431 if num_expected_locations == 1 and loc_exact: 432 check_breakpoint_result( 433 test, 434 break_results, 435 num_locations=num_expected_locations, 436 file_name=file_name, 437 line_number=line_number, 438 module_name=module_name) 439 else: 440 check_breakpoint_result( 441 test, 442 break_results, 443 num_locations=num_expected_locations) 444 445 return get_bpno_from_match(break_results) 446 447 448def run_break_set_by_symbol( 449 test, 450 symbol, 451 extra_options=None, 452 num_expected_locations=-1, 453 sym_exact=False, 454 module_name=None): 455 """Set a breakpoint by symbol name. Common options are the same as run_break_set_by_file_and_line. 456 457 If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match.""" 458 command = 'breakpoint set -n "%s"' % (symbol) 459 460 if module_name: 461 command += " --shlib '%s'" % (module_name) 462 463 if extra_options: 464 command += " " + extra_options 465 466 break_results = run_break_set_command(test, command) 467 468 if num_expected_locations == 1 and sym_exact: 469 check_breakpoint_result( 470 test, 471 break_results, 472 num_locations=num_expected_locations, 473 symbol_name=symbol, 474 module_name=module_name) 475 else: 476 check_breakpoint_result( 477 test, 478 break_results, 479 num_locations=num_expected_locations) 480 481 return get_bpno_from_match(break_results) 482 483 484def run_break_set_by_selector( 485 test, 486 selector, 487 extra_options=None, 488 num_expected_locations=-1, 489 module_name=None): 490 """Set a breakpoint by selector. Common options are the same as run_break_set_by_file_and_line.""" 491 492 command = 'breakpoint set -S "%s"' % (selector) 493 494 if module_name: 495 command += ' --shlib "%s"' % (module_name) 496 497 if extra_options: 498 command += " " + extra_options 499 500 break_results = run_break_set_command(test, command) 501 502 if num_expected_locations == 1: 503 check_breakpoint_result( 504 test, 505 break_results, 506 num_locations=num_expected_locations, 507 symbol_name=selector, 508 symbol_match_exact=False, 509 module_name=module_name) 510 else: 511 check_breakpoint_result( 512 test, 513 break_results, 514 num_locations=num_expected_locations) 515 516 return get_bpno_from_match(break_results) 517 518 519def run_break_set_by_regexp( 520 test, 521 regexp, 522 extra_options=None, 523 num_expected_locations=-1): 524 """Set a breakpoint by regular expression match on symbol name. Common options are the same as run_break_set_by_file_and_line.""" 525 526 command = 'breakpoint set -r "%s"' % (regexp) 527 if extra_options: 528 command += " " + extra_options 529 530 break_results = run_break_set_command(test, command) 531 532 check_breakpoint_result( 533 test, 534 break_results, 535 num_locations=num_expected_locations) 536 537 return get_bpno_from_match(break_results) 538 539 540def run_break_set_by_source_regexp( 541 test, 542 regexp, 543 extra_options=None, 544 num_expected_locations=-1): 545 """Set a breakpoint by source regular expression. Common options are the same as run_break_set_by_file_and_line.""" 546 command = 'breakpoint set -p "%s"' % (regexp) 547 if extra_options: 548 command += " " + extra_options 549 550 break_results = run_break_set_command(test, command) 551 552 check_breakpoint_result( 553 test, 554 break_results, 555 num_locations=num_expected_locations) 556 557 return get_bpno_from_match(break_results) 558 559def run_break_set_by_file_colon_line( 560 test, 561 specifier, 562 path, 563 line_number, 564 column_number = 0, 565 extra_options=None, 566 num_expected_locations=-1): 567 command = 'breakpoint set -y "%s"'%(specifier) 568 if extra_options: 569 command += " " + extra_options 570 571 print("About to run: '%s'", command) 572 break_results = run_break_set_command(test, command) 573 check_breakpoint_result( 574 test, 575 break_results, 576 num_locations = num_expected_locations, 577 file_name = path, 578 line_number = line_number, 579 column_number = column_number) 580 581 return get_bpno_from_match(break_results) 582 583def run_break_set_command(test, command): 584 """Run the command passed in - it must be some break set variant - and analyze the result. 585 Returns a dictionary of information gleaned from the command-line results. 586 Will assert if the breakpoint setting fails altogether. 587 588 Dictionary will contain: 589 bpno - breakpoint of the newly created breakpoint, -1 on error. 590 num_locations - number of locations set for the breakpoint. 591 592 If there is only one location, the dictionary MAY contain: 593 file - source file name 594 line_no - source line number 595 column - source column number 596 symbol - symbol name 597 inline_symbol - inlined symbol name 598 offset - offset from the original symbol 599 module - module 600 address - address at which the breakpoint was set.""" 601 602 patterns = [ 603 r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$", 604 r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.", 605 r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>[+\-]{0,1}[^+]+)( \+ (?P<offset>[0-9]+)){0,1}( \[inlined\] (?P<inline_symbol>.*)){0,1} at (?P<file>[^:]+):(?P<line_no>[0-9]+)(?P<column>(:[0-9]+)?), address = (?P<address>0x[0-9a-fA-F]+)$", 606 r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>.*)( \+ (?P<offset>[0-9]+)){0,1}, address = (?P<address>0x[0-9a-fA-F]+)$"] 607 match_object = test.match(command, patterns) 608 break_results = match_object.groupdict() 609 610 # We always insert the breakpoint number, setting it to -1 if we couldn't find it 611 # Also, make sure it gets stored as an integer. 612 if not 'bpno' in break_results: 613 break_results['bpno'] = -1 614 else: 615 break_results['bpno'] = int(break_results['bpno']) 616 617 # We always insert the number of locations 618 # If ONE location is set for the breakpoint, then the output doesn't mention locations, but it has to be 1... 619 # We also make sure it is an integer. 620 621 if not 'num_locations' in break_results: 622 num_locations = 1 623 else: 624 num_locations = break_results['num_locations'] 625 if num_locations == 'no': 626 num_locations = 0 627 else: 628 num_locations = int(break_results['num_locations']) 629 630 break_results['num_locations'] = num_locations 631 632 if 'line_no' in break_results: 633 break_results['line_no'] = int(break_results['line_no']) 634 635 return break_results 636 637 638def get_bpno_from_match(break_results): 639 return int(break_results['bpno']) 640 641 642def check_breakpoint_result( 643 test, 644 break_results, 645 file_name=None, 646 line_number=-1, 647 column_number=0, 648 symbol_name=None, 649 symbol_match_exact=True, 650 module_name=None, 651 offset=-1, 652 num_locations=-1): 653 654 out_num_locations = break_results['num_locations'] 655 656 if num_locations == -1: 657 test.assertTrue(out_num_locations > 0, 658 "Expecting one or more locations, got none.") 659 elif num_locations != -2: 660 test.assertTrue( 661 num_locations == out_num_locations, 662 "Expecting %d locations, got %d." % 663 (num_locations, 664 out_num_locations)) 665 666 if file_name: 667 out_file_name = "" 668 if 'file' in break_results: 669 out_file_name = break_results['file'] 670 test.assertTrue( 671 file_name.endswith(out_file_name), 672 "Breakpoint file name '%s' doesn't match resultant name '%s'." % 673 (file_name, 674 out_file_name)) 675 676 if line_number != -1: 677 out_line_number = -1 678 if 'line_no' in break_results: 679 out_line_number = break_results['line_no'] 680 681 test.assertTrue( 682 line_number == out_line_number, 683 "Breakpoint line number %s doesn't match resultant line %s." % 684 (line_number, 685 out_line_number)) 686 687 if column_number != 0: 688 out_column_number = 0 689 if 'column' in break_results: 690 out_column_number = break_results['column'] 691 692 test.assertTrue( 693 column_number == out_column_number, 694 "Breakpoint column number %s doesn't match resultant column %s." % 695 (column_number, 696 out_column_number)) 697 698 if symbol_name: 699 out_symbol_name = "" 700 # Look first for the inlined symbol name, otherwise use the symbol 701 # name: 702 if 'inline_symbol' in break_results and break_results['inline_symbol']: 703 out_symbol_name = break_results['inline_symbol'] 704 elif 'symbol' in break_results: 705 out_symbol_name = break_results['symbol'] 706 707 if symbol_match_exact: 708 test.assertTrue( 709 symbol_name == out_symbol_name, 710 "Symbol name '%s' doesn't match resultant symbol '%s'." % 711 (symbol_name, 712 out_symbol_name)) 713 else: 714 test.assertTrue( 715 out_symbol_name.find(symbol_name) != - 716 1, 717 "Symbol name '%s' isn't in resultant symbol '%s'." % 718 (symbol_name, 719 out_symbol_name)) 720 721 if module_name: 722 out_module_name = None 723 if 'module' in break_results: 724 out_module_name = break_results['module'] 725 726 test.assertTrue( 727 module_name.find(out_module_name) != - 728 1, 729 "Symbol module name '%s' isn't in expected module name '%s'." % 730 (out_module_name, 731 module_name)) 732 733# ================================================== 734# Utility functions related to Threads and Processes 735# ================================================== 736 737 738def get_stopped_threads(process, reason): 739 """Returns the thread(s) with the specified stop reason in a list. 740 741 The list can be empty if no such thread exists. 742 """ 743 threads = [] 744 for t in process: 745 if t.GetStopReason() == reason: 746 threads.append(t) 747 return threads 748 749 750def get_stopped_thread(process, reason): 751 """A convenience function which returns the first thread with the given stop 752 reason or None. 753 754 Example usages: 755 756 1. Get the stopped thread due to a breakpoint condition 757 758 ... 759 from lldbutil import get_stopped_thread 760 thread = get_stopped_thread(process, lldb.eStopReasonPlanComplete) 761 self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") 762 ... 763 764 2. Get the thread stopped due to a breakpoint 765 766 ... 767 from lldbutil import get_stopped_thread 768 thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) 769 self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint") 770 ... 771 772 """ 773 threads = get_stopped_threads(process, reason) 774 if len(threads) == 0: 775 return None 776 return threads[0] 777 778 779def get_threads_stopped_at_breakpoint_id(process, bpid): 780 """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt""" 781 stopped_threads = [] 782 threads = [] 783 784 stopped_threads = get_stopped_threads(process, lldb.eStopReasonBreakpoint) 785 786 if len(stopped_threads) == 0: 787 return threads 788 789 for thread in stopped_threads: 790 # Make sure we've hit our breakpoint... 791 break_id = thread.GetStopReasonDataAtIndex(0) 792 if break_id == bpid: 793 threads.append(thread) 794 795 return threads 796 797 798def get_threads_stopped_at_breakpoint(process, bkpt): 799 return get_threads_stopped_at_breakpoint_id(process, bkpt.GetID()) 800 801 802def get_one_thread_stopped_at_breakpoint_id( 803 process, bpid, require_exactly_one=True): 804 threads = get_threads_stopped_at_breakpoint_id(process, bpid) 805 if len(threads) == 0: 806 return None 807 if require_exactly_one and len(threads) != 1: 808 return None 809 810 return threads[0] 811 812 813def get_one_thread_stopped_at_breakpoint( 814 process, bkpt, require_exactly_one=True): 815 return get_one_thread_stopped_at_breakpoint_id( 816 process, bkpt.GetID(), require_exactly_one) 817 818 819def is_thread_crashed(test, thread): 820 """In the test suite we dereference a null pointer to simulate a crash. The way this is 821 reported depends on the platform.""" 822 if test.platformIsDarwin(): 823 return thread.GetStopReason( 824 ) == lldb.eStopReasonException and "EXC_BAD_ACCESS" in thread.GetStopDescription(100) 825 elif test.getPlatform() == "linux": 826 return thread.GetStopReason() == lldb.eStopReasonSignal and thread.GetStopReasonDataAtIndex( 827 0) == thread.GetProcess().GetUnixSignals().GetSignalNumberFromName("SIGSEGV") 828 elif test.getPlatform() == "windows": 829 return "Exception 0xc0000005" in thread.GetStopDescription(200) 830 else: 831 return "invalid address" in thread.GetStopDescription(100) 832 833 834def get_crashed_threads(test, process): 835 threads = [] 836 if process.GetState() != lldb.eStateStopped: 837 return threads 838 for thread in process: 839 if is_thread_crashed(test, thread): 840 threads.append(thread) 841 return threads 842 843# Helper functions for run_to_{source,name}_breakpoint: 844 845def run_to_breakpoint_make_target(test, exe_name = "a.out", in_cwd = True): 846 if in_cwd: 847 exe = test.getBuildArtifact(exe_name) 848 849 # Create the target 850 target = test.dbg.CreateTarget(exe) 851 test.assertTrue(target, "Target: %s is not valid."%(exe_name)) 852 853 # Set environment variables for the inferior. 854 if lldbtest_config.inferior_env: 855 test.runCmd('settings set target.env-vars {}'.format( 856 lldbtest_config.inferior_env)) 857 858 return target 859 860def run_to_breakpoint_do_run(test, target, bkpt, launch_info = None, 861 only_one_thread = True, extra_images = None): 862 863 # Launch the process, and do not stop at the entry point. 864 if not launch_info: 865 launch_info = target.GetLaunchInfo() 866 launch_info.SetWorkingDirectory(test.get_process_working_directory()) 867 868 if extra_images: 869 environ = test.registerSharedLibrariesWithTarget(target, extra_images) 870 launch_info.SetEnvironmentEntries(environ, True) 871 872 error = lldb.SBError() 873 process = target.Launch(launch_info, error) 874 875 # Unfortunate workaround for the iPhone simulator. 876 retry = SIMULATOR_RETRY 877 while (retry and error.Fail() and error.GetCString() and 878 "Unable to boot the Simulator" in error.GetCString()): 879 retry -= 1 880 print("** Simulator is unresponsive. Retrying %d more time(s)"%retry) 881 import time 882 time.sleep(60) 883 error = lldb.SBError() 884 process = target.Launch(launch_info, error) 885 886 test.assertTrue(process, 887 "Could not create a valid process for %s: %s" % 888 (target.GetExecutable().GetFilename(), error.GetCString())) 889 test.assertFalse(error.Fail(), 890 "Process launch failed: %s" % (error.GetCString())) 891 892 test.assertEqual(process.GetState(), lldb.eStateStopped) 893 894 # Frame #0 should be at our breakpoint. 895 threads = get_threads_stopped_at_breakpoint( 896 process, bkpt) 897 898 num_threads = len(threads) 899 if only_one_thread: 900 test.assertEqual(num_threads, 1, "Expected 1 thread to stop at breakpoint, %d did."%(num_threads)) 901 else: 902 test.assertGreater(num_threads, 0, "No threads stopped at breakpoint") 903 904 thread = threads[0] 905 return (target, process, thread, bkpt) 906 907def run_to_name_breakpoint (test, bkpt_name, launch_info = None, 908 exe_name = "a.out", 909 bkpt_module = None, 910 in_cwd = True, 911 only_one_thread = True, 912 extra_images = None): 913 """Start up a target, using exe_name as the executable, and run it to 914 a breakpoint set by name on bkpt_name restricted to bkpt_module. 915 916 If you want to pass in launch arguments or environment 917 variables, you can optionally pass in an SBLaunchInfo. If you 918 do that, remember to set the working directory as well. 919 920 If your executable isn't called a.out, you can pass that in. 921 And if your executable isn't in the CWD, pass in the absolute 922 path to the executable in exe_name, and set in_cwd to False. 923 924 If you need to restrict the breakpoint to a particular module, 925 pass the module name (a string not a FileSpec) in bkpt_module. If 926 nothing is passed in setting will be unrestricted. 927 928 If the target isn't valid, the breakpoint isn't found, or hit, the 929 function will cause a testsuite failure. 930 931 If successful it returns a tuple with the target process and 932 thread that hit the breakpoint, and the breakpoint that we set 933 for you. 934 935 If only_one_thread is true, we require that there be only one 936 thread stopped at the breakpoint. Otherwise we only require one 937 or more threads stop there. If there are more than one, we return 938 the first thread that stopped. 939 """ 940 941 target = run_to_breakpoint_make_target(test, exe_name, in_cwd) 942 943 breakpoint = target.BreakpointCreateByName(bkpt_name, bkpt_module) 944 945 946 test.assertTrue(breakpoint.GetNumLocations() > 0, 947 "No locations found for name breakpoint: '%s'."%(bkpt_name)) 948 return run_to_breakpoint_do_run(test, target, breakpoint, launch_info, 949 only_one_thread, extra_images) 950 951def run_to_source_breakpoint(test, bkpt_pattern, source_spec, 952 launch_info = None, exe_name = "a.out", 953 bkpt_module = None, 954 in_cwd = True, 955 only_one_thread = True, 956 extra_images = None, 957 has_locations_before_run = True): 958 """Start up a target, using exe_name as the executable, and run it to 959 a breakpoint set by source regex bkpt_pattern. 960 961 The rest of the behavior is the same as run_to_name_breakpoint. 962 """ 963 964 target = run_to_breakpoint_make_target(test, exe_name, in_cwd) 965 # Set the breakpoints 966 breakpoint = target.BreakpointCreateBySourceRegex( 967 bkpt_pattern, source_spec, bkpt_module) 968 if has_locations_before_run: 969 test.assertTrue(breakpoint.GetNumLocations() > 0, 970 'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"' 971 %(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory())) 972 return run_to_breakpoint_do_run(test, target, breakpoint, launch_info, 973 only_one_thread, extra_images) 974 975def run_to_line_breakpoint(test, source_spec, line_number, column = 0, 976 launch_info = None, exe_name = "a.out", 977 bkpt_module = None, 978 in_cwd = True, 979 only_one_thread = True, 980 extra_images = None): 981 """Start up a target, using exe_name as the executable, and run it to 982 a breakpoint set by (source_spec, line_number(, column)). 983 984 The rest of the behavior is the same as run_to_name_breakpoint. 985 """ 986 987 target = run_to_breakpoint_make_target(test, exe_name, in_cwd) 988 # Set the breakpoints 989 breakpoint = target.BreakpointCreateByLocation( 990 source_spec, line_number, column, 0, lldb.SBFileSpecList()) 991 test.assertTrue(breakpoint.GetNumLocations() > 0, 992 'No locations found for line breakpoint: "%s:%d(:%d)", dir: "%s"' 993 %(source_spec.GetFilename(), line_number, column, 994 source_spec.GetDirectory())) 995 return run_to_breakpoint_do_run(test, target, breakpoint, launch_info, 996 only_one_thread, extra_images) 997 998 999def continue_to_breakpoint(process, bkpt): 1000 """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None""" 1001 process.Continue() 1002 if process.GetState() != lldb.eStateStopped: 1003 return None 1004 else: 1005 return get_threads_stopped_at_breakpoint(process, bkpt) 1006 1007 1008def get_caller_symbol(thread): 1009 """ 1010 Returns the symbol name for the call site of the leaf function. 1011 """ 1012 depth = thread.GetNumFrames() 1013 if depth <= 1: 1014 return None 1015 caller = thread.GetFrameAtIndex(1).GetSymbol() 1016 if caller: 1017 return caller.GetName() 1018 else: 1019 return None 1020 1021 1022def get_function_names(thread): 1023 """ 1024 Returns a sequence of function names from the stack frames of this thread. 1025 """ 1026 def GetFuncName(i): 1027 return thread.GetFrameAtIndex(i).GetFunctionName() 1028 1029 return list(map(GetFuncName, list(range(thread.GetNumFrames())))) 1030 1031 1032def get_symbol_names(thread): 1033 """ 1034 Returns a sequence of symbols for this thread. 1035 """ 1036 def GetSymbol(i): 1037 return thread.GetFrameAtIndex(i).GetSymbol().GetName() 1038 1039 return list(map(GetSymbol, list(range(thread.GetNumFrames())))) 1040 1041 1042def get_pc_addresses(thread): 1043 """ 1044 Returns a sequence of pc addresses for this thread. 1045 """ 1046 def GetPCAddress(i): 1047 return thread.GetFrameAtIndex(i).GetPCAddress() 1048 1049 return list(map(GetPCAddress, list(range(thread.GetNumFrames())))) 1050 1051 1052def get_filenames(thread): 1053 """ 1054 Returns a sequence of file names from the stack frames of this thread. 1055 """ 1056 def GetFilename(i): 1057 return thread.GetFrameAtIndex( 1058 i).GetLineEntry().GetFileSpec().GetFilename() 1059 1060 return list(map(GetFilename, list(range(thread.GetNumFrames())))) 1061 1062 1063def get_line_numbers(thread): 1064 """ 1065 Returns a sequence of line numbers from the stack frames of this thread. 1066 """ 1067 def GetLineNumber(i): 1068 return thread.GetFrameAtIndex(i).GetLineEntry().GetLine() 1069 1070 return list(map(GetLineNumber, list(range(thread.GetNumFrames())))) 1071 1072 1073def get_module_names(thread): 1074 """ 1075 Returns a sequence of module names from the stack frames of this thread. 1076 """ 1077 def GetModuleName(i): 1078 return thread.GetFrameAtIndex( 1079 i).GetModule().GetFileSpec().GetFilename() 1080 1081 return list(map(GetModuleName, list(range(thread.GetNumFrames())))) 1082 1083 1084def get_stack_frames(thread): 1085 """ 1086 Returns a sequence of stack frames for this thread. 1087 """ 1088 def GetStackFrame(i): 1089 return thread.GetFrameAtIndex(i) 1090 1091 return list(map(GetStackFrame, list(range(thread.GetNumFrames())))) 1092 1093 1094def print_stacktrace(thread, string_buffer=False): 1095 """Prints a simple stack trace of this thread.""" 1096 1097 output = SixStringIO() if string_buffer else sys.stdout 1098 target = thread.GetProcess().GetTarget() 1099 1100 depth = thread.GetNumFrames() 1101 1102 mods = get_module_names(thread) 1103 funcs = get_function_names(thread) 1104 symbols = get_symbol_names(thread) 1105 files = get_filenames(thread) 1106 lines = get_line_numbers(thread) 1107 addrs = get_pc_addresses(thread) 1108 1109 if thread.GetStopReason() != lldb.eStopReasonInvalid: 1110 desc = "stop reason=" + stop_reason_to_str(thread.GetStopReason()) 1111 else: 1112 desc = "" 1113 print( 1114 "Stack trace for thread id={0:#x} name={1} queue={2} ".format( 1115 thread.GetThreadID(), 1116 thread.GetName(), 1117 thread.GetQueueName()) + desc, 1118 file=output) 1119 1120 for i in range(depth): 1121 frame = thread.GetFrameAtIndex(i) 1122 function = frame.GetFunction() 1123 1124 load_addr = addrs[i].GetLoadAddress(target) 1125 if not function: 1126 file_addr = addrs[i].GetFileAddress() 1127 start_addr = frame.GetSymbol().GetStartAddress().GetFileAddress() 1128 symbol_offset = file_addr - start_addr 1129 print( 1130 " frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format( 1131 num=i, 1132 addr=load_addr, 1133 mod=mods[i], 1134 symbol=symbols[i], 1135 offset=symbol_offset), 1136 file=output) 1137 else: 1138 print( 1139 " frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format( 1140 num=i, 1141 addr=load_addr, 1142 mod=mods[i], 1143 func='%s [inlined]' % 1144 funcs[i] if frame.IsInlined() else funcs[i], 1145 file=files[i], 1146 line=lines[i], 1147 args=get_args_as_string( 1148 frame, 1149 showFuncName=False) if not frame.IsInlined() else '()'), 1150 file=output) 1151 1152 if string_buffer: 1153 return output.getvalue() 1154 1155 1156def print_stacktraces(process, string_buffer=False): 1157 """Prints the stack traces of all the threads.""" 1158 1159 output = SixStringIO() if string_buffer else sys.stdout 1160 1161 print("Stack traces for " + str(process), file=output) 1162 1163 for thread in process: 1164 print(print_stacktrace(thread, string_buffer=True), file=output) 1165 1166 if string_buffer: 1167 return output.getvalue() 1168 1169 1170def expect_state_changes(test, listener, process, states, timeout=30): 1171 """Listens for state changed events on the listener and makes sure they match what we 1172 expect. Stop-and-restart events (where GetRestartedFromEvent() returns true) are ignored.""" 1173 1174 for expected_state in states: 1175 def get_next_event(): 1176 event = lldb.SBEvent() 1177 if not listener.WaitForEventForBroadcasterWithType( 1178 timeout, 1179 process.GetBroadcaster(), 1180 lldb.SBProcess.eBroadcastBitStateChanged, 1181 event): 1182 test.fail( 1183 "Timed out while waiting for a transition to state %s" % 1184 lldb.SBDebugger.StateAsCString(expected_state)) 1185 return event 1186 1187 event = get_next_event() 1188 while (lldb.SBProcess.GetStateFromEvent(event) == lldb.eStateStopped and 1189 lldb.SBProcess.GetRestartedFromEvent(event)): 1190 # Ignore restarted event and the subsequent running event. 1191 event = get_next_event() 1192 test.assertEqual( 1193 lldb.SBProcess.GetStateFromEvent(event), 1194 lldb.eStateRunning, 1195 "Restarted event followed by a running event") 1196 event = get_next_event() 1197 1198 test.assertEqual( 1199 lldb.SBProcess.GetStateFromEvent(event), 1200 expected_state) 1201 1202# =================================== 1203# Utility functions related to Frames 1204# =================================== 1205 1206 1207def get_parent_frame(frame): 1208 """ 1209 Returns the parent frame of the input frame object; None if not available. 1210 """ 1211 thread = frame.GetThread() 1212 parent_found = False 1213 for f in thread: 1214 if parent_found: 1215 return f 1216 if f.GetFrameID() == frame.GetFrameID(): 1217 parent_found = True 1218 1219 # If we reach here, no parent has been found, return None. 1220 return None 1221 1222 1223def get_args_as_string(frame, showFuncName=True): 1224 """ 1225 Returns the args of the input frame object as a string. 1226 """ 1227 # arguments => True 1228 # locals => False 1229 # statics => False 1230 # in_scope_only => True 1231 vars = frame.GetVariables(True, False, False, True) # type of SBValueList 1232 args = [] # list of strings 1233 for var in vars: 1234 args.append("(%s)%s=%s" % (var.GetTypeName(), 1235 var.GetName(), 1236 var.GetValue())) 1237 if frame.GetFunction(): 1238 name = frame.GetFunction().GetName() 1239 elif frame.GetSymbol(): 1240 name = frame.GetSymbol().GetName() 1241 else: 1242 name = "" 1243 if showFuncName: 1244 return "%s(%s)" % (name, ", ".join(args)) 1245 else: 1246 return "(%s)" % (", ".join(args)) 1247 1248 1249def print_registers(frame, string_buffer=False): 1250 """Prints all the register sets of the frame.""" 1251 1252 output = SixStringIO() if string_buffer else sys.stdout 1253 1254 print("Register sets for " + str(frame), file=output) 1255 1256 registerSet = frame.GetRegisters() # Return type of SBValueList. 1257 print("Frame registers (size of register set = %d):" % 1258 registerSet.GetSize(), file=output) 1259 for value in registerSet: 1260 #print(value, file=output) 1261 print("%s (number of children = %d):" % 1262 (value.GetName(), value.GetNumChildren()), file=output) 1263 for child in value: 1264 print( 1265 "Name: %s, Value: %s" % 1266 (child.GetName(), 1267 child.GetValue()), 1268 file=output) 1269 1270 if string_buffer: 1271 return output.getvalue() 1272 1273 1274def get_registers(frame, kind): 1275 """Returns the registers given the frame and the kind of registers desired. 1276 1277 Returns None if there's no such kind. 1278 """ 1279 registerSet = frame.GetRegisters() # Return type of SBValueList. 1280 for value in registerSet: 1281 if kind.lower() in value.GetName().lower(): 1282 return value 1283 1284 return None 1285 1286 1287def get_GPRs(frame): 1288 """Returns the general purpose registers of the frame as an SBValue. 1289 1290 The returned SBValue object is iterable. An example: 1291 ... 1292 from lldbutil import get_GPRs 1293 regs = get_GPRs(frame) 1294 for reg in regs: 1295 print("%s => %s" % (reg.GetName(), reg.GetValue())) 1296 ... 1297 """ 1298 return get_registers(frame, "general purpose") 1299 1300 1301def get_FPRs(frame): 1302 """Returns the floating point registers of the frame as an SBValue. 1303 1304 The returned SBValue object is iterable. An example: 1305 ... 1306 from lldbutil import get_FPRs 1307 regs = get_FPRs(frame) 1308 for reg in regs: 1309 print("%s => %s" % (reg.GetName(), reg.GetValue())) 1310 ... 1311 """ 1312 return get_registers(frame, "floating point") 1313 1314 1315def get_ESRs(frame): 1316 """Returns the exception state registers of the frame as an SBValue. 1317 1318 The returned SBValue object is iterable. An example: 1319 ... 1320 from lldbutil import get_ESRs 1321 regs = get_ESRs(frame) 1322 for reg in regs: 1323 print("%s => %s" % (reg.GetName(), reg.GetValue())) 1324 ... 1325 """ 1326 return get_registers(frame, "exception state") 1327 1328# ====================================== 1329# Utility classes/functions for SBValues 1330# ====================================== 1331 1332 1333class BasicFormatter(object): 1334 """The basic formatter inspects the value object and prints the value.""" 1335 1336 def format(self, value, buffer=None, indent=0): 1337 if not buffer: 1338 output = SixStringIO() 1339 else: 1340 output = buffer 1341 # If there is a summary, it suffices. 1342 val = value.GetSummary() 1343 # Otherwise, get the value. 1344 if val is None: 1345 val = value.GetValue() 1346 if val is None and value.GetNumChildren() > 0: 1347 val = "%s (location)" % value.GetLocation() 1348 print("{indentation}({type}) {name} = {value}".format( 1349 indentation=' ' * indent, 1350 type=value.GetTypeName(), 1351 name=value.GetName(), 1352 value=val), file=output) 1353 return output.getvalue() 1354 1355 1356class ChildVisitingFormatter(BasicFormatter): 1357 """The child visiting formatter prints the value and its immediate children. 1358 1359 The constructor takes a keyword arg: indent_child, which defaults to 2. 1360 """ 1361 1362 def __init__(self, indent_child=2): 1363 """Default indentation of 2 SPC's for the children.""" 1364 self.cindent = indent_child 1365 1366 def format(self, value, buffer=None): 1367 if not buffer: 1368 output = SixStringIO() 1369 else: 1370 output = buffer 1371 1372 BasicFormatter.format(self, value, buffer=output) 1373 for child in value: 1374 BasicFormatter.format( 1375 self, child, buffer=output, indent=self.cindent) 1376 1377 return output.getvalue() 1378 1379 1380class RecursiveDecentFormatter(BasicFormatter): 1381 """The recursive decent formatter prints the value and the decendents. 1382 1383 The constructor takes two keyword args: indent_level, which defaults to 0, 1384 and indent_child, which defaults to 2. The current indentation level is 1385 determined by indent_level, while the immediate children has an additional 1386 indentation by inden_child. 1387 """ 1388 1389 def __init__(self, indent_level=0, indent_child=2): 1390 self.lindent = indent_level 1391 self.cindent = indent_child 1392 1393 def format(self, value, buffer=None): 1394 if not buffer: 1395 output = SixStringIO() 1396 else: 1397 output = buffer 1398 1399 BasicFormatter.format(self, value, buffer=output, indent=self.lindent) 1400 new_indent = self.lindent + self.cindent 1401 for child in value: 1402 if child.GetSummary() is not None: 1403 BasicFormatter.format( 1404 self, child, buffer=output, indent=new_indent) 1405 else: 1406 if child.GetNumChildren() > 0: 1407 rdf = RecursiveDecentFormatter(indent_level=new_indent) 1408 rdf.format(child, buffer=output) 1409 else: 1410 BasicFormatter.format( 1411 self, child, buffer=output, indent=new_indent) 1412 1413 return output.getvalue() 1414 1415# =========================================================== 1416# Utility functions for path manipulation on remote platforms 1417# =========================================================== 1418 1419 1420def join_remote_paths(*paths): 1421 # TODO: update with actual platform name for remote windows once it exists 1422 if lldb.remote_platform.GetName() == 'remote-windows': 1423 return os.path.join(*paths).replace(os.path.sep, '\\') 1424 return os.path.join(*paths).replace(os.path.sep, '/') 1425 1426 1427def append_to_process_working_directory(test, *paths): 1428 remote = lldb.remote_platform 1429 if remote: 1430 return join_remote_paths(remote.GetWorkingDirectory(), *paths) 1431 return os.path.join(test.getBuildDir(), *paths) 1432 1433# ================================================== 1434# Utility functions to get the correct signal number 1435# ================================================== 1436 1437import signal 1438 1439 1440def get_signal_number(signal_name): 1441 platform = lldb.remote_platform 1442 if platform and platform.IsValid(): 1443 signals = platform.GetUnixSignals() 1444 if signals.IsValid(): 1445 signal_number = signals.GetSignalNumberFromName(signal_name) 1446 if signal_number > 0: 1447 return signal_number 1448 # No remote platform; fall back to using local python signals. 1449 return getattr(signal, signal_name) 1450 1451 1452class PrintableRegex(object): 1453 1454 def __init__(self, text): 1455 self.regex = re.compile(text) 1456 self.text = text 1457 1458 def match(self, str): 1459 return self.regex.match(str) 1460 1461 def __str__(self): 1462 return "%s" % (self.text) 1463 1464 def __repr__(self): 1465 return "re.compile(%s) -> %s" % (self.text, self.regex) 1466 1467 1468def skip_if_callable(test, mycallable, reason): 1469 if six.callable(mycallable): 1470 if mycallable(test): 1471 test.skipTest(reason) 1472 return True 1473 return False 1474 1475 1476def skip_if_library_missing(test, target, library): 1477 def find_library(target, library): 1478 for module in target.modules: 1479 filename = module.file.GetFilename() 1480 if isinstance(library, str): 1481 if library == filename: 1482 return False 1483 elif hasattr(library, 'match'): 1484 if library.match(filename): 1485 return False 1486 return True 1487 1488 def find_library_callable(test): 1489 return find_library(target, library) 1490 return skip_if_callable( 1491 test, 1492 find_library_callable, 1493 "could not find library matching '%s' in target %s" % 1494 (library, 1495 target)) 1496 1497 1498def read_file_on_target(test, remote): 1499 if lldb.remote_platform: 1500 local = test.getBuildArtifact("file_from_target") 1501 error = lldb.remote_platform.Get(lldb.SBFileSpec(remote, False), 1502 lldb.SBFileSpec(local, True)) 1503 test.assertTrue(error.Success(), "Reading file {0} failed: {1}".format(remote, error)) 1504 else: 1505 local = remote 1506 with open(local, 'r') as f: 1507 return f.read() 1508 1509def read_file_from_process_wd(test, name): 1510 path = append_to_process_working_directory(test, name) 1511 return read_file_on_target(test, path) 1512 1513def wait_for_file_on_target(testcase, file_path, max_attempts=6): 1514 for i in range(max_attempts): 1515 err, retcode, msg = testcase.run_platform_command("ls %s" % file_path) 1516 if err.Success() and retcode == 0: 1517 break 1518 if i < max_attempts: 1519 # Exponential backoff! 1520 import time 1521 time.sleep(pow(2, i) * 0.25) 1522 else: 1523 testcase.fail( 1524 "File %s not found even after %d attempts." % 1525 (file_path, max_attempts)) 1526 1527 return read_file_on_target(testcase, file_path) 1528 1529def packetlog_get_process_info(log): 1530 """parse a gdb-remote packet log file and extract the response to qProcessInfo""" 1531 process_info = dict() 1532 with open(log, "r") as logfile: 1533 process_info_ostype = None 1534 expect_process_info_response = False 1535 for line in logfile: 1536 if expect_process_info_response: 1537 for pair in line.split(';'): 1538 keyval = pair.split(':') 1539 if len(keyval) == 2: 1540 process_info[keyval[0]] = keyval[1] 1541 break 1542 if 'send packet: $qProcessInfo#' in line: 1543 expect_process_info_response = True 1544 return process_info 1545 1546def packetlog_get_dylib_info(log): 1547 """parse a gdb-remote packet log file and extract the *last* complete 1548 (=> fetch_all_solibs=true) response to jGetLoadedDynamicLibrariesInfos""" 1549 import json 1550 dylib_info = None 1551 with open(log, "r") as logfile: 1552 dylib_info = None 1553 expect_dylib_info_response = False 1554 for line in logfile: 1555 if expect_dylib_info_response: 1556 while line[0] != '$': 1557 line = line[1:] 1558 line = line[1:] 1559 # Unescape '}'. 1560 dylib_info = json.loads(line.replace('}]','}')[:-4]) 1561 expect_dylib_info_response = False 1562 if 'send packet: $jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}' in line: 1563 expect_dylib_info_response = True 1564 1565 return dylib_info 1566