Newer
Older
Johnny Chen
committed
"""
This LLDB module contains miscellaneous utilities.
Johnny Chen
committed
"""
import lldb
import sys
import StringIO
Johnny Chen
committed
################################################
# #
# Iterator for lldb aggregate data structures. #
# #
################################################
Johnny Chen
committed
def lldb_iter(obj, getsize, getelem):
Johnny Chen
committed
"""
A generator adaptor for lldb aggregate data structures.
Johnny Chen
committed
API clients pass in the aggregate object, the name of the method to get the
size of the object, and the name of the method to get the element given an
index.
Johnny Chen
committed
Example usage:
def disassemble_instructions (insts):
Johnny Chen
committed
from lldbutil import lldb_iter
for i in lldb_iter(insts, 'GetSize', 'GetInstructionAtIndex'):
Johnny Chen
committed
print i
"""
Johnny Chen
committed
size = getattr(obj, getsize)
elem = getattr(obj, getelem)
for i in range(size()):
yield elem(i)
Johnny Chen
committed
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
########################################################
# #
# Convert some enum value to its string's counterpart. #
# #
########################################################
def StateTypeString(enum):
"""Returns the stateType string given an enum."""
if enum == lldb.eStateInvalid:
return "Invalid"
elif enum == lldb.eStateUnloaded:
return "Unloaded"
elif enum == lldb.eStateAttaching:
return "Attaching"
elif enum == lldb.eStateLaunching:
return "Launching"
elif enum == lldb.eStateStopped:
return "Stopped"
elif enum == lldb.eStateRunning:
return "Running"
elif enum == lldb.eStateStepping:
return "Stepping"
elif enum == lldb.eStateCrashed:
return "Crashed"
elif enum == lldb.eStateDetached:
return "Detached"
elif enum == lldb.eStateExited:
return "Exited"
elif enum == lldb.eStateSuspended:
return "Suspended"
else:
raise Exception("Unknown stopReason enum")
def StopReasonString(enum):
"""Returns the stopReason string given an enum."""
if enum == lldb.eStopReasonInvalid:
return "Invalid"
elif enum == lldb.eStopReasonNone:
return "None"
elif enum == lldb.eStopReasonTrace:
return "Trace"
elif enum == lldb.eStopReasonBreakpoint:
return "Breakpoint"
elif enum == lldb.eStopReasonWatchpoint:
return "Watchpoint"
elif enum == lldb.eStopReasonSignal:
return "Signal"
elif enum == lldb.eStopReasonException:
return "Exception"
elif enum == lldb.eStopReasonPlanComplete:
return "PlanComplete"
else:
raise Exception("Unknown stopReason enum")
#######################################################
# #
# Utility functions related to Threads and Processes. #
# #
#######################################################
Johnny Chen
committed
def GetFunctionNames(thread):
"""
Returns a sequence of function names from the stack frames of this thread.
"""
def GetFuncName(i):
return thread.GetFrameAtIndex(i).GetFunction().GetName()
return map(GetFuncName, range(thread.GetNumFrames()))
def GetSymbolNames(thread):
"""
Returns a sequence of symbols for this thread.
"""
def GetSymbol(i):
return thread.GetFrameAtIndex(i).GetSymbol().GetName()
return map(GetSymbol, range(thread.GetNumFrames()))
def GetPCAddresses(thread):
"""
Returns a sequence of pc addresses for this thread.
"""
def GetPCAddress(i):
return thread.GetFrameAtIndex(i).GetPCAddress()
return map(GetPCAddress, range(thread.GetNumFrames()))
Johnny Chen
committed
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
def GetFilenames(thread):
"""
Returns a sequence of file names from the stack frames of this thread.
"""
def GetFilename(i):
return thread.GetFrameAtIndex(i).GetLineEntry().GetFileSpec().GetFilename()
return map(GetFilename, range(thread.GetNumFrames()))
def GetLineNumbers(thread):
"""
Returns a sequence of line numbers from the stack frames of this thread.
"""
def GetLineNumber(i):
return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
return map(GetLineNumber, range(thread.GetNumFrames()))
def GetModuleNames(thread):
"""
Returns a sequence of module names from the stack frames of this thread.
"""
def GetModuleName(i):
return thread.GetFrameAtIndex(i).GetModule().GetFileSpec().GetFilename()
return map(GetModuleName, range(thread.GetNumFrames()))
def GetStackFrames(thread):
"""
Returns a sequence of stack frames for this thread.
"""
def GetStackFrame(i):
return thread.GetFrameAtIndex(i)
return map(GetStackFrame, range(thread.GetNumFrames()))
def PrintStackTrace(thread, string_buffer = False):
Johnny Chen
committed
"""Prints a simple stack trace of this thread."""
output = StringIO.StringIO() if string_buffer else sys.stdout
target = thread.GetProcess().GetTarget()
Johnny Chen
committed
depth = thread.GetNumFrames()
mods = GetModuleNames(thread)
funcs = GetFunctionNames(thread)
symbols = GetSymbolNames(thread)
Johnny Chen
committed
files = GetFilenames(thread)
lines = GetLineNumbers(thread)
addrs = GetPCAddresses(thread)
print >> output, "Stack trace for thread id={0:#x} name={1} queue={2}:".format(
Johnny Chen
committed
thread.GetThreadID(), thread.GetName(), thread.GetQueueName())
for i in range(depth):
frame = thread.GetFrameAtIndex(i)
function = frame.GetFunction()
load_addr = addrs[i].GetLoadAddress(target)
if not function.IsValid():
file_addr = addrs[i].GetFileAddress()
print >> output, " frame #{num}: {addr:#016x} {mod}`{symbol} + ????".format(
num=i, addr=load_addr, mod=mods[i], symbol=symbols[i])
else:
print >> output, " frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line}".format(
num=i, addr=load_addr, mod=mods[i], func=funcs[i], file=files[i], line=lines[i])
if string_buffer:
return output.getvalue()
def PrintStackTraces(process, string_buffer = False):
"""Prints the stack traces of all the threads."""
output = StringIO.StringIO() if string_buffer else sys.stdout
print >> output, "Stack traces for " + repr(process)
Johnny Chen
committed
for i in range(process.GetNumThreads()):
print >> output, PrintStackTrace(process.GetThreadAtIndex(i), string_buffer=True)
if string_buffer:
return output.getvalue()