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