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
# =================================================
# 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")
# ==================================================
# 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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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()