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 os 13import re 14import sys 15 16# Third-party modules 17from six import StringIO as SixStringIO 18import six 19 20# LLDB modules 21import lldb 22 23 24# =================================================== 25# Utilities for locating/checking executable programs 26# =================================================== 27 28def is_exe(fpath): 29 """Returns True if fpath is an executable.""" 30 return os.path.isfile(fpath) and os.access(fpath, os.X_OK) 31 32def which(program): 33 """Returns the full path to a program; None otherwise.""" 34 fpath, fname = os.path.split(program) 35 if fpath: 36 if is_exe(program): 37 return program 38 else: 39 for path in os.environ["PATH"].split(os.pathsep): 40 exe_file = os.path.join(path, program) 41 if is_exe(exe_file): 42 return exe_file 43 return None 44 45# =================================================== 46# Disassembly for an SBFunction or an SBSymbol object 47# =================================================== 48 49def disassemble(target, function_or_symbol): 50 """Disassemble the function or symbol given a target. 51 52 It returns the disassembly content in a string object. 53 """ 54 buf = SixStringIO() 55 insts = function_or_symbol.GetInstructions(target) 56 for i in insts: 57 print(i, file=buf) 58 return buf.getvalue() 59 60# ========================================================== 61# Integer (byte size 1, 2, 4, and 8) to bytearray conversion 62# ========================================================== 63 64def int_to_bytearray(val, bytesize): 65 """Utility function to convert an integer into a bytearray. 66 67 It returns the bytearray in the little endian format. It is easy to get the 68 big endian format, just do ba.reverse() on the returned object. 69 """ 70 import struct 71 72 if bytesize == 1: 73 return bytearray([val]) 74 75 # Little endian followed by a format character. 76 template = "<%c" 77 if bytesize == 2: 78 fmt = template % 'h' 79 elif bytesize == 4: 80 fmt = template % 'i' 81 elif bytesize == 4: 82 fmt = template % 'q' 83 else: 84 return None 85 86 packed = struct.pack(fmt, val) 87 return bytearray(packed) 88 89def bytearray_to_int(bytes, bytesize): 90 """Utility function to convert a bytearray into an integer. 91 92 It interprets the bytearray in the little endian format. For a big endian 93 bytearray, just do ba.reverse() on the object before passing it in. 94 """ 95 import struct 96 97 if bytesize == 1: 98 return bytes[0] 99 100 # Little endian followed by a format character. 101 template = "<%c" 102 if bytesize == 2: 103 fmt = template % 'h' 104 elif bytesize == 4: 105 fmt = template % 'i' 106 elif bytesize == 4: 107 fmt = template % 'q' 108 else: 109 return None 110 111 unpacked = struct.unpack_from(fmt, bytes) 112 return unpacked[0] 113 114 115# ============================================================== 116# Get the description of an lldb object or None if not available 117# ============================================================== 118def get_description(obj, option=None): 119 """Calls lldb_obj.GetDescription() and returns a string, or None. 120 121 For SBTarget, SBBreakpointLocation, and SBWatchpoint lldb objects, an extra 122 option can be passed in to describe the detailed level of description 123 desired: 124 o lldb.eDescriptionLevelBrief 125 o lldb.eDescriptionLevelFull 126 o lldb.eDescriptionLevelVerbose 127 """ 128 method = getattr(obj, 'GetDescription') 129 if not method: 130 return None 131 tuple = (lldb.SBTarget, lldb.SBBreakpointLocation, lldb.SBWatchpoint) 132 if isinstance(obj, tuple): 133 if option is None: 134 option = lldb.eDescriptionLevelBrief 135 136 stream = lldb.SBStream() 137 if option is None: 138 success = method(stream) 139 else: 140 success = method(stream, option) 141 if not success: 142 return None 143 return stream.GetData() 144 145 146# ================================================= 147# Convert some enum value to its string counterpart 148# ================================================= 149 150def state_type_to_str(enum): 151 """Returns the stateType string given an enum.""" 152 if enum == lldb.eStateInvalid: 153 return "invalid" 154 elif enum == lldb.eStateUnloaded: 155 return "unloaded" 156 elif enum == lldb.eStateConnected: 157 return "connected" 158 elif enum == lldb.eStateAttaching: 159 return "attaching" 160 elif enum == lldb.eStateLaunching: 161 return "launching" 162 elif enum == lldb.eStateStopped: 163 return "stopped" 164 elif enum == lldb.eStateRunning: 165 return "running" 166 elif enum == lldb.eStateStepping: 167 return "stepping" 168 elif enum == lldb.eStateCrashed: 169 return "crashed" 170 elif enum == lldb.eStateDetached: 171 return "detached" 172 elif enum == lldb.eStateExited: 173 return "exited" 174 elif enum == lldb.eStateSuspended: 175 return "suspended" 176 else: 177 raise Exception("Unknown StateType enum") 178 179def stop_reason_to_str(enum): 180 """Returns the stopReason string given an enum.""" 181 if enum == lldb.eStopReasonInvalid: 182 return "invalid" 183 elif enum == lldb.eStopReasonNone: 184 return "none" 185 elif enum == lldb.eStopReasonTrace: 186 return "trace" 187 elif enum == lldb.eStopReasonBreakpoint: 188 return "breakpoint" 189 elif enum == lldb.eStopReasonWatchpoint: 190 return "watchpoint" 191 elif enum == lldb.eStopReasonExec: 192 return "exec" 193 elif enum == lldb.eStopReasonSignal: 194 return "signal" 195 elif enum == lldb.eStopReasonException: 196 return "exception" 197 elif enum == lldb.eStopReasonPlanComplete: 198 return "plancomplete" 199 elif enum == lldb.eStopReasonThreadExiting: 200 return "threadexiting" 201 else: 202 raise Exception("Unknown StopReason enum") 203 204def symbol_type_to_str(enum): 205 """Returns the symbolType string given an enum.""" 206 if enum == lldb.eSymbolTypeInvalid: 207 return "invalid" 208 elif enum == lldb.eSymbolTypeAbsolute: 209 return "absolute" 210 elif enum == lldb.eSymbolTypeCode: 211 return "code" 212 elif enum == lldb.eSymbolTypeData: 213 return "data" 214 elif enum == lldb.eSymbolTypeTrampoline: 215 return "trampoline" 216 elif enum == lldb.eSymbolTypeRuntime: 217 return "runtime" 218 elif enum == lldb.eSymbolTypeException: 219 return "exception" 220 elif enum == lldb.eSymbolTypeSourceFile: 221 return "sourcefile" 222 elif enum == lldb.eSymbolTypeHeaderFile: 223 return "headerfile" 224 elif enum == lldb.eSymbolTypeObjectFile: 225 return "objectfile" 226 elif enum == lldb.eSymbolTypeCommonBlock: 227 return "commonblock" 228 elif enum == lldb.eSymbolTypeBlock: 229 return "block" 230 elif enum == lldb.eSymbolTypeLocal: 231 return "local" 232 elif enum == lldb.eSymbolTypeParam: 233 return "param" 234 elif enum == lldb.eSymbolTypeVariable: 235 return "variable" 236 elif enum == lldb.eSymbolTypeVariableType: 237 return "variabletype" 238 elif enum == lldb.eSymbolTypeLineEntry: 239 return "lineentry" 240 elif enum == lldb.eSymbolTypeLineHeader: 241 return "lineheader" 242 elif enum == lldb.eSymbolTypeScopeBegin: 243 return "scopebegin" 244 elif enum == lldb.eSymbolTypeScopeEnd: 245 return "scopeend" 246 elif enum == lldb.eSymbolTypeAdditional: 247 return "additional" 248 elif enum == lldb.eSymbolTypeCompiler: 249 return "compiler" 250 elif enum == lldb.eSymbolTypeInstrumentation: 251 return "instrumentation" 252 elif enum == lldb.eSymbolTypeUndefined: 253 return "undefined" 254 255def value_type_to_str(enum): 256 """Returns the valueType string given an enum.""" 257 if enum == lldb.eValueTypeInvalid: 258 return "invalid" 259 elif enum == lldb.eValueTypeVariableGlobal: 260 return "global_variable" 261 elif enum == lldb.eValueTypeVariableStatic: 262 return "static_variable" 263 elif enum == lldb.eValueTypeVariableArgument: 264 return "argument_variable" 265 elif enum == lldb.eValueTypeVariableLocal: 266 return "local_variable" 267 elif enum == lldb.eValueTypeRegister: 268 return "register" 269 elif enum == lldb.eValueTypeRegisterSet: 270 return "register_set" 271 elif enum == lldb.eValueTypeConstResult: 272 return "constant_result" 273 else: 274 raise Exception("Unknown ValueType enum") 275 276 277# ================================================== 278# Get stopped threads due to each stop reason. 279# ================================================== 280 281def sort_stopped_threads(process, 282 breakpoint_threads = None, 283 crashed_threads = None, 284 watchpoint_threads = None, 285 signal_threads = None, 286 exiting_threads = None, 287 other_threads = None): 288 """ Fills array *_threads with threads stopped for the corresponding stop 289 reason. 290 """ 291 for lst in [breakpoint_threads, 292 watchpoint_threads, 293 signal_threads, 294 exiting_threads, 295 other_threads]: 296 if lst is not None: 297 lst[:] = [] 298 299 for thread in process: 300 dispatched = False 301 for (reason, list) in [(lldb.eStopReasonBreakpoint, breakpoint_threads), 302 (lldb.eStopReasonException, crashed_threads), 303 (lldb.eStopReasonWatchpoint, watchpoint_threads), 304 (lldb.eStopReasonSignal, signal_threads), 305 (lldb.eStopReasonThreadExiting, exiting_threads), 306 (None, other_threads)]: 307 if not dispatched and list is not None: 308 if thread.GetStopReason() == reason or reason is None: 309 list.append(thread) 310 dispatched = True 311 312# ================================================== 313# Utility functions for setting breakpoints 314# ================================================== 315 316def run_break_set_by_file_and_line (test, file_name, line_number, extra_options = None, num_expected_locations = 1, loc_exact=False, module_name=None): 317 """Set a breakpoint by file and line, returning the breakpoint number. 318 319 If extra_options is not None, then we append it to the breakpoint set command. 320 321 If num_expected_locations is -1 we check that we got AT LEAST one location, otherwise we check that num_expected_locations equals the number of locations. 322 323 If loc_exact is true, we check that there is one location, and that location must be at the input file and line number.""" 324 325 if file_name == None: 326 command = 'breakpoint set -l %d'%(line_number) 327 else: 328 command = 'breakpoint set -f "%s" -l %d'%(file_name, line_number) 329 330 if module_name: 331 command += " --shlib '%s'" % (module_name) 332 333 if extra_options: 334 command += " " + extra_options 335 336 break_results = run_break_set_command (test, command) 337 338 if num_expected_locations == 1 and loc_exact: 339 check_breakpoint_result (test, break_results, num_locations=num_expected_locations, file_name = file_name, line_number = line_number, module_name=module_name) 340 else: 341 check_breakpoint_result (test, break_results, num_locations = num_expected_locations) 342 343 return get_bpno_from_match (break_results) 344 345def run_break_set_by_symbol (test, symbol, extra_options = None, num_expected_locations = -1, sym_exact = False, module_name=None): 346 """Set a breakpoint by symbol name. Common options are the same as run_break_set_by_file_and_line. 347 348 If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match.""" 349 command = 'breakpoint set -n "%s"'%(symbol) 350 351 if module_name: 352 command += " --shlib '%s'" % (module_name) 353 354 if extra_options: 355 command += " " + extra_options 356 357 break_results = run_break_set_command (test, command) 358 359 if num_expected_locations == 1 and sym_exact: 360 check_breakpoint_result (test, break_results, num_locations = num_expected_locations, symbol_name = symbol, module_name=module_name) 361 else: 362 check_breakpoint_result (test, break_results, num_locations = num_expected_locations) 363 364 return get_bpno_from_match (break_results) 365 366def run_break_set_by_selector (test, selector, extra_options = None, num_expected_locations = -1, module_name=None): 367 """Set a breakpoint by selector. Common options are the same as run_break_set_by_file_and_line.""" 368 369 command = 'breakpoint set -S "%s"' % (selector) 370 371 if module_name: 372 command += ' --shlib "%s"' % (module_name) 373 374 if extra_options: 375 command += " " + extra_options 376 377 break_results = run_break_set_command (test, command) 378 379 if num_expected_locations == 1: 380 check_breakpoint_result (test, break_results, num_locations = num_expected_locations, symbol_name = selector, symbol_match_exact=False, module_name=module_name) 381 else: 382 check_breakpoint_result (test, break_results, num_locations = num_expected_locations) 383 384 return get_bpno_from_match (break_results) 385 386def run_break_set_by_regexp (test, regexp, extra_options=None, num_expected_locations=-1): 387 """Set a breakpoint by regular expression match on symbol name. Common options are the same as run_break_set_by_file_and_line.""" 388 389 command = 'breakpoint set -r "%s"'%(regexp) 390 if extra_options: 391 command += " " + extra_options 392 393 break_results = run_break_set_command (test, command) 394 395 check_breakpoint_result (test, break_results, num_locations=num_expected_locations) 396 397 return get_bpno_from_match (break_results) 398 399def run_break_set_by_source_regexp (test, regexp, extra_options=None, num_expected_locations=-1): 400 """Set a breakpoint by source regular expression. Common options are the same as run_break_set_by_file_and_line.""" 401 command = 'breakpoint set -p "%s"'%(regexp) 402 if extra_options: 403 command += " " + extra_options 404 405 break_results = run_break_set_command (test, command) 406 407 check_breakpoint_result (test, break_results, num_locations=num_expected_locations) 408 409 return get_bpno_from_match (break_results) 410 411def run_break_set_command (test, command): 412 """Run the command passed in - it must be some break set variant - and analyze the result. 413 Returns a dictionary of information gleaned from the command-line results. 414 Will assert if the breakpoint setting fails altogether. 415 416 Dictionary will contain: 417 bpno - breakpoint of the newly created breakpoint, -1 on error. 418 num_locations - number of locations set for the breakpoint. 419 420 If there is only one location, the dictionary MAY contain: 421 file - source file name 422 line_no - source line number 423 symbol - symbol name 424 inline_symbol - inlined symbol name 425 offset - offset from the original symbol 426 module - module 427 address - address at which the breakpoint was set.""" 428 429 patterns = [r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$", 430 r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.", 431 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]+), address = (?P<address>0x[0-9a-fA-F]+)$", 432 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]+)$"] 433 match_object = test.match (command, patterns) 434 break_results = match_object.groupdict() 435 436 # We always insert the breakpoint number, setting it to -1 if we couldn't find it 437 # Also, make sure it gets stored as an integer. 438 if not 'bpno' in break_results: 439 break_results['bpno'] = -1 440 else: 441 break_results['bpno'] = int(break_results['bpno']) 442 443 # We always insert the number of locations 444 # If ONE location is set for the breakpoint, then the output doesn't mention locations, but it has to be 1... 445 # We also make sure it is an integer. 446 447 if not 'num_locations' in break_results: 448 num_locations = 1 449 else: 450 num_locations = break_results['num_locations'] 451 if num_locations == 'no': 452 num_locations = 0 453 else: 454 num_locations = int(break_results['num_locations']) 455 456 break_results['num_locations'] = num_locations 457 458 if 'line_no' in break_results: 459 break_results['line_no'] = int(break_results['line_no']) 460 461 return break_results 462 463def get_bpno_from_match (break_results): 464 return int (break_results['bpno']) 465 466def check_breakpoint_result (test, break_results, file_name=None, line_number=-1, symbol_name=None, symbol_match_exact=True, module_name=None, offset=-1, num_locations=-1): 467 468 out_num_locations = break_results['num_locations'] 469 470 if num_locations == -1: 471 test.assertTrue (out_num_locations > 0, "Expecting one or more locations, got none.") 472 else: 473 test.assertTrue (num_locations == out_num_locations, "Expecting %d locations, got %d."%(num_locations, out_num_locations)) 474 475 if file_name: 476 out_file_name = "" 477 if 'file' in break_results: 478 out_file_name = break_results['file'] 479 test.assertTrue (file_name == out_file_name, "Breakpoint file name '%s' doesn't match resultant name '%s'."%(file_name, out_file_name)) 480 481 if line_number != -1: 482 out_line_number = -1 483 if 'line_no' in break_results: 484 out_line_number = break_results['line_no'] 485 486 test.assertTrue (line_number == out_line_number, "Breakpoint line number %s doesn't match resultant line %s."%(line_number, out_line_number)) 487 488 if symbol_name: 489 out_symbol_name = "" 490 # Look first for the inlined symbol name, otherwise use the symbol name: 491 if 'inline_symbol' in break_results and break_results['inline_symbol']: 492 out_symbol_name = break_results['inline_symbol'] 493 elif 'symbol' in break_results: 494 out_symbol_name = break_results['symbol'] 495 496 if symbol_match_exact: 497 test.assertTrue(symbol_name == out_symbol_name, "Symbol name '%s' doesn't match resultant symbol '%s'."%(symbol_name, out_symbol_name)) 498 else: 499 test.assertTrue(out_symbol_name.find(symbol_name) != -1, "Symbol name '%s' isn't in resultant symbol '%s'."%(symbol_name, out_symbol_name)) 500 501 if module_name: 502 out_module_name = None 503 if 'module' in break_results: 504 out_module_name = break_results['module'] 505 506 test.assertTrue (module_name.find(out_module_name) != -1, "Symbol module name '%s' isn't in expected module name '%s'."%(out_module_name, module_name)) 507 508# ================================================== 509# Utility functions related to Threads and Processes 510# ================================================== 511 512def get_stopped_threads(process, reason): 513 """Returns the thread(s) with the specified stop reason in a list. 514 515 The list can be empty if no such thread exists. 516 """ 517 threads = [] 518 for t in process: 519 if t.GetStopReason() == reason: 520 threads.append(t) 521 return threads 522 523def get_stopped_thread(process, reason): 524 """A convenience function which returns the first thread with the given stop 525 reason or None. 526 527 Example usages: 528 529 1. Get the stopped thread due to a breakpoint condition 530 531 ... 532 from lldbutil import get_stopped_thread 533 thread = get_stopped_thread(process, lldb.eStopReasonPlanComplete) 534 self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") 535 ... 536 537 2. Get the thread stopped due to a breakpoint 538 539 ... 540 from lldbutil import get_stopped_thread 541 thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) 542 self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint") 543 ... 544 545 """ 546 threads = get_stopped_threads(process, reason) 547 if len(threads) == 0: 548 return None 549 return threads[0] 550 551def get_threads_stopped_at_breakpoint_id(process, bpid): 552 """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt""" 553 stopped_threads = [] 554 threads = [] 555 556 stopped_threads = get_stopped_threads (process, lldb.eStopReasonBreakpoint) 557 558 if len(stopped_threads) == 0: 559 return threads 560 561 for thread in stopped_threads: 562 # Make sure we've hit our breakpoint... 563 break_id = thread.GetStopReasonDataAtIndex (0) 564 if break_id == bpid: 565 threads.append(thread) 566 567 return threads 568 569def get_threads_stopped_at_breakpoint (process, bkpt): 570 return get_threads_stopped_at_breakpoint_id(process, bkpt.GetID()) 571 572def get_one_thread_stopped_at_breakpoint_id(process, bpid, require_exactly_one = True): 573 threads = get_threads_stopped_at_breakpoint_id(process, bpid) 574 if len(threads) == 0: 575 return None 576 if require_exactly_one and len(threads) != 1: 577 return None 578 579 return threads[0] 580 581def get_one_thread_stopped_at_breakpoint(process, bkpt, require_exactly_one = True): 582 return get_one_thread_stopped_at_breakpoint_id(process, bkpt.GetID(), require_exactly_one) 583 584def is_thread_crashed (test, thread): 585 """In the test suite we dereference a null pointer to simulate a crash. The way this is 586 reported depends on the platform.""" 587 if test.platformIsDarwin(): 588 return thread.GetStopReason() == lldb.eStopReasonException and "EXC_BAD_ACCESS" in thread.GetStopDescription(100) 589 elif test.getPlatform() == "linux": 590 return thread.GetStopReason() == lldb.eStopReasonSignal and thread.GetStopReasonDataAtIndex(0) == thread.GetProcess().GetUnixSignals().GetSignalNumberFromName("SIGSEGV") 591 else: 592 return "invalid address" in thread.GetStopDescription(100) 593 594def get_crashed_threads (test, process): 595 threads = [] 596 if process.GetState() != lldb.eStateStopped: 597 return threads 598 for thread in process: 599 if is_thread_crashed(test, thread): 600 threads.append(thread) 601 return threads 602 603def continue_to_breakpoint (process, bkpt): 604 """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None""" 605 process.Continue() 606 if process.GetState() != lldb.eStateStopped: 607 return None 608 else: 609 return get_threads_stopped_at_breakpoint (process, bkpt) 610 611def get_caller_symbol(thread): 612 """ 613 Returns the symbol name for the call site of the leaf function. 614 """ 615 depth = thread.GetNumFrames() 616 if depth <= 1: 617 return None 618 caller = thread.GetFrameAtIndex(1).GetSymbol() 619 if caller: 620 return caller.GetName() 621 else: 622 return None 623 624 625def get_function_names(thread): 626 """ 627 Returns a sequence of function names from the stack frames of this thread. 628 """ 629 def GetFuncName(i): 630 return thread.GetFrameAtIndex(i).GetFunctionName() 631 632 return list(map(GetFuncName, list(range(thread.GetNumFrames())))) 633 634 635def get_symbol_names(thread): 636 """ 637 Returns a sequence of symbols for this thread. 638 """ 639 def GetSymbol(i): 640 return thread.GetFrameAtIndex(i).GetSymbol().GetName() 641 642 return list(map(GetSymbol, list(range(thread.GetNumFrames())))) 643 644 645def get_pc_addresses(thread): 646 """ 647 Returns a sequence of pc addresses for this thread. 648 """ 649 def GetPCAddress(i): 650 return thread.GetFrameAtIndex(i).GetPCAddress() 651 652 return list(map(GetPCAddress, list(range(thread.GetNumFrames())))) 653 654 655def get_filenames(thread): 656 """ 657 Returns a sequence of file names from the stack frames of this thread. 658 """ 659 def GetFilename(i): 660 return thread.GetFrameAtIndex(i).GetLineEntry().GetFileSpec().GetFilename() 661 662 return list(map(GetFilename, list(range(thread.GetNumFrames())))) 663 664 665def get_line_numbers(thread): 666 """ 667 Returns a sequence of line numbers from the stack frames of this thread. 668 """ 669 def GetLineNumber(i): 670 return thread.GetFrameAtIndex(i).GetLineEntry().GetLine() 671 672 return list(map(GetLineNumber, list(range(thread.GetNumFrames())))) 673 674 675def get_module_names(thread): 676 """ 677 Returns a sequence of module names from the stack frames of this thread. 678 """ 679 def GetModuleName(i): 680 return thread.GetFrameAtIndex(i).GetModule().GetFileSpec().GetFilename() 681 682 return list(map(GetModuleName, list(range(thread.GetNumFrames())))) 683 684 685def get_stack_frames(thread): 686 """ 687 Returns a sequence of stack frames for this thread. 688 """ 689 def GetStackFrame(i): 690 return thread.GetFrameAtIndex(i) 691 692 return list(map(GetStackFrame, list(range(thread.GetNumFrames())))) 693 694 695def print_stacktrace(thread, string_buffer = False): 696 """Prints a simple stack trace of this thread.""" 697 698 output = SixStringIO() if string_buffer else sys.stdout 699 target = thread.GetProcess().GetTarget() 700 701 depth = thread.GetNumFrames() 702 703 mods = get_module_names(thread) 704 funcs = get_function_names(thread) 705 symbols = get_symbol_names(thread) 706 files = get_filenames(thread) 707 lines = get_line_numbers(thread) 708 addrs = get_pc_addresses(thread) 709 710 if thread.GetStopReason() != lldb.eStopReasonInvalid: 711 desc = "stop reason=" + stop_reason_to_str(thread.GetStopReason()) 712 else: 713 desc = "" 714 print("Stack trace for thread id={0:#x} name={1} queue={2} ".format( 715 thread.GetThreadID(), thread.GetName(), thread.GetQueueName()) + desc, file=output) 716 717 for i in range(depth): 718 frame = thread.GetFrameAtIndex(i) 719 function = frame.GetFunction() 720 721 load_addr = addrs[i].GetLoadAddress(target) 722 if not function: 723 file_addr = addrs[i].GetFileAddress() 724 start_addr = frame.GetSymbol().GetStartAddress().GetFileAddress() 725 symbol_offset = file_addr - start_addr 726 print(" frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format( 727 num=i, addr=load_addr, mod=mods[i], symbol=symbols[i], offset=symbol_offset), file=output) 728 else: 729 print(" frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format( 730 num=i, addr=load_addr, mod=mods[i], 731 func='%s [inlined]' % funcs[i] if frame.IsInlined() else funcs[i], 732 file=files[i], line=lines[i], 733 args=get_args_as_string(frame, showFuncName=False) if not frame.IsInlined() else '()'), file=output) 734 735 if string_buffer: 736 return output.getvalue() 737 738 739def print_stacktraces(process, string_buffer = False): 740 """Prints the stack traces of all the threads.""" 741 742 output = SixStringIO() if string_buffer else sys.stdout 743 744 print("Stack traces for " + str(process), file=output) 745 746 for thread in process: 747 print(print_stacktrace(thread, string_buffer=True), file=output) 748 749 if string_buffer: 750 return output.getvalue() 751 752def expect_state_changes(test, listener, states, timeout = 5): 753 """Listens for state changed events on the listener and makes sure they match what we 754 expect. Stop-and-restart events (where GetRestartedFromEvent() returns true) are ignored.""" 755 756 for expected_state in states: 757 def get_next_event(): 758 event = lldb.SBEvent() 759 if not listener.WaitForEvent(timeout, event): 760 test.fail("Timed out while waiting for a transition to state %s" % 761 lldb.SBDebugger.StateAsCString(expected_state)) 762 return event 763 764 event = get_next_event() 765 while (lldb.SBProcess.GetStateFromEvent(event) == lldb.eStateStopped and 766 lldb.SBProcess.GetRestartedFromEvent(event)): 767 # Ignore restarted event and the subsequent running event. 768 event = get_next_event() 769 test.assertEqual(lldb.SBProcess.GetStateFromEvent(event), lldb.eStateRunning, 770 "Restarted event followed by a running event") 771 event = get_next_event() 772 773 test.assertEqual(lldb.SBProcess.GetStateFromEvent(event), expected_state) 774 775# =================================== 776# Utility functions related to Frames 777# =================================== 778 779def get_parent_frame(frame): 780 """ 781 Returns the parent frame of the input frame object; None if not available. 782 """ 783 thread = frame.GetThread() 784 parent_found = False 785 for f in thread: 786 if parent_found: 787 return f 788 if f.GetFrameID() == frame.GetFrameID(): 789 parent_found = True 790 791 # If we reach here, no parent has been found, return None. 792 return None 793 794def get_args_as_string(frame, showFuncName=True): 795 """ 796 Returns the args of the input frame object as a string. 797 """ 798 # arguments => True 799 # locals => False 800 # statics => False 801 # in_scope_only => True 802 vars = frame.GetVariables(True, False, False, True) # type of SBValueList 803 args = [] # list of strings 804 for var in vars: 805 args.append("(%s)%s=%s" % (var.GetTypeName(), 806 var.GetName(), 807 var.GetValue())) 808 if frame.GetFunction(): 809 name = frame.GetFunction().GetName() 810 elif frame.GetSymbol(): 811 name = frame.GetSymbol().GetName() 812 else: 813 name = "" 814 if showFuncName: 815 return "%s(%s)" % (name, ", ".join(args)) 816 else: 817 return "(%s)" % (", ".join(args)) 818 819def print_registers(frame, string_buffer = False): 820 """Prints all the register sets of the frame.""" 821 822 output = SixStringIO() if string_buffer else sys.stdout 823 824 print("Register sets for " + str(frame), file=output) 825 826 registerSet = frame.GetRegisters() # Return type of SBValueList. 827 print("Frame registers (size of register set = %d):" % registerSet.GetSize(), file=output) 828 for value in registerSet: 829 #print(value, file=output) 830 print("%s (number of children = %d):" % (value.GetName(), value.GetNumChildren()), file=output) 831 for child in value: 832 print("Name: %s, Value: %s" % (child.GetName(), child.GetValue()), file=output) 833 834 if string_buffer: 835 return output.getvalue() 836 837def get_registers(frame, kind): 838 """Returns the registers given the frame and the kind of registers desired. 839 840 Returns None if there's no such kind. 841 """ 842 registerSet = frame.GetRegisters() # Return type of SBValueList. 843 for value in registerSet: 844 if kind.lower() in value.GetName().lower(): 845 return value 846 847 return None 848 849def get_GPRs(frame): 850 """Returns the general purpose registers of the frame as an SBValue. 851 852 The returned SBValue object is iterable. An example: 853 ... 854 from lldbutil import get_GPRs 855 regs = get_GPRs(frame) 856 for reg in regs: 857 print("%s => %s" % (reg.GetName(), reg.GetValue())) 858 ... 859 """ 860 return get_registers(frame, "general purpose") 861 862def get_FPRs(frame): 863 """Returns the floating point registers of the frame as an SBValue. 864 865 The returned SBValue object is iterable. An example: 866 ... 867 from lldbutil import get_FPRs 868 regs = get_FPRs(frame) 869 for reg in regs: 870 print("%s => %s" % (reg.GetName(), reg.GetValue())) 871 ... 872 """ 873 return get_registers(frame, "floating point") 874 875def get_ESRs(frame): 876 """Returns the exception state registers of the frame as an SBValue. 877 878 The returned SBValue object is iterable. An example: 879 ... 880 from lldbutil import get_ESRs 881 regs = get_ESRs(frame) 882 for reg in regs: 883 print("%s => %s" % (reg.GetName(), reg.GetValue())) 884 ... 885 """ 886 return get_registers(frame, "exception state") 887 888# ====================================== 889# Utility classes/functions for SBValues 890# ====================================== 891 892class BasicFormatter(object): 893 """The basic formatter inspects the value object and prints the value.""" 894 def format(self, value, buffer=None, indent=0): 895 if not buffer: 896 output = SixStringIO() 897 else: 898 output = buffer 899 # If there is a summary, it suffices. 900 val = value.GetSummary() 901 # Otherwise, get the value. 902 if val == None: 903 val = value.GetValue() 904 if val == None and value.GetNumChildren() > 0: 905 val = "%s (location)" % value.GetLocation() 906 print("{indentation}({type}) {name} = {value}".format( 907 indentation = ' ' * indent, 908 type = value.GetTypeName(), 909 name = value.GetName(), 910 value = val), file=output) 911 return output.getvalue() 912 913class ChildVisitingFormatter(BasicFormatter): 914 """The child visiting formatter prints the value and its immediate children. 915 916 The constructor takes a keyword arg: indent_child, which defaults to 2. 917 """ 918 def __init__(self, indent_child=2): 919 """Default indentation of 2 SPC's for the children.""" 920 self.cindent = indent_child 921 def format(self, value, buffer=None): 922 if not buffer: 923 output = SixStringIO() 924 else: 925 output = buffer 926 927 BasicFormatter.format(self, value, buffer=output) 928 for child in value: 929 BasicFormatter.format(self, child, buffer=output, indent=self.cindent) 930 931 return output.getvalue() 932 933class RecursiveDecentFormatter(BasicFormatter): 934 """The recursive decent formatter prints the value and the decendents. 935 936 The constructor takes two keyword args: indent_level, which defaults to 0, 937 and indent_child, which defaults to 2. The current indentation level is 938 determined by indent_level, while the immediate children has an additional 939 indentation by inden_child. 940 """ 941 def __init__(self, indent_level=0, indent_child=2): 942 self.lindent = indent_level 943 self.cindent = indent_child 944 def format(self, value, buffer=None): 945 if not buffer: 946 output = SixStringIO() 947 else: 948 output = buffer 949 950 BasicFormatter.format(self, value, buffer=output, indent=self.lindent) 951 new_indent = self.lindent + self.cindent 952 for child in value: 953 if child.GetSummary() != None: 954 BasicFormatter.format(self, child, buffer=output, indent=new_indent) 955 else: 956 if child.GetNumChildren() > 0: 957 rdf = RecursiveDecentFormatter(indent_level=new_indent) 958 rdf.format(child, buffer=output) 959 else: 960 BasicFormatter.format(self, child, buffer=output, indent=new_indent) 961 962 return output.getvalue() 963 964# =========================================================== 965# Utility functions for path manipulation on remote platforms 966# =========================================================== 967 968def join_remote_paths(*paths): 969 # TODO: update with actual platform name for remote windows once it exists 970 if lldb.remote_platform.GetName() == 'remote-windows': 971 return os.path.join(*paths).replace(os.path.sep, '\\') 972 return os.path.join(*paths).replace(os.path.sep, '/') 973 974def append_to_process_working_directory(*paths): 975 remote = lldb.remote_platform 976 if remote: 977 return join_remote_paths(remote.GetWorkingDirectory(), *paths) 978 return os.path.join(os.getcwd(), *paths) 979 980# ================================================== 981# Utility functions to get the correct signal number 982# ================================================== 983 984import signal 985 986def get_signal_number(signal_name): 987 platform = lldb.remote_platform 988 if platform and platform.IsValid(): 989 signals = platform.GetUnixSignals() 990 if signals.IsValid(): 991 signal_number = signals.GetSignalNumberFromName(signal_name) 992 if signal_number > 0: 993 return signal_number 994 # No remote platform; fall back to using local python signals. 995 return getattr(signal, signal_name) 996 997class PrintableRegex(object): 998 def __init__(self, text): 999 self.regex = re.compile(text) 1000 self.text = text 1001 1002 def match(self, str): 1003 return self.regex.match(str) 1004 1005 def __str__(self): 1006 return "%s" % (self.text) 1007 1008 def __repr__(self): 1009 return "re.compile(%s) -> %s" % (self.text, self.regex) 1010 1011def skip_if_callable(test, mycallable, reason): 1012 if six.callable(mycallable): 1013 if mycallable(test): 1014 test.skipTest(reason) 1015 return True 1016 return False 1017 1018def skip_if_library_missing(test, target, library): 1019 def find_library(target, library): 1020 for module in target.modules: 1021 filename = module.file.GetFilename() 1022 if isinstance(library, str): 1023 if library == filename: 1024 return False 1025 elif hasattr(library, 'match'): 1026 if library.match(filename): 1027 return False 1028 return True 1029 def find_library_callable(test): 1030 return find_library(target, library) 1031 return skip_if_callable(test, find_library_callable, "could not find library matching '%s' in target %s" % (library, target)) 1032