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 """Start up a target, using exe_name as the executable, and run it to 958 a breakpoint set by source regex bkpt_pattern. 959 960 The rest of the behavior is the same as run_to_name_breakpoint. 961 """ 962 963 target = run_to_breakpoint_make_target(test, exe_name, in_cwd) 964 # Set the breakpoints 965 breakpoint = target.BreakpointCreateBySourceRegex( 966 bkpt_pattern, source_spec, bkpt_module) 967 test.assertTrue(breakpoint.GetNumLocations() > 0, 968 'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"' 969 %(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory())) 970 return run_to_breakpoint_do_run(test, target, breakpoint, launch_info, 971 only_one_thread, extra_images) 972 973def run_to_line_breakpoint(test, source_spec, line_number, column = 0, 974 launch_info = None, exe_name = "a.out", 975 bkpt_module = None, 976 in_cwd = True, 977 only_one_thread = True, 978 extra_images = None): 979 """Start up a target, using exe_name as the executable, and run it to 980 a breakpoint set by (source_spec, line_number(, column)). 981 982 The rest of the behavior is the same as run_to_name_breakpoint. 983 """ 984 985 target = run_to_breakpoint_make_target(test, exe_name, in_cwd) 986 # Set the breakpoints 987 breakpoint = target.BreakpointCreateByLocation( 988 source_spec, line_number, column, 0, lldb.SBFileSpecList()) 989 test.assertTrue(breakpoint.GetNumLocations() > 0, 990 'No locations found for line breakpoint: "%s:%d(:%d)", dir: "%s"' 991 %(source_spec.GetFilename(), line_number, column, 992 source_spec.GetDirectory())) 993 return run_to_breakpoint_do_run(test, target, breakpoint, launch_info, 994 only_one_thread, extra_images) 995 996 997def continue_to_breakpoint(process, bkpt): 998 """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None""" 999 process.Continue() 1000 if process.GetState() != lldb.eStateStopped: 1001 return None 1002 else: 1003 return get_threads_stopped_at_breakpoint(process, bkpt) 1004 1005 1006def get_caller_symbol(thread): 1007 """ 1008 Returns the symbol name for the call site of the leaf function. 1009 """ 1010 depth = thread.GetNumFrames() 1011 if depth <= 1: 1012 return None 1013 caller = thread.GetFrameAtIndex(1).GetSymbol() 1014 if caller: 1015 return caller.GetName() 1016 else: 1017 return None 1018 1019 1020def get_function_names(thread): 1021 """ 1022 Returns a sequence of function names from the stack frames of this thread. 1023 """ 1024 def GetFuncName(i): 1025 return thread.GetFrameAtIndex(i).GetFunctionName() 1026 1027 return list(map(GetFuncName, list(range(thread.GetNumFrames())))) 1028 1029 1030def get_symbol_names(thread): 1031 """ 1032 Returns a sequence of symbols for this thread. 1033 """ 1034 def GetSymbol(i): 1035 return thread.GetFrameAtIndex(i).GetSymbol().GetName() 1036 1037 return list(map(GetSymbol, list(range(thread.GetNumFrames())))) 1038 1039 1040def get_pc_addresses(thread): 1041 """ 1042 Returns a sequence of pc addresses for this thread. 1043 """ 1044 def GetPCAddress(i): 1045 return thread.GetFrameAtIndex(i).GetPCAddress() 1046 1047 return list(map(GetPCAddress, list(range(thread.GetNumFrames())))) 1048 1049 1050def get_filenames(thread): 1051 """ 1052 Returns a sequence of file names from the stack frames of this thread. 1053 """ 1054 def GetFilename(i): 1055 return thread.GetFrameAtIndex( 1056 i).GetLineEntry().GetFileSpec().GetFilename() 1057 1058 return list(map(GetFilename, list(range(thread.GetNumFrames())))) 1059 1060 1061def get_line_numbers(thread): 1062 """ 1063 Returns a sequence of line numbers from the stack frames of this thread. 1064 """ 1065 def GetLineNumber(i): 1066 return thread.GetFrameAtIndex(i).GetLineEntry().GetLine() 1067 1068 return list(map(GetLineNumber, list(range(thread.GetNumFrames())))) 1069 1070 1071def get_module_names(thread): 1072 """ 1073 Returns a sequence of module names from the stack frames of this thread. 1074 """ 1075 def GetModuleName(i): 1076 return thread.GetFrameAtIndex( 1077 i).GetModule().GetFileSpec().GetFilename() 1078 1079 return list(map(GetModuleName, list(range(thread.GetNumFrames())))) 1080 1081 1082def get_stack_frames(thread): 1083 """ 1084 Returns a sequence of stack frames for this thread. 1085 """ 1086 def GetStackFrame(i): 1087 return thread.GetFrameAtIndex(i) 1088 1089 return list(map(GetStackFrame, list(range(thread.GetNumFrames())))) 1090 1091 1092def print_stacktrace(thread, string_buffer=False): 1093 """Prints a simple stack trace of this thread.""" 1094 1095 output = SixStringIO() if string_buffer else sys.stdout 1096 target = thread.GetProcess().GetTarget() 1097 1098 depth = thread.GetNumFrames() 1099 1100 mods = get_module_names(thread) 1101 funcs = get_function_names(thread) 1102 symbols = get_symbol_names(thread) 1103 files = get_filenames(thread) 1104 lines = get_line_numbers(thread) 1105 addrs = get_pc_addresses(thread) 1106 1107 if thread.GetStopReason() != lldb.eStopReasonInvalid: 1108 desc = "stop reason=" + stop_reason_to_str(thread.GetStopReason()) 1109 else: 1110 desc = "" 1111 print( 1112 "Stack trace for thread id={0:#x} name={1} queue={2} ".format( 1113 thread.GetThreadID(), 1114 thread.GetName(), 1115 thread.GetQueueName()) + desc, 1116 file=output) 1117 1118 for i in range(depth): 1119 frame = thread.GetFrameAtIndex(i) 1120 function = frame.GetFunction() 1121 1122 load_addr = addrs[i].GetLoadAddress(target) 1123 if not function: 1124 file_addr = addrs[i].GetFileAddress() 1125 start_addr = frame.GetSymbol().GetStartAddress().GetFileAddress() 1126 symbol_offset = file_addr - start_addr 1127 print( 1128 " frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format( 1129 num=i, 1130 addr=load_addr, 1131 mod=mods[i], 1132 symbol=symbols[i], 1133 offset=symbol_offset), 1134 file=output) 1135 else: 1136 print( 1137 " frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format( 1138 num=i, 1139 addr=load_addr, 1140 mod=mods[i], 1141 func='%s [inlined]' % 1142 funcs[i] if frame.IsInlined() else funcs[i], 1143 file=files[i], 1144 line=lines[i], 1145 args=get_args_as_string( 1146 frame, 1147 showFuncName=False) if not frame.IsInlined() else '()'), 1148 file=output) 1149 1150 if string_buffer: 1151 return output.getvalue() 1152 1153 1154def print_stacktraces(process, string_buffer=False): 1155 """Prints the stack traces of all the threads.""" 1156 1157 output = SixStringIO() if string_buffer else sys.stdout 1158 1159 print("Stack traces for " + str(process), file=output) 1160 1161 for thread in process: 1162 print(print_stacktrace(thread, string_buffer=True), file=output) 1163 1164 if string_buffer: 1165 return output.getvalue() 1166 1167 1168def expect_state_changes(test, listener, process, states, timeout=30): 1169 """Listens for state changed events on the listener and makes sure they match what we 1170 expect. Stop-and-restart events (where GetRestartedFromEvent() returns true) are ignored.""" 1171 1172 for expected_state in states: 1173 def get_next_event(): 1174 event = lldb.SBEvent() 1175 if not listener.WaitForEventForBroadcasterWithType( 1176 timeout, 1177 process.GetBroadcaster(), 1178 lldb.SBProcess.eBroadcastBitStateChanged, 1179 event): 1180 test.fail( 1181 "Timed out while waiting for a transition to state %s" % 1182 lldb.SBDebugger.StateAsCString(expected_state)) 1183 return event 1184 1185 event = get_next_event() 1186 while (lldb.SBProcess.GetStateFromEvent(event) == lldb.eStateStopped and 1187 lldb.SBProcess.GetRestartedFromEvent(event)): 1188 # Ignore restarted event and the subsequent running event. 1189 event = get_next_event() 1190 test.assertEqual( 1191 lldb.SBProcess.GetStateFromEvent(event), 1192 lldb.eStateRunning, 1193 "Restarted event followed by a running event") 1194 event = get_next_event() 1195 1196 test.assertEqual( 1197 lldb.SBProcess.GetStateFromEvent(event), 1198 expected_state) 1199 1200# =================================== 1201# Utility functions related to Frames 1202# =================================== 1203 1204 1205def get_parent_frame(frame): 1206 """ 1207 Returns the parent frame of the input frame object; None if not available. 1208 """ 1209 thread = frame.GetThread() 1210 parent_found = False 1211 for f in thread: 1212 if parent_found: 1213 return f 1214 if f.GetFrameID() == frame.GetFrameID(): 1215 parent_found = True 1216 1217 # If we reach here, no parent has been found, return None. 1218 return None 1219 1220 1221def get_args_as_string(frame, showFuncName=True): 1222 """ 1223 Returns the args of the input frame object as a string. 1224 """ 1225 # arguments => True 1226 # locals => False 1227 # statics => False 1228 # in_scope_only => True 1229 vars = frame.GetVariables(True, False, False, True) # type of SBValueList 1230 args = [] # list of strings 1231 for var in vars: 1232 args.append("(%s)%s=%s" % (var.GetTypeName(), 1233 var.GetName(), 1234 var.GetValue())) 1235 if frame.GetFunction(): 1236 name = frame.GetFunction().GetName() 1237 elif frame.GetSymbol(): 1238 name = frame.GetSymbol().GetName() 1239 else: 1240 name = "" 1241 if showFuncName: 1242 return "%s(%s)" % (name, ", ".join(args)) 1243 else: 1244 return "(%s)" % (", ".join(args)) 1245 1246 1247def print_registers(frame, string_buffer=False): 1248 """Prints all the register sets of the frame.""" 1249 1250 output = SixStringIO() if string_buffer else sys.stdout 1251 1252 print("Register sets for " + str(frame), file=output) 1253 1254 registerSet = frame.GetRegisters() # Return type of SBValueList. 1255 print("Frame registers (size of register set = %d):" % 1256 registerSet.GetSize(), file=output) 1257 for value in registerSet: 1258 #print(value, file=output) 1259 print("%s (number of children = %d):" % 1260 (value.GetName(), value.GetNumChildren()), file=output) 1261 for child in value: 1262 print( 1263 "Name: %s, Value: %s" % 1264 (child.GetName(), 1265 child.GetValue()), 1266 file=output) 1267 1268 if string_buffer: 1269 return output.getvalue() 1270 1271 1272def get_registers(frame, kind): 1273 """Returns the registers given the frame and the kind of registers desired. 1274 1275 Returns None if there's no such kind. 1276 """ 1277 registerSet = frame.GetRegisters() # Return type of SBValueList. 1278 for value in registerSet: 1279 if kind.lower() in value.GetName().lower(): 1280 return value 1281 1282 return None 1283 1284 1285def get_GPRs(frame): 1286 """Returns the general purpose registers of the frame as an SBValue. 1287 1288 The returned SBValue object is iterable. An example: 1289 ... 1290 from lldbutil import get_GPRs 1291 regs = get_GPRs(frame) 1292 for reg in regs: 1293 print("%s => %s" % (reg.GetName(), reg.GetValue())) 1294 ... 1295 """ 1296 return get_registers(frame, "general purpose") 1297 1298 1299def get_FPRs(frame): 1300 """Returns the floating point registers of the frame as an SBValue. 1301 1302 The returned SBValue object is iterable. An example: 1303 ... 1304 from lldbutil import get_FPRs 1305 regs = get_FPRs(frame) 1306 for reg in regs: 1307 print("%s => %s" % (reg.GetName(), reg.GetValue())) 1308 ... 1309 """ 1310 return get_registers(frame, "floating point") 1311 1312 1313def get_ESRs(frame): 1314 """Returns the exception state registers of the frame as an SBValue. 1315 1316 The returned SBValue object is iterable. An example: 1317 ... 1318 from lldbutil import get_ESRs 1319 regs = get_ESRs(frame) 1320 for reg in regs: 1321 print("%s => %s" % (reg.GetName(), reg.GetValue())) 1322 ... 1323 """ 1324 return get_registers(frame, "exception state") 1325 1326# ====================================== 1327# Utility classes/functions for SBValues 1328# ====================================== 1329 1330 1331class BasicFormatter(object): 1332 """The basic formatter inspects the value object and prints the value.""" 1333 1334 def format(self, value, buffer=None, indent=0): 1335 if not buffer: 1336 output = SixStringIO() 1337 else: 1338 output = buffer 1339 # If there is a summary, it suffices. 1340 val = value.GetSummary() 1341 # Otherwise, get the value. 1342 if val is None: 1343 val = value.GetValue() 1344 if val is None and value.GetNumChildren() > 0: 1345 val = "%s (location)" % value.GetLocation() 1346 print("{indentation}({type}) {name} = {value}".format( 1347 indentation=' ' * indent, 1348 type=value.GetTypeName(), 1349 name=value.GetName(), 1350 value=val), file=output) 1351 return output.getvalue() 1352 1353 1354class ChildVisitingFormatter(BasicFormatter): 1355 """The child visiting formatter prints the value and its immediate children. 1356 1357 The constructor takes a keyword arg: indent_child, which defaults to 2. 1358 """ 1359 1360 def __init__(self, indent_child=2): 1361 """Default indentation of 2 SPC's for the children.""" 1362 self.cindent = indent_child 1363 1364 def format(self, value, buffer=None): 1365 if not buffer: 1366 output = SixStringIO() 1367 else: 1368 output = buffer 1369 1370 BasicFormatter.format(self, value, buffer=output) 1371 for child in value: 1372 BasicFormatter.format( 1373 self, child, buffer=output, indent=self.cindent) 1374 1375 return output.getvalue() 1376 1377 1378class RecursiveDecentFormatter(BasicFormatter): 1379 """The recursive decent formatter prints the value and the decendents. 1380 1381 The constructor takes two keyword args: indent_level, which defaults to 0, 1382 and indent_child, which defaults to 2. The current indentation level is 1383 determined by indent_level, while the immediate children has an additional 1384 indentation by inden_child. 1385 """ 1386 1387 def __init__(self, indent_level=0, indent_child=2): 1388 self.lindent = indent_level 1389 self.cindent = indent_child 1390 1391 def format(self, value, buffer=None): 1392 if not buffer: 1393 output = SixStringIO() 1394 else: 1395 output = buffer 1396 1397 BasicFormatter.format(self, value, buffer=output, indent=self.lindent) 1398 new_indent = self.lindent + self.cindent 1399 for child in value: 1400 if child.GetSummary() is not None: 1401 BasicFormatter.format( 1402 self, child, buffer=output, indent=new_indent) 1403 else: 1404 if child.GetNumChildren() > 0: 1405 rdf = RecursiveDecentFormatter(indent_level=new_indent) 1406 rdf.format(child, buffer=output) 1407 else: 1408 BasicFormatter.format( 1409 self, child, buffer=output, indent=new_indent) 1410 1411 return output.getvalue() 1412 1413# =========================================================== 1414# Utility functions for path manipulation on remote platforms 1415# =========================================================== 1416 1417 1418def join_remote_paths(*paths): 1419 # TODO: update with actual platform name for remote windows once it exists 1420 if lldb.remote_platform.GetName() == 'remote-windows': 1421 return os.path.join(*paths).replace(os.path.sep, '\\') 1422 return os.path.join(*paths).replace(os.path.sep, '/') 1423 1424 1425def append_to_process_working_directory(test, *paths): 1426 remote = lldb.remote_platform 1427 if remote: 1428 return join_remote_paths(remote.GetWorkingDirectory(), *paths) 1429 return os.path.join(test.getBuildDir(), *paths) 1430 1431# ================================================== 1432# Utility functions to get the correct signal number 1433# ================================================== 1434 1435import signal 1436 1437 1438def get_signal_number(signal_name): 1439 platform = lldb.remote_platform 1440 if platform and platform.IsValid(): 1441 signals = platform.GetUnixSignals() 1442 if signals.IsValid(): 1443 signal_number = signals.GetSignalNumberFromName(signal_name) 1444 if signal_number > 0: 1445 return signal_number 1446 # No remote platform; fall back to using local python signals. 1447 return getattr(signal, signal_name) 1448 1449 1450class PrintableRegex(object): 1451 1452 def __init__(self, text): 1453 self.regex = re.compile(text) 1454 self.text = text 1455 1456 def match(self, str): 1457 return self.regex.match(str) 1458 1459 def __str__(self): 1460 return "%s" % (self.text) 1461 1462 def __repr__(self): 1463 return "re.compile(%s) -> %s" % (self.text, self.regex) 1464 1465 1466def skip_if_callable(test, mycallable, reason): 1467 if six.callable(mycallable): 1468 if mycallable(test): 1469 test.skipTest(reason) 1470 return True 1471 return False 1472 1473 1474def skip_if_library_missing(test, target, library): 1475 def find_library(target, library): 1476 for module in target.modules: 1477 filename = module.file.GetFilename() 1478 if isinstance(library, str): 1479 if library == filename: 1480 return False 1481 elif hasattr(library, 'match'): 1482 if library.match(filename): 1483 return False 1484 return True 1485 1486 def find_library_callable(test): 1487 return find_library(target, library) 1488 return skip_if_callable( 1489 test, 1490 find_library_callable, 1491 "could not find library matching '%s' in target %s" % 1492 (library, 1493 target)) 1494 1495 1496def read_file_on_target(test, remote): 1497 if lldb.remote_platform: 1498 local = test.getBuildArtifact("file_from_target") 1499 error = lldb.remote_platform.Get(lldb.SBFileSpec(remote, False), 1500 lldb.SBFileSpec(local, True)) 1501 test.assertTrue(error.Success(), "Reading file {0} failed: {1}".format(remote, error)) 1502 else: 1503 local = remote 1504 with open(local, 'r') as f: 1505 return f.read() 1506 1507def read_file_from_process_wd(test, name): 1508 path = append_to_process_working_directory(test, name) 1509 return read_file_on_target(test, path) 1510 1511def wait_for_file_on_target(testcase, file_path, max_attempts=6): 1512 for i in range(max_attempts): 1513 err, retcode, msg = testcase.run_platform_command("ls %s" % file_path) 1514 if err.Success() and retcode == 0: 1515 break 1516 if i < max_attempts: 1517 # Exponential backoff! 1518 import time 1519 time.sleep(pow(2, i) * 0.25) 1520 else: 1521 testcase.fail( 1522 "File %s not found even after %d attempts." % 1523 (file_path, max_attempts)) 1524 1525 return read_file_on_target(testcase, file_path) 1526 1527def packetlog_get_process_info(log): 1528 """parse a gdb-remote packet log file and extract the response to qProcessInfo""" 1529 process_info = dict() 1530 with open(log, "r") as logfile: 1531 process_info_ostype = None 1532 expect_process_info_response = False 1533 for line in logfile: 1534 if expect_process_info_response: 1535 for pair in line.split(';'): 1536 keyval = pair.split(':') 1537 if len(keyval) == 2: 1538 process_info[keyval[0]] = keyval[1] 1539 break 1540 if 'send packet: $qProcessInfo#' in line: 1541 expect_process_info_response = True 1542 return process_info 1543 1544def packetlog_get_dylib_info(log): 1545 """parse a gdb-remote packet log file and extract the *last* complete 1546 (=> fetch_all_solibs=true) response to jGetLoadedDynamicLibrariesInfos""" 1547 import json 1548 dylib_info = None 1549 with open(log, "r") as logfile: 1550 dylib_info = None 1551 expect_dylib_info_response = False 1552 for line in logfile: 1553 if expect_dylib_info_response: 1554 while line[0] != '$': 1555 line = line[1:] 1556 line = line[1:] 1557 # Unescape '}'. 1558 dylib_info = json.loads(line.replace('}]','}')[:-4]) 1559 expect_dylib_info_response = False 1560 if 'send packet: $jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}' in line: 1561 expect_dylib_info_response = True 1562 1563 return dylib_info 1564