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