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