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 else: 740 return "invalid address" in thread.GetStopDescription(100) 741 742 743def get_crashed_threads(test, process): 744 threads = [] 745 if process.GetState() != lldb.eStateStopped: 746 return threads 747 for thread in process: 748 if is_thread_crashed(test, thread): 749 threads.append(thread) 750 return threads 751 752# Helper functions for run_to_{source,name}_breakpoint: 753 754def run_to_breakpoint_make_target(test, exe_name = "a.out", in_cwd = True): 755 if in_cwd: 756 exe = test.getBuildArtifact(exe_name) 757 758 # Create the target 759 target = test.dbg.CreateTarget(exe) 760 test.assertTrue(target, "Target: %s is not valid."%(exe_name)) 761 return target 762 763def run_to_breakpoint_do_run(test, target, bkpt, launch_info = None): 764 765 # Launch the process, and do not stop at the entry point. 766 if not launch_info: 767 launch_info = lldb.SBLaunchInfo(None) 768 launch_info.SetWorkingDirectory(test.get_process_working_directory()) 769 770 error = lldb.SBError() 771 process = target.Launch(launch_info, error) 772 773 test.assertTrue(process, 774 "Could not create a valid process for %s: %s"%(target.GetExecutable().GetFilename(), 775 error.GetCString())) 776 777 # Frame #0 should be at our breakpoint. 778 threads = get_threads_stopped_at_breakpoint( 779 process, bkpt) 780 781 test.assertTrue(len(threads) == 1, "Expected 1 thread to stop at breakpoint, %d did."%(len(threads))) 782 thread = threads[0] 783 return (target, process, thread, bkpt) 784 785def run_to_name_breakpoint (test, bkpt_name, launch_info = None, 786 exe_name = "a.out", 787 bkpt_module = None, 788 in_cwd = True): 789 """Start up a target, using exe_name as the executable, and run it to 790 a breakpoint set by name on bkpt_name restricted to bkpt_module. 791 792 If you want to pass in launch arguments or environment 793 variables, you can optionally pass in an SBLaunchInfo. If you 794 do that, remember to set the working directory as well. 795 796 If your executable isn't called a.out, you can pass that in. 797 And if your executable isn't in the CWD, pass in the absolute 798 path to the executable in exe_name, and set in_cwd to False. 799 800 If you need to restrict the breakpoint to a particular module, 801 pass the module name (a string not a FileSpec) in bkpt_module. If 802 nothing is passed in setting will be unrestricted. 803 804 If the target isn't valid, the breakpoint isn't found, or hit, the 805 function will cause a testsuite failure. 806 807 If successful it returns a tuple with the target process and 808 thread that hit the breakpoint, and the breakpoint that we set 809 for you. 810 """ 811 812 target = run_to_breakpoint_make_target(test, exe_name, in_cwd) 813 814 breakpoint = target.BreakpointCreateByName(bkpt_name, bkpt_module) 815 816 817 test.assertTrue(breakpoint.GetNumLocations() > 0, 818 "No locations found for name breakpoint: '%s'."%(bkpt_name)) 819 return run_to_breakpoint_do_run(test, target, breakpoint, launch_info) 820 821def run_to_source_breakpoint(test, bkpt_pattern, source_spec, 822 launch_info = None, exe_name = "a.out", 823 bkpt_module = None, 824 in_cwd = True): 825 """Start up a target, using exe_name as the executable, and run it to 826 a breakpoint set by source regex bkpt_pattern. 827 828 The rest of the behavior is the same as run_to_name_breakpoint. 829 """ 830 831 target = run_to_breakpoint_make_target(test, exe_name, in_cwd) 832 # Set the breakpoints 833 breakpoint = target.BreakpointCreateBySourceRegex( 834 bkpt_pattern, source_spec, bkpt_module) 835 test.assertTrue(breakpoint.GetNumLocations() > 0, 836 'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"' 837 %(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory())) 838 return run_to_breakpoint_do_run(test, target, breakpoint, launch_info) 839 840def run_to_line_breakpoint(test, source_spec, line_number, column = 0, 841 launch_info = None, exe_name = "a.out", 842 bkpt_module = None, 843 in_cwd = True): 844 """Start up a target, using exe_name as the executable, and run it to 845 a breakpoint set by (source_spec, line_number(, column)). 846 847 The rest of the behavior is the same as run_to_name_breakpoint. 848 """ 849 850 target = run_to_breakpoint_make_target(test, exe_name, in_cwd) 851 # Set the breakpoints 852 breakpoint = target.BreakpointCreateByLocation( 853 source_spec, line_number, column, 0, lldb.SBFileSpecList()) 854 test.assertTrue(breakpoint.GetNumLocations() > 0, 855 'No locations found for line breakpoint: "%s:%d(:%d)", dir: "%s"' 856 %(source_spec.GetFilename(), line_number, column, 857 source_spec.GetDirectory())) 858 return run_to_breakpoint_do_run(test, target, breakpoint, launch_info) 859 860 861def continue_to_breakpoint(process, bkpt): 862 """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None""" 863 process.Continue() 864 if process.GetState() != lldb.eStateStopped: 865 return None 866 else: 867 return get_threads_stopped_at_breakpoint(process, bkpt) 868 869 870def get_caller_symbol(thread): 871 """ 872 Returns the symbol name for the call site of the leaf function. 873 """ 874 depth = thread.GetNumFrames() 875 if depth <= 1: 876 return None 877 caller = thread.GetFrameAtIndex(1).GetSymbol() 878 if caller: 879 return caller.GetName() 880 else: 881 return None 882 883 884def get_function_names(thread): 885 """ 886 Returns a sequence of function names from the stack frames of this thread. 887 """ 888 def GetFuncName(i): 889 return thread.GetFrameAtIndex(i).GetFunctionName() 890 891 return list(map(GetFuncName, list(range(thread.GetNumFrames())))) 892 893 894def get_symbol_names(thread): 895 """ 896 Returns a sequence of symbols for this thread. 897 """ 898 def GetSymbol(i): 899 return thread.GetFrameAtIndex(i).GetSymbol().GetName() 900 901 return list(map(GetSymbol, list(range(thread.GetNumFrames())))) 902 903 904def get_pc_addresses(thread): 905 """ 906 Returns a sequence of pc addresses for this thread. 907 """ 908 def GetPCAddress(i): 909 return thread.GetFrameAtIndex(i).GetPCAddress() 910 911 return list(map(GetPCAddress, list(range(thread.GetNumFrames())))) 912 913 914def get_filenames(thread): 915 """ 916 Returns a sequence of file names from the stack frames of this thread. 917 """ 918 def GetFilename(i): 919 return thread.GetFrameAtIndex( 920 i).GetLineEntry().GetFileSpec().GetFilename() 921 922 return list(map(GetFilename, list(range(thread.GetNumFrames())))) 923 924 925def get_line_numbers(thread): 926 """ 927 Returns a sequence of line numbers from the stack frames of this thread. 928 """ 929 def GetLineNumber(i): 930 return thread.GetFrameAtIndex(i).GetLineEntry().GetLine() 931 932 return list(map(GetLineNumber, list(range(thread.GetNumFrames())))) 933 934 935def get_module_names(thread): 936 """ 937 Returns a sequence of module names from the stack frames of this thread. 938 """ 939 def GetModuleName(i): 940 return thread.GetFrameAtIndex( 941 i).GetModule().GetFileSpec().GetFilename() 942 943 return list(map(GetModuleName, list(range(thread.GetNumFrames())))) 944 945 946def get_stack_frames(thread): 947 """ 948 Returns a sequence of stack frames for this thread. 949 """ 950 def GetStackFrame(i): 951 return thread.GetFrameAtIndex(i) 952 953 return list(map(GetStackFrame, list(range(thread.GetNumFrames())))) 954 955 956def print_stacktrace(thread, string_buffer=False): 957 """Prints a simple stack trace of this thread.""" 958 959 output = SixStringIO() if string_buffer else sys.stdout 960 target = thread.GetProcess().GetTarget() 961 962 depth = thread.GetNumFrames() 963 964 mods = get_module_names(thread) 965 funcs = get_function_names(thread) 966 symbols = get_symbol_names(thread) 967 files = get_filenames(thread) 968 lines = get_line_numbers(thread) 969 addrs = get_pc_addresses(thread) 970 971 if thread.GetStopReason() != lldb.eStopReasonInvalid: 972 desc = "stop reason=" + stop_reason_to_str(thread.GetStopReason()) 973 else: 974 desc = "" 975 print( 976 "Stack trace for thread id={0:#x} name={1} queue={2} ".format( 977 thread.GetThreadID(), 978 thread.GetName(), 979 thread.GetQueueName()) + desc, 980 file=output) 981 982 for i in range(depth): 983 frame = thread.GetFrameAtIndex(i) 984 function = frame.GetFunction() 985 986 load_addr = addrs[i].GetLoadAddress(target) 987 if not function: 988 file_addr = addrs[i].GetFileAddress() 989 start_addr = frame.GetSymbol().GetStartAddress().GetFileAddress() 990 symbol_offset = file_addr - start_addr 991 print( 992 " frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format( 993 num=i, 994 addr=load_addr, 995 mod=mods[i], 996 symbol=symbols[i], 997 offset=symbol_offset), 998 file=output) 999 else: 1000 print( 1001 " frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format( 1002 num=i, 1003 addr=load_addr, 1004 mod=mods[i], 1005 func='%s [inlined]' % 1006 funcs[i] if frame.IsInlined() else funcs[i], 1007 file=files[i], 1008 line=lines[i], 1009 args=get_args_as_string( 1010 frame, 1011 showFuncName=False) if not frame.IsInlined() else '()'), 1012 file=output) 1013 1014 if string_buffer: 1015 return output.getvalue() 1016 1017 1018def print_stacktraces(process, string_buffer=False): 1019 """Prints the stack traces of all the threads.""" 1020 1021 output = SixStringIO() if string_buffer else sys.stdout 1022 1023 print("Stack traces for " + str(process), file=output) 1024 1025 for thread in process: 1026 print(print_stacktrace(thread, string_buffer=True), file=output) 1027 1028 if string_buffer: 1029 return output.getvalue() 1030 1031 1032def expect_state_changes(test, listener, process, states, timeout=5): 1033 """Listens for state changed events on the listener and makes sure they match what we 1034 expect. Stop-and-restart events (where GetRestartedFromEvent() returns true) are ignored.""" 1035 1036 for expected_state in states: 1037 def get_next_event(): 1038 event = lldb.SBEvent() 1039 if not listener.WaitForEventForBroadcasterWithType( 1040 timeout, 1041 process.GetBroadcaster(), 1042 lldb.SBProcess.eBroadcastBitStateChanged, 1043 event): 1044 test.fail( 1045 "Timed out while waiting for a transition to state %s" % 1046 lldb.SBDebugger.StateAsCString(expected_state)) 1047 return event 1048 1049 event = get_next_event() 1050 while (lldb.SBProcess.GetStateFromEvent(event) == lldb.eStateStopped and 1051 lldb.SBProcess.GetRestartedFromEvent(event)): 1052 # Ignore restarted event and the subsequent running event. 1053 event = get_next_event() 1054 test.assertEqual( 1055 lldb.SBProcess.GetStateFromEvent(event), 1056 lldb.eStateRunning, 1057 "Restarted event followed by a running event") 1058 event = get_next_event() 1059 1060 test.assertEqual( 1061 lldb.SBProcess.GetStateFromEvent(event), 1062 expected_state) 1063 1064# =================================== 1065# Utility functions related to Frames 1066# =================================== 1067 1068 1069def get_parent_frame(frame): 1070 """ 1071 Returns the parent frame of the input frame object; None if not available. 1072 """ 1073 thread = frame.GetThread() 1074 parent_found = False 1075 for f in thread: 1076 if parent_found: 1077 return f 1078 if f.GetFrameID() == frame.GetFrameID(): 1079 parent_found = True 1080 1081 # If we reach here, no parent has been found, return None. 1082 return None 1083 1084 1085def get_args_as_string(frame, showFuncName=True): 1086 """ 1087 Returns the args of the input frame object as a string. 1088 """ 1089 # arguments => True 1090 # locals => False 1091 # statics => False 1092 # in_scope_only => True 1093 vars = frame.GetVariables(True, False, False, True) # type of SBValueList 1094 args = [] # list of strings 1095 for var in vars: 1096 args.append("(%s)%s=%s" % (var.GetTypeName(), 1097 var.GetName(), 1098 var.GetValue())) 1099 if frame.GetFunction(): 1100 name = frame.GetFunction().GetName() 1101 elif frame.GetSymbol(): 1102 name = frame.GetSymbol().GetName() 1103 else: 1104 name = "" 1105 if showFuncName: 1106 return "%s(%s)" % (name, ", ".join(args)) 1107 else: 1108 return "(%s)" % (", ".join(args)) 1109 1110 1111def print_registers(frame, string_buffer=False): 1112 """Prints all the register sets of the frame.""" 1113 1114 output = SixStringIO() if string_buffer else sys.stdout 1115 1116 print("Register sets for " + str(frame), file=output) 1117 1118 registerSet = frame.GetRegisters() # Return type of SBValueList. 1119 print("Frame registers (size of register set = %d):" % 1120 registerSet.GetSize(), file=output) 1121 for value in registerSet: 1122 #print(value, file=output) 1123 print("%s (number of children = %d):" % 1124 (value.GetName(), value.GetNumChildren()), file=output) 1125 for child in value: 1126 print( 1127 "Name: %s, Value: %s" % 1128 (child.GetName(), 1129 child.GetValue()), 1130 file=output) 1131 1132 if string_buffer: 1133 return output.getvalue() 1134 1135 1136def get_registers(frame, kind): 1137 """Returns the registers given the frame and the kind of registers desired. 1138 1139 Returns None if there's no such kind. 1140 """ 1141 registerSet = frame.GetRegisters() # Return type of SBValueList. 1142 for value in registerSet: 1143 if kind.lower() in value.GetName().lower(): 1144 return value 1145 1146 return None 1147 1148 1149def get_GPRs(frame): 1150 """Returns the general purpose registers of the frame as an SBValue. 1151 1152 The returned SBValue object is iterable. An example: 1153 ... 1154 from lldbutil import get_GPRs 1155 regs = get_GPRs(frame) 1156 for reg in regs: 1157 print("%s => %s" % (reg.GetName(), reg.GetValue())) 1158 ... 1159 """ 1160 return get_registers(frame, "general purpose") 1161 1162 1163def get_FPRs(frame): 1164 """Returns the floating point registers of the frame as an SBValue. 1165 1166 The returned SBValue object is iterable. An example: 1167 ... 1168 from lldbutil import get_FPRs 1169 regs = get_FPRs(frame) 1170 for reg in regs: 1171 print("%s => %s" % (reg.GetName(), reg.GetValue())) 1172 ... 1173 """ 1174 return get_registers(frame, "floating point") 1175 1176 1177def get_ESRs(frame): 1178 """Returns the exception state registers of the frame as an SBValue. 1179 1180 The returned SBValue object is iterable. An example: 1181 ... 1182 from lldbutil import get_ESRs 1183 regs = get_ESRs(frame) 1184 for reg in regs: 1185 print("%s => %s" % (reg.GetName(), reg.GetValue())) 1186 ... 1187 """ 1188 return get_registers(frame, "exception state") 1189 1190# ====================================== 1191# Utility classes/functions for SBValues 1192# ====================================== 1193 1194 1195class BasicFormatter(object): 1196 """The basic formatter inspects the value object and prints the value.""" 1197 1198 def format(self, value, buffer=None, indent=0): 1199 if not buffer: 1200 output = SixStringIO() 1201 else: 1202 output = buffer 1203 # If there is a summary, it suffices. 1204 val = value.GetSummary() 1205 # Otherwise, get the value. 1206 if val is None: 1207 val = value.GetValue() 1208 if val is None and value.GetNumChildren() > 0: 1209 val = "%s (location)" % value.GetLocation() 1210 print("{indentation}({type}) {name} = {value}".format( 1211 indentation=' ' * indent, 1212 type=value.GetTypeName(), 1213 name=value.GetName(), 1214 value=val), file=output) 1215 return output.getvalue() 1216 1217 1218class ChildVisitingFormatter(BasicFormatter): 1219 """The child visiting formatter prints the value and its immediate children. 1220 1221 The constructor takes a keyword arg: indent_child, which defaults to 2. 1222 """ 1223 1224 def __init__(self, indent_child=2): 1225 """Default indentation of 2 SPC's for the children.""" 1226 self.cindent = indent_child 1227 1228 def format(self, value, buffer=None): 1229 if not buffer: 1230 output = SixStringIO() 1231 else: 1232 output = buffer 1233 1234 BasicFormatter.format(self, value, buffer=output) 1235 for child in value: 1236 BasicFormatter.format( 1237 self, child, buffer=output, indent=self.cindent) 1238 1239 return output.getvalue() 1240 1241 1242class RecursiveDecentFormatter(BasicFormatter): 1243 """The recursive decent formatter prints the value and the decendents. 1244 1245 The constructor takes two keyword args: indent_level, which defaults to 0, 1246 and indent_child, which defaults to 2. The current indentation level is 1247 determined by indent_level, while the immediate children has an additional 1248 indentation by inden_child. 1249 """ 1250 1251 def __init__(self, indent_level=0, indent_child=2): 1252 self.lindent = indent_level 1253 self.cindent = indent_child 1254 1255 def format(self, value, buffer=None): 1256 if not buffer: 1257 output = SixStringIO() 1258 else: 1259 output = buffer 1260 1261 BasicFormatter.format(self, value, buffer=output, indent=self.lindent) 1262 new_indent = self.lindent + self.cindent 1263 for child in value: 1264 if child.GetSummary() is not None: 1265 BasicFormatter.format( 1266 self, child, buffer=output, indent=new_indent) 1267 else: 1268 if child.GetNumChildren() > 0: 1269 rdf = RecursiveDecentFormatter(indent_level=new_indent) 1270 rdf.format(child, buffer=output) 1271 else: 1272 BasicFormatter.format( 1273 self, child, buffer=output, indent=new_indent) 1274 1275 return output.getvalue() 1276 1277# =========================================================== 1278# Utility functions for path manipulation on remote platforms 1279# =========================================================== 1280 1281 1282def join_remote_paths(*paths): 1283 # TODO: update with actual platform name for remote windows once it exists 1284 if lldb.remote_platform.GetName() == 'remote-windows': 1285 return os.path.join(*paths).replace(os.path.sep, '\\') 1286 return os.path.join(*paths).replace(os.path.sep, '/') 1287 1288 1289def append_to_process_working_directory(test, *paths): 1290 remote = lldb.remote_platform 1291 if remote: 1292 return join_remote_paths(remote.GetWorkingDirectory(), *paths) 1293 return os.path.join(test.getBuildDir(), *paths) 1294 1295# ================================================== 1296# Utility functions to get the correct signal number 1297# ================================================== 1298 1299import signal 1300 1301 1302def get_signal_number(signal_name): 1303 platform = lldb.remote_platform 1304 if platform and platform.IsValid(): 1305 signals = platform.GetUnixSignals() 1306 if signals.IsValid(): 1307 signal_number = signals.GetSignalNumberFromName(signal_name) 1308 if signal_number > 0: 1309 return signal_number 1310 # No remote platform; fall back to using local python signals. 1311 return getattr(signal, signal_name) 1312 1313 1314class PrintableRegex(object): 1315 1316 def __init__(self, text): 1317 self.regex = re.compile(text) 1318 self.text = text 1319 1320 def match(self, str): 1321 return self.regex.match(str) 1322 1323 def __str__(self): 1324 return "%s" % (self.text) 1325 1326 def __repr__(self): 1327 return "re.compile(%s) -> %s" % (self.text, self.regex) 1328 1329 1330def skip_if_callable(test, mycallable, reason): 1331 if six.callable(mycallable): 1332 if mycallable(test): 1333 test.skipTest(reason) 1334 return True 1335 return False 1336 1337 1338def skip_if_library_missing(test, target, library): 1339 def find_library(target, library): 1340 for module in target.modules: 1341 filename = module.file.GetFilename() 1342 if isinstance(library, str): 1343 if library == filename: 1344 return False 1345 elif hasattr(library, 'match'): 1346 if library.match(filename): 1347 return False 1348 return True 1349 1350 def find_library_callable(test): 1351 return find_library(target, library) 1352 return skip_if_callable( 1353 test, 1354 find_library_callable, 1355 "could not find library matching '%s' in target %s" % 1356 (library, 1357 target)) 1358 1359 1360def read_file_on_target(test, remote): 1361 if lldb.remote_platform: 1362 local = test.getBuildArtifact("file_from_target") 1363 error = lldb.remote_platform.Get(lldb.SBFileSpec(remote, False), 1364 lldb.SBFileSpec(local, True)) 1365 test.assertTrue(error.Success(), "Reading file {0} failed: {1}".format(remote, error)) 1366 else: 1367 local = remote 1368 with open(local, 'r') as f: 1369 return f.read() 1370 1371def read_file_from_process_wd(test, name): 1372 path = append_to_process_working_directory(test, name) 1373 return read_file_on_target(test, path) 1374 1375def wait_for_file_on_target(testcase, file_path, max_attempts=6): 1376 for i in range(max_attempts): 1377 err, retcode, msg = testcase.run_platform_command("ls %s" % file_path) 1378 if err.Success() and retcode == 0: 1379 break 1380 if i < max_attempts: 1381 # Exponential backoff! 1382 import time 1383 time.sleep(pow(2, i) * 0.25) 1384 else: 1385 testcase.fail( 1386 "File %s not found even after %d attempts." % 1387 (file_path, max_attempts)) 1388 1389 return read_file_on_target(testcase, file_path) 1390