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