Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / utils / lui / lldbutil.py
blob6cbf4a302f65f3566ac4742a7cf3e5a9d005c238
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 ##===----------------------------------------------------------------------===##
9 """
10 This LLDB module contains miscellaneous utilities.
11 Some of the test suite takes advantage of the utility functions defined here.
12 They can also be useful for general purpose lldb scripting.
13 """
15 import lldb
16 import os
17 import sys
18 import io
20 # ===================================================
21 # Utilities for locating/checking executable programs
22 # ===================================================
25 def is_exe(fpath):
26 """Returns True if fpath is an executable."""
27 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
30 def which(program):
31 """Returns the full path to a program; None otherwise."""
32 fpath, fname = os.path.split(program)
33 if fpath:
34 if is_exe(program):
35 return program
36 else:
37 for path in os.environ["PATH"].split(os.pathsep):
38 exe_file = os.path.join(path, program)
39 if is_exe(exe_file):
40 return exe_file
41 return None
44 # ===================================================
45 # Disassembly for an SBFunction or an SBSymbol object
46 # ===================================================
49 def disassemble(target, function_or_symbol):
50 """Disassemble the function or symbol given a target.
52 It returns the disassembly content in a string object.
53 """
54 buf = io.StringIO()
55 insts = function_or_symbol.GetInstructions(target)
56 for i in insts:
57 print(i, file=buf)
58 return buf.getvalue()
61 # ==========================================================
62 # Integer (byte size 1, 2, 4, and 8) to bytearray conversion
63 # ==========================================================
66 def int_to_bytearray(val, bytesize):
67 """Utility function to convert an integer into a bytearray.
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
74 if bytesize == 1:
75 return bytearray([val])
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
88 packed = struct.pack(fmt, val)
89 return bytearray(ord(x) for x in packed)
92 def bytearray_to_int(bytes, bytesize):
93 """Utility function to convert a bytearray into an integer.
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
100 if bytesize == 1:
101 return bytes[0]
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
114 unpacked = struct.unpack(fmt, str(bytes))
115 return unpacked[0]
118 # ==============================================================
119 # Get the description of an lldb object or None if not available
120 # ==============================================================
121 def get_description(obj, option=None):
122 """Calls lldb_obj.GetDescription() and returns a string, or None.
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
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
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()
149 # =================================================
150 # Convert some enum value to its string counterpart
151 # =================================================
154 def state_type_to_str(enum):
155 """Returns the stateType string given an enum."""
156 if enum == lldb.eStateInvalid:
157 return "invalid"
158 elif enum == lldb.eStateUnloaded:
159 return "unloaded"
160 elif enum == lldb.eStateConnected:
161 return "connected"
162 elif enum == lldb.eStateAttaching:
163 return "attaching"
164 elif enum == lldb.eStateLaunching:
165 return "launching"
166 elif enum == lldb.eStateStopped:
167 return "stopped"
168 elif enum == lldb.eStateRunning:
169 return "running"
170 elif enum == lldb.eStateStepping:
171 return "stepping"
172 elif enum == lldb.eStateCrashed:
173 return "crashed"
174 elif enum == lldb.eStateDetached:
175 return "detached"
176 elif enum == lldb.eStateExited:
177 return "exited"
178 elif enum == lldb.eStateSuspended:
179 return "suspended"
180 else:
181 raise Exception("Unknown StateType enum")
184 def stop_reason_to_str(enum):
185 """Returns the stopReason string given an enum."""
186 if enum == lldb.eStopReasonInvalid:
187 return "invalid"
188 elif enum == lldb.eStopReasonNone:
189 return "none"
190 elif enum == lldb.eStopReasonTrace:
191 return "trace"
192 elif enum == lldb.eStopReasonBreakpoint:
193 return "breakpoint"
194 elif enum == lldb.eStopReasonWatchpoint:
195 return "watchpoint"
196 elif enum == lldb.eStopReasonSignal:
197 return "signal"
198 elif enum == lldb.eStopReasonException:
199 return "exception"
200 elif enum == lldb.eStopReasonPlanComplete:
201 return "plancomplete"
202 elif enum == lldb.eStopReasonThreadExiting:
203 return "threadexiting"
204 else:
205 raise Exception("Unknown StopReason enum")
208 def symbol_type_to_str(enum):
209 """Returns the symbolType string given an enum."""
210 if enum == lldb.eSymbolTypeInvalid:
211 return "invalid"
212 elif enum == lldb.eSymbolTypeAbsolute:
213 return "absolute"
214 elif enum == lldb.eSymbolTypeCode:
215 return "code"
216 elif enum == lldb.eSymbolTypeData:
217 return "data"
218 elif enum == lldb.eSymbolTypeTrampoline:
219 return "trampoline"
220 elif enum == lldb.eSymbolTypeRuntime:
221 return "runtime"
222 elif enum == lldb.eSymbolTypeException:
223 return "exception"
224 elif enum == lldb.eSymbolTypeSourceFile:
225 return "sourcefile"
226 elif enum == lldb.eSymbolTypeHeaderFile:
227 return "headerfile"
228 elif enum == lldb.eSymbolTypeObjectFile:
229 return "objectfile"
230 elif enum == lldb.eSymbolTypeCommonBlock:
231 return "commonblock"
232 elif enum == lldb.eSymbolTypeBlock:
233 return "block"
234 elif enum == lldb.eSymbolTypeLocal:
235 return "local"
236 elif enum == lldb.eSymbolTypeParam:
237 return "param"
238 elif enum == lldb.eSymbolTypeVariable:
239 return "variable"
240 elif enum == lldb.eSymbolTypeVariableType:
241 return "variabletype"
242 elif enum == lldb.eSymbolTypeLineEntry:
243 return "lineentry"
244 elif enum == lldb.eSymbolTypeLineHeader:
245 return "lineheader"
246 elif enum == lldb.eSymbolTypeScopeBegin:
247 return "scopebegin"
248 elif enum == lldb.eSymbolTypeScopeEnd:
249 return "scopeend"
250 elif enum == lldb.eSymbolTypeAdditional:
251 return "additional"
252 elif enum == lldb.eSymbolTypeCompiler:
253 return "compiler"
254 elif enum == lldb.eSymbolTypeInstrumentation:
255 return "instrumentation"
256 elif enum == lldb.eSymbolTypeUndefined:
257 return "undefined"
260 def value_type_to_str(enum):
261 """Returns the valueType string given an enum."""
262 if enum == lldb.eValueTypeInvalid:
263 return "invalid"
264 elif enum == lldb.eValueTypeVariableGlobal:
265 return "global_variable"
266 elif enum == lldb.eValueTypeVariableStatic:
267 return "static_variable"
268 elif enum == lldb.eValueTypeVariableArgument:
269 return "argument_variable"
270 elif enum == lldb.eValueTypeVariableLocal:
271 return "local_variable"
272 elif enum == lldb.eValueTypeRegister:
273 return "register"
274 elif enum == lldb.eValueTypeRegisterSet:
275 return "register_set"
276 elif enum == lldb.eValueTypeConstResult:
277 return "constant_result"
278 else:
279 raise Exception("Unknown ValueType enum")
282 # ==================================================
283 # Get stopped threads due to each stop reason.
284 # ==================================================
287 def sort_stopped_threads(
288 process,
289 breakpoint_threads=None,
290 crashed_threads=None,
291 watchpoint_threads=None,
292 signal_threads=None,
293 exiting_threads=None,
294 other_threads=None,
296 """Fills array *_threads with threads stopped for the corresponding stop
297 reason.
299 for lst in [
300 breakpoint_threads,
301 watchpoint_threads,
302 signal_threads,
303 exiting_threads,
304 other_threads,
306 if lst is not None:
307 lst[:] = []
309 for thread in process:
310 dispatched = False
311 for reason, list in [
312 (lldb.eStopReasonBreakpoint, breakpoint_threads),
313 (lldb.eStopReasonException, crashed_threads),
314 (lldb.eStopReasonWatchpoint, watchpoint_threads),
315 (lldb.eStopReasonSignal, signal_threads),
316 (lldb.eStopReasonThreadExiting, exiting_threads),
317 (None, other_threads),
319 if not dispatched and list is not None:
320 if thread.GetStopReason() == reason or reason is None:
321 list.append(thread)
322 dispatched = True
325 # ==================================================
326 # Utility functions for setting breakpoints
327 # ==================================================
330 def run_break_set_by_file_and_line(
331 test,
332 file_name,
333 line_number,
334 extra_options=None,
335 num_expected_locations=1,
336 loc_exact=False,
337 module_name=None,
339 """Set a breakpoint by file and line, returning the breakpoint number.
341 If extra_options is not None, then we append it to the breakpoint set command.
343 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.
345 If loc_exact is true, we check that there is one location, and that location must be at the input file and line number.
348 if file_name is None:
349 command = "breakpoint set -l %d" % (line_number)
350 else:
351 command = 'breakpoint set -f "%s" -l %d' % (file_name, line_number)
353 if module_name:
354 command += " --shlib '%s'" % (module_name)
356 if extra_options:
357 command += " " + extra_options
359 break_results = run_break_set_command(test, command)
361 if num_expected_locations == 1 and loc_exact:
362 check_breakpoint_result(
363 test,
364 break_results,
365 num_locations=num_expected_locations,
366 file_name=file_name,
367 line_number=line_number,
368 module_name=module_name,
370 else:
371 check_breakpoint_result(
372 test, break_results, num_locations=num_expected_locations
375 return get_bpno_from_match(break_results)
378 def run_break_set_by_symbol(
379 test,
380 symbol,
381 extra_options=None,
382 num_expected_locations=-1,
383 sym_exact=False,
384 module_name=None,
386 """Set a breakpoint by symbol name. Common options are the same as run_break_set_by_file_and_line.
388 If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match.
390 command = 'breakpoint set -n "%s"' % (symbol)
392 if module_name:
393 command += " --shlib '%s'" % (module_name)
395 if extra_options:
396 command += " " + extra_options
398 break_results = run_break_set_command(test, command)
400 if num_expected_locations == 1 and sym_exact:
401 check_breakpoint_result(
402 test,
403 break_results,
404 num_locations=num_expected_locations,
405 symbol_name=symbol,
406 module_name=module_name,
408 else:
409 check_breakpoint_result(
410 test, break_results, num_locations=num_expected_locations
413 return get_bpno_from_match(break_results)
416 def run_break_set_by_selector(
417 test, selector, extra_options=None, num_expected_locations=-1, module_name=None
419 """Set a breakpoint by selector. Common options are the same as run_break_set_by_file_and_line."""
421 command = 'breakpoint set -S "%s"' % (selector)
423 if module_name:
424 command += ' --shlib "%s"' % (module_name)
426 if extra_options:
427 command += " " + extra_options
429 break_results = run_break_set_command(test, command)
431 if num_expected_locations == 1:
432 check_breakpoint_result(
433 test,
434 break_results,
435 num_locations=num_expected_locations,
436 symbol_name=selector,
437 symbol_match_exact=False,
438 module_name=module_name,
440 else:
441 check_breakpoint_result(
442 test, break_results, num_locations=num_expected_locations
445 return get_bpno_from_match(break_results)
448 def run_break_set_by_regexp(
449 test, regexp, extra_options=None, num_expected_locations=-1
451 """Set a breakpoint by regular expression match on symbol name. Common options are the same as run_break_set_by_file_and_line."""
453 command = 'breakpoint set -r "%s"' % (regexp)
454 if extra_options:
455 command += " " + extra_options
457 break_results = run_break_set_command(test, command)
459 check_breakpoint_result(test, break_results, num_locations=num_expected_locations)
461 return get_bpno_from_match(break_results)
464 def run_break_set_by_source_regexp(
465 test, regexp, extra_options=None, num_expected_locations=-1
467 """Set a breakpoint by source regular expression. Common options are the same as run_break_set_by_file_and_line."""
468 command = 'breakpoint set -p "%s"' % (regexp)
469 if extra_options:
470 command += " " + extra_options
472 break_results = run_break_set_command(test, command)
474 check_breakpoint_result(test, break_results, num_locations=num_expected_locations)
476 return get_bpno_from_match(break_results)
479 def 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.
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.
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."""
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]+)$",
503 match_object = test.match(command, patterns)
504 break_results = match_object.groupdict()
506 # We always insert the breakpoint number, setting it to -1 if we couldn't find it
507 # Also, make sure it gets stored as an integer.
508 if not "bpno" in break_results:
509 break_results["bpno"] = -1
510 else:
511 break_results["bpno"] = int(break_results["bpno"])
513 # We always insert the number of locations
514 # If ONE location is set for the breakpoint, then the output doesn't mention locations, but it has to be 1...
515 # We also make sure it is an integer.
517 if not "num_locations" in break_results:
518 num_locations = 1
519 else:
520 num_locations = break_results["num_locations"]
521 if num_locations == "no":
522 num_locations = 0
523 else:
524 num_locations = int(break_results["num_locations"])
526 break_results["num_locations"] = num_locations
528 if "line_no" in break_results:
529 break_results["line_no"] = int(break_results["line_no"])
531 return break_results
534 def get_bpno_from_match(break_results):
535 return int(break_results["bpno"])
538 def check_breakpoint_result(
539 test,
540 break_results,
541 file_name=None,
542 line_number=-1,
543 symbol_name=None,
544 symbol_match_exact=True,
545 module_name=None,
546 offset=-1,
547 num_locations=-1,
549 out_num_locations = break_results["num_locations"]
551 if num_locations == -1:
552 test.assertTrue(
553 out_num_locations > 0, "Expecting one or more locations, got none."
555 else:
556 test.assertTrue(
557 num_locations == out_num_locations,
558 "Expecting %d locations, got %d." % (num_locations, out_num_locations),
561 if file_name:
562 out_file_name = ""
563 if "file" in break_results:
564 out_file_name = break_results["file"]
565 test.assertTrue(
566 file_name == out_file_name,
567 "Breakpoint file name '%s' doesn't match resultant name '%s'."
568 % (file_name, out_file_name),
571 if line_number != -1:
572 out_file_line = -1
573 if "line_no" in break_results:
574 out_line_number = break_results["line_no"]
576 test.assertTrue(
577 line_number == out_line_number,
578 "Breakpoint line number %s doesn't match resultant line %s."
579 % (line_number, out_line_number),
582 if symbol_name:
583 out_symbol_name = ""
584 # Look first for the inlined symbol name, otherwise use the symbol
585 # name:
586 if "inline_symbol" in break_results and break_results["inline_symbol"]:
587 out_symbol_name = break_results["inline_symbol"]
588 elif "symbol" in break_results:
589 out_symbol_name = break_results["symbol"]
591 if symbol_match_exact:
592 test.assertTrue(
593 symbol_name == out_symbol_name,
594 "Symbol name '%s' doesn't match resultant symbol '%s'."
595 % (symbol_name, out_symbol_name),
597 else:
598 test.assertTrue(
599 out_symbol_name.find(symbol_name) != -1,
600 "Symbol name '%s' isn't in resultant symbol '%s'."
601 % (symbol_name, out_symbol_name),
604 if module_name:
605 out_nodule_name = None
606 if "module" in break_results:
607 out_module_name = break_results["module"]
609 test.assertTrue(
610 module_name.find(out_module_name) != -1,
611 "Symbol module name '%s' isn't in expected module name '%s'."
612 % (out_module_name, module_name),
616 # ==================================================
617 # Utility functions related to Threads and Processes
618 # ==================================================
621 def get_stopped_threads(process, reason):
622 """Returns the thread(s) with the specified stop reason in a list.
624 The list can be empty if no such thread exists.
626 threads = []
627 for t in process:
628 if t.GetStopReason() == reason:
629 threads.append(t)
630 return threads
633 def get_stopped_thread(process, reason):
634 """A convenience function which returns the first thread with the given stop
635 reason or None.
637 Example usages:
639 1. Get the stopped thread due to a breakpoint condition
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")
647 2. Get the thread stopped due to a breakpoint
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")
656 threads = get_stopped_threads(process, reason)
657 if len(threads) == 0:
658 return None
659 return threads[0]
662 def 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 = []
667 stopped_threads = get_stopped_threads(process, lldb.eStopReasonBreakpoint)
669 if len(stopped_threads) == 0:
670 return threads
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)
678 return threads
681 def 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)
690 def get_caller_symbol(thread):
692 Returns the symbol name for the call site of the leaf function.
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
704 def get_function_names(thread):
706 Returns a sequence of function names from the stack frames of this thread.
709 def GetFuncName(i):
710 return thread.GetFrameAtIndex(i).GetFunctionName()
712 return [GetFuncName(i) for i in range(thread.GetNumFrames())]
715 def get_symbol_names(thread):
717 Returns a sequence of symbols for this thread.
720 def GetSymbol(i):
721 return thread.GetFrameAtIndex(i).GetSymbol().GetName()
723 return [GetSymbol(i) for i in range(thread.GetNumFrames())]
726 def get_pc_addresses(thread):
728 Returns a sequence of pc addresses for this thread.
731 def GetPCAddress(i):
732 return thread.GetFrameAtIndex(i).GetPCAddress()
734 return [GetPCAddress(i) for i in range(thread.GetNumFrames())]
737 def get_filenames(thread):
739 Returns a sequence of file names from the stack frames of this thread.
742 def GetFilename(i):
743 return thread.GetFrameAtIndex(i).GetLineEntry().GetFileSpec().GetFilename()
745 return [GetFilename(i) for i in range(thread.GetNumFrames())]
748 def get_line_numbers(thread):
750 Returns a sequence of line numbers from the stack frames of this thread.
753 def GetLineNumber(i):
754 return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
756 return [GetLineNumber(i) for i in range(thread.GetNumFrames())]
759 def get_module_names(thread):
761 Returns a sequence of module names from the stack frames of this thread.
764 def GetModuleName(i):
765 return thread.GetFrameAtIndex(i).GetModule().GetFileSpec().GetFilename()
767 return [GetModuleName(i) for i in range(thread.GetNumFrames())]
770 def get_stack_frames(thread):
772 Returns a sequence of stack frames for this thread.
775 def GetStackFrame(i):
776 return thread.GetFrameAtIndex(i)
778 return [GetStackFrame(i) for i in range(thread.GetNumFrames())]
781 def print_stacktrace(thread, string_buffer=False):
782 """Prints a simple stack trace of this thread."""
784 output = io.StringIO() if string_buffer else sys.stdout
785 target = thread.GetProcess().GetTarget()
787 depth = thread.GetNumFrames()
789 mods = get_module_names(thread)
790 funcs = get_function_names(thread)
791 symbols = get_symbol_names(thread)
792 files = get_filenames(thread)
793 lines = get_line_numbers(thread)
794 addrs = get_pc_addresses(thread)
796 if thread.GetStopReason() != lldb.eStopReasonInvalid:
797 desc = "stop reason=" + stop_reason_to_str(thread.GetStopReason())
798 else:
799 desc = ""
800 print(
801 "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
802 thread.GetThreadID(), thread.GetName(), thread.GetQueueName()
804 + desc,
805 file=output,
808 for i in range(depth):
809 frame = thread.GetFrameAtIndex(i)
810 function = frame.GetFunction()
812 load_addr = addrs[i].GetLoadAddress(target)
813 if not function:
814 file_addr = addrs[i].GetFileAddress()
815 start_addr = frame.GetSymbol().GetStartAddress().GetFileAddress()
816 symbol_offset = file_addr - start_addr
817 print(
818 " frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format(
819 num=i,
820 addr=load_addr,
821 mod=mods[i],
822 symbol=symbols[i],
823 offset=symbol_offset,
825 file=output,
827 else:
828 print(
829 " frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format(
830 num=i,
831 addr=load_addr,
832 mod=mods[i],
833 func="%s [inlined]" % funcs[i] if frame.IsInlined() else funcs[i],
834 file=files[i],
835 line=lines[i],
836 args=get_args_as_string(frame, showFuncName=False)
837 if not frame.IsInlined()
838 else "()",
840 file=output,
843 if string_buffer:
844 return output.getvalue()
847 def print_stacktraces(process, string_buffer=False):
848 """Prints the stack traces of all the threads."""
850 output = io.StringIO() if string_buffer else sys.stdout
852 print("Stack traces for " + str(process), file=output)
854 for thread in process:
855 print(print_stacktrace(thread, string_buffer=True), file=output)
857 if string_buffer:
858 return output.getvalue()
861 # ===================================
862 # Utility functions related to Frames
863 # ===================================
866 def get_parent_frame(frame):
868 Returns the parent frame of the input frame object; None if not available.
870 thread = frame.GetThread()
871 parent_found = False
872 for f in thread:
873 if parent_found:
874 return f
875 if f.GetFrameID() == frame.GetFrameID():
876 parent_found = True
878 # If we reach here, no parent has been found, return None.
879 return None
882 def get_args_as_string(frame, showFuncName=True):
884 Returns the args of the input frame object as a string.
886 # arguments => True
887 # locals => False
888 # statics => False
889 # in_scope_only => True
890 vars = frame.GetVariables(True, False, False, True) # type of SBValueList
891 args = [] # list of strings
892 for var in vars:
893 args.append("(%s)%s=%s" % (var.GetTypeName(), var.GetName(), var.GetValue()))
894 if frame.GetFunction():
895 name = frame.GetFunction().GetName()
896 elif frame.GetSymbol():
897 name = frame.GetSymbol().GetName()
898 else:
899 name = ""
900 if showFuncName:
901 return "%s(%s)" % (name, ", ".join(args))
902 else:
903 return "(%s)" % (", ".join(args))
906 def print_registers(frame, string_buffer=False):
907 """Prints all the register sets of the frame."""
909 output = io.StringIO() if string_buffer else sys.stdout
911 print("Register sets for " + str(frame), file=output)
913 registerSet = frame.GetRegisters() # Return type of SBValueList.
914 print(
915 "Frame registers (size of register set = %d):" % registerSet.GetSize(),
916 file=output,
918 for value in registerSet:
919 # print >> output, value
920 print(
921 "%s (number of children = %d):" % (value.GetName(), value.GetNumChildren()),
922 file=output,
924 for child in value:
925 print(
926 "Name: %s, Value: %s" % (child.GetName(), child.GetValue()), file=output
929 if string_buffer:
930 return output.getvalue()
933 def get_registers(frame, kind):
934 """Returns the registers given the frame and the kind of registers desired.
936 Returns None if there's no such kind.
938 registerSet = frame.GetRegisters() # Return type of SBValueList.
939 for value in registerSet:
940 if kind.lower() in value.GetName().lower():
941 return value
943 return None
946 def get_GPRs(frame):
947 """Returns the general purpose registers of the frame as an SBValue.
949 The returned SBValue object is iterable. An example:
951 from lldbutil import get_GPRs
952 regs = get_GPRs(frame)
953 for reg in regs:
954 print "%s => %s" % (reg.GetName(), reg.GetValue())
957 return get_registers(frame, "general purpose")
960 def get_FPRs(frame):
961 """Returns the floating point registers of the frame as an SBValue.
963 The returned SBValue object is iterable. An example:
965 from lldbutil import get_FPRs
966 regs = get_FPRs(frame)
967 for reg in regs:
968 print "%s => %s" % (reg.GetName(), reg.GetValue())
971 return get_registers(frame, "floating point")
974 def get_ESRs(frame):
975 """Returns the exception state registers of the frame as an SBValue.
977 The returned SBValue object is iterable. An example:
979 from lldbutil import get_ESRs
980 regs = get_ESRs(frame)
981 for reg in regs:
982 print "%s => %s" % (reg.GetName(), reg.GetValue())
985 return get_registers(frame, "exception state")
988 # ======================================
989 # Utility classes/functions for SBValues
990 # ======================================
993 class BasicFormatter(object):
994 """The basic formatter inspects the value object and prints the value."""
996 def format(self, value, buffer=None, indent=0):
997 if not buffer:
998 output = io.StringIO()
999 else:
1000 output = buffer
1001 # If there is a summary, it suffices.
1002 val = value.GetSummary()
1003 # Otherwise, get the value.
1004 if val is None:
1005 val = value.GetValue()
1006 if val is None and value.GetNumChildren() > 0:
1007 val = "%s (location)" % value.GetLocation()
1008 print(
1009 "{indentation}({type}) {name} = {value}".format(
1010 indentation=" " * indent,
1011 type=value.GetTypeName(),
1012 name=value.GetName(),
1013 value=val,
1015 file=output,
1017 return output.getvalue()
1020 class ChildVisitingFormatter(BasicFormatter):
1021 """The child visiting formatter prints the value and its immediate children.
1023 The constructor takes a keyword arg: indent_child, which defaults to 2.
1026 def __init__(self, indent_child=2):
1027 """Default indentation of 2 SPC's for the children."""
1028 self.cindent = indent_child
1030 def format(self, value, buffer=None):
1031 if not buffer:
1032 output = io.StringIO()
1033 else:
1034 output = buffer
1036 BasicFormatter.format(self, value, buffer=output)
1037 for child in value:
1038 BasicFormatter.format(self, child, buffer=output, indent=self.cindent)
1040 return output.getvalue()
1043 class RecursiveDecentFormatter(BasicFormatter):
1044 """The recursive decent formatter prints the value and the decendents.
1046 The constructor takes two keyword args: indent_level, which defaults to 0,
1047 and indent_child, which defaults to 2. The current indentation level is
1048 determined by indent_level, while the immediate children has an additional
1049 indentation by inden_child.
1052 def __init__(self, indent_level=0, indent_child=2):
1053 self.lindent = indent_level
1054 self.cindent = indent_child
1056 def format(self, value, buffer=None):
1057 if not buffer:
1058 output = io.StringIO()
1059 else:
1060 output = buffer
1062 BasicFormatter.format(self, value, buffer=output, indent=self.lindent)
1063 new_indent = self.lindent + self.cindent
1064 for child in value:
1065 if child.GetSummary() is not None:
1066 BasicFormatter.format(self, child, buffer=output, indent=new_indent)
1067 else:
1068 if child.GetNumChildren() > 0:
1069 rdf = RecursiveDecentFormatter(indent_level=new_indent)
1070 rdf.format(child, buffer=output)
1071 else:
1072 BasicFormatter.format(self, child, buffer=output, indent=new_indent)
1074 return output.getvalue()