blob: b4a6e40bdcab64457f777cca17f52f3cbfd1d73a [file] [log] [blame]
"""
This LLDB module contains miscellaneous utilities.
"""
import lldb
import sys
import StringIO
# ===========================================
# Iterator for lldb aggregate data structures
# ===========================================
def lldb_iter(obj, getsize, getelem):
"""
A generator adaptor for lldb aggregate data structures.
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.
Example usage:
def disassemble_instructions (insts):
from lldbutil import lldb_iter
for i in lldb_iter(insts, 'GetSize', 'GetInstructionAtIndex'):
print i
"""
size = getattr(obj, getsize)
elem = getattr(obj, getelem)
for i in range(size()):
yield elem(i)
# =================================================
# Convert some enum value to its string 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")
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
# ==================================================
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()))
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):
"""Prints a simple stack trace of this thread."""
output = StringIO.StringIO() if string_buffer else sys.stdout
target = thread.GetProcess().GetTarget()
depth = thread.GetNumFrames()
mods = GetModuleNames(thread)
funcs = GetFunctionNames(thread)
symbols = GetSymbolNames(thread)
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
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)
for i in range(process.GetNumThreads()):
print >> output, PrintStackTrace(process.GetThreadAtIndex(i), string_buffer=True)
if string_buffer:
return output.getvalue()