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