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