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.
API clients pass in an aggregate object or a container of it, the name of
the method to get the size of the aggregate, and the name of the method to
get the element by index.
Johnny Chen
committed
Johnny Chen
committed
Example usages:
Johnny Chen
committed
Johnny Chen
committed
1. Pass an aggregate as the first argument:
Johnny Chen
committed
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
2. Pass a container of aggregate which provides APIs to get to the size and
the element of the aggregate:
# Module is a container of symbol table
module = target.FindModule(filespec)
for symbol in lldb_iter(module, 'GetNumSymbols', 'GetSymbolAtIndex'):
name = symbol.GetName()
...
Johnny Chen
committed
"""
Johnny Chen
committed
size = getattr(obj, getsize)
elem = getattr(obj, getelem)
for i in range(size()):
yield elem(i)
Johnny Chen
committed
# =================================================
# Convert some enum value to its string counterpart
# =================================================
def StateTypeString(enum):
"""Returns the stateType string given an enum."""
if enum == lldb.eStateInvalid:
Johnny Chen
committed
return "invalid"
elif enum == lldb.eStateUnloaded:
Johnny Chen
committed
return "unloaded"
elif enum == lldb.eStateAttaching:
Johnny Chen
committed
return "attaching"
elif enum == lldb.eStateLaunching:
Johnny Chen
committed
return "launching"
elif enum == lldb.eStateStopped:
Johnny Chen
committed
return "stopped"
elif enum == lldb.eStateRunning:
Johnny Chen
committed
return "running"
elif enum == lldb.eStateStepping:
Johnny Chen
committed
return "stepping"
elif enum == lldb.eStateCrashed:
Johnny Chen
committed
return "crashed"
elif enum == lldb.eStateDetached:
Johnny Chen
committed
return "detached"
elif enum == lldb.eStateExited:
Johnny Chen
committed
return "exited"
elif enum == lldb.eStateSuspended:
Johnny Chen
committed
return "suspended"
else:
raise Exception("Unknown stopReason enum")
def StopReasonString(enum):
"""Returns the stopReason string given an enum."""
if enum == lldb.eStopReasonInvalid:
Johnny Chen
committed
return "invalid"
elif enum == lldb.eStopReasonNone:
Johnny Chen
committed
return "none"
elif enum == lldb.eStopReasonTrace:
Johnny Chen
committed
return "trace"
elif enum == lldb.eStopReasonBreakpoint:
Johnny Chen
committed
return "breakpoint"
elif enum == lldb.eStopReasonWatchpoint:
Johnny Chen
committed
return "watchpoint"
elif enum == lldb.eStopReasonSignal:
Johnny Chen
committed
return "signal"
elif enum == lldb.eStopReasonException:
Johnny Chen
committed
return "exception"
elif enum == lldb.eStopReasonPlanComplete:
Johnny Chen
committed
return "plancomplete"
else:
raise Exception("Unknown stopReason enum")
Johnny Chen
committed
def ValueTypeString(enum):
"""Returns the valueType string given an enum."""
if enum == lldb.eValueTypeInvalid:
return "invalid"
elif enum == lldb.eValueTypeVariableGlobal:
return "global_variable"
elif enum == lldb.eValueTypeVariableStatic:
return "static_variable"
elif enum == lldb.eValueTypeVariableArgument:
return "argument_variable"
elif enum == lldb.eValueTypeVariableLocal:
return "local_variable"
elif enum == lldb.eValueTypeRegister:
return "register"
elif enum == lldb.eValueTypeRegisterSet:
return "register_set"
elif enum == lldb.eValueTypeConstResult:
return "constant_result"
else:
raise Exception("Unknown valueType 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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
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)
if thread.GetStopReason() != lldb.eStopReasonInvalid:
desc = "stop reason=" + StopReasonString(thread.GetStopReason())
else:
desc = ""
print >> output, "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
thread.GetThreadID(), thread.GetName(), thread.GetQueueName()) + desc
Johnny Chen
committed
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()