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