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