blob: 46314647d84a0b7220258e5f1690384a58f75a9c [file] [log] [blame]
Johnny Chen1605cf62010-09-08 22:54:46 +00001"""
Johnny Chenb51d87d2010-10-07 21:38:28 +00002This LLDB module contains miscellaneous utilities.
Johnny Chen1605cf62010-09-08 22:54:46 +00003"""
4
5import lldb
Johnny Chen30425e92010-10-07 18:52:48 +00006import sys
Johnny Chened5f04e2010-10-15 23:33:18 +00007import StringIO
Johnny Chen1605cf62010-09-08 22:54:46 +00008
Johnny Chen77356a02011-03-03 01:41:57 +00009# ===========================================
10# Iterator for lldb aggregate data structures
11# ===========================================
12
13def lldb_iter(obj, getsize, getelem):
14 """A generator adaptor for lldb aggregate data structures.
15
16 API clients pass in an aggregate object or a container of it, the name of
17 the method to get the size of the aggregate, and the name of the method to
18 get the element by index.
19
20 Example usages:
21
22 1. Pass an aggregate as the first argument:
23
24 def disassemble_instructions (insts):
25 from lldbutil import lldb_iter
26 for i in lldb_iter(insts, 'GetSize', 'GetInstructionAtIndex'):
27 print i
28
29 2. Pass a container of aggregate which provides APIs to get to the size and
30 the element of the aggregate:
31
32 # Module is a container of symbol table
33 module = target.FindModule(filespec)
34 for symbol in lldb_iter(module, 'GetNumSymbols', 'GetSymbolAtIndex'):
35 name = symbol.GetName()
36 ...
37 """
38 size = getattr(obj, getsize)
39 elem = getattr(obj, getelem)
40 for i in range(size()):
41 yield elem(i)
42
43
Johnny Chen51ed1b62011-03-03 19:14:00 +000044# ===================================================
45# Disassembly for an SBFunction or an SBSymbol object
46# ===================================================
47
48def disassemble(target, function_or_symbol):
49 """Disassemble the function or symbol given a target.
50
51 It returns the disassembly content in a string object.
52 """
53 buf = StringIO.StringIO()
54 insts = function_or_symbol.GetInstructions(target)
55 for i in lldb_iter(insts, 'GetSize', 'GetInstructionAtIndex'):
56 print >> buf, i
57 return buf.getvalue()
58
59
Johnny Chen4c70f282011-03-02 01:36:45 +000060# ==========================================================
61# Integer (byte size 1, 2, 4, and 8) to bytearray conversion
62# ==========================================================
63
64def int_to_bytearray(val, bytesize):
65 """Utility function to convert an integer into a bytearray.
66
Johnny Chend2765fc2011-03-02 20:54:22 +000067 It returns the bytearray in the little endian format. It is easy to get the
68 big endian format, just do ba.reverse() on the returned object.
Johnny Chen4c70f282011-03-02 01:36:45 +000069 """
70 from struct import *
71
72 if bytesize == 1:
73 return bytearray([val])
74
75 # Little endian followed by a format character.
76 template = "<%c"
77 if bytesize == 2:
78 fmt = template % 'h'
79 elif bytesize == 4:
80 fmt = template % 'i'
81 elif bytesize == 4:
82 fmt = template % 'q'
83 else:
84 return None
85
86 packed = pack(fmt, val)
87 return bytearray(map(ord, packed))
88
89def bytearray_to_int(bytes, bytesize):
90 """Utility function to convert a bytearray into an integer.
91
Johnny Chend2765fc2011-03-02 20:54:22 +000092 It interprets the bytearray in the little endian format. For a big endian
93 bytearray, just do ba.reverse() on the object before passing it in.
Johnny Chen4c70f282011-03-02 01:36:45 +000094 """
95 from struct import *
96
97 if bytesize == 1:
98 return ba[0]
99
100 # Little endian followed by a format character.
101 template = "<%c"
102 if bytesize == 2:
103 fmt = template % 'h'
104 elif bytesize == 4:
105 fmt = template % 'i'
106 elif bytesize == 4:
107 fmt = template % 'q'
108 else:
109 return None
110
111 unpacked = unpack(fmt, str(bytes))
112 return unpacked[0]
113
114
Johnny Chen77356a02011-03-03 01:41:57 +0000115# ===========================================================
116# Returns the list of stopped thread(s) given an lldb process
117# ===========================================================
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000118
Johnny Chen77356a02011-03-03 01:41:57 +0000119def get_stopped_threads(process, reason):
120 """Returns the thread(s) with the specified stop reason in a list."""
121 threads = []
122 for t in lldb_iter(process, 'GetNumThreads', 'GetThreadAtIndex'):
123 if t.GetStopReason() == reason:
124 threads.append(t)
125 return threads
Johnny Chen164bf882010-10-09 01:31:09 +0000126
Johnny Chen77356a02011-03-03 01:41:57 +0000127def get_stopped_thread(process, reason):
128 """A convenience function which returns the first thread with the given stop
129 reason or None.
Johnny Chen164bf882010-10-09 01:31:09 +0000130
Johnny Chendeaf8842010-12-08 19:19:08 +0000131 Example usages:
132
Johnny Chen77356a02011-03-03 01:41:57 +0000133 1. Get the stopped thread due to a breakpoint condition
Johnny Chen164bf882010-10-09 01:31:09 +0000134
Johnny Chen77356a02011-03-03 01:41:57 +0000135 ...
136 from lldbutil import get_stopped_thread
137 thread = get_stopped_thread(self.process, lldb.eStopReasonPlanComplete)
138 self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint condition")
139 ...
Johnny Chendeaf8842010-12-08 19:19:08 +0000140
Johnny Chen77356a02011-03-03 01:41:57 +0000141 2. Get the thread stopped due to a breakpoint
Johnny Chendeaf8842010-12-08 19:19:08 +0000142
Johnny Chen77356a02011-03-03 01:41:57 +0000143 ...
144 from lldbutil import get_stopped_thread
145 thread = get_stopped_thread(self.process, lldb.eStopReasonBreakpoint)
146 self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint")
147 ...
148
Johnny Chen164bf882010-10-09 01:31:09 +0000149 """
Johnny Chen77356a02011-03-03 01:41:57 +0000150 threads = get_stopped_threads(process, reason)
151 if len(threads) == 0:
152 return None
153 return threads[0]
Johnny Chen164bf882010-10-09 01:31:09 +0000154
Johnny Chen168a61a2010-10-22 21:31:03 +0000155# =================================================
156# Convert some enum value to its string counterpart
157# =================================================
Johnny Chenbe683bc2010-10-07 22:15:58 +0000158
159def StateTypeString(enum):
160 """Returns the stateType string given an enum."""
161 if enum == lldb.eStateInvalid:
Johnny Chen59b84772010-10-18 15:46:54 +0000162 return "invalid"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000163 elif enum == lldb.eStateUnloaded:
Johnny Chen59b84772010-10-18 15:46:54 +0000164 return "unloaded"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000165 elif enum == lldb.eStateAttaching:
Johnny Chen59b84772010-10-18 15:46:54 +0000166 return "attaching"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000167 elif enum == lldb.eStateLaunching:
Johnny Chen59b84772010-10-18 15:46:54 +0000168 return "launching"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000169 elif enum == lldb.eStateStopped:
Johnny Chen59b84772010-10-18 15:46:54 +0000170 return "stopped"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000171 elif enum == lldb.eStateRunning:
Johnny Chen59b84772010-10-18 15:46:54 +0000172 return "running"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000173 elif enum == lldb.eStateStepping:
Johnny Chen59b84772010-10-18 15:46:54 +0000174 return "stepping"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000175 elif enum == lldb.eStateCrashed:
Johnny Chen59b84772010-10-18 15:46:54 +0000176 return "crashed"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000177 elif enum == lldb.eStateDetached:
Johnny Chen59b84772010-10-18 15:46:54 +0000178 return "detached"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000179 elif enum == lldb.eStateExited:
Johnny Chen59b84772010-10-18 15:46:54 +0000180 return "exited"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000181 elif enum == lldb.eStateSuspended:
Johnny Chen59b84772010-10-18 15:46:54 +0000182 return "suspended"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000183 else:
184 raise Exception("Unknown stopReason enum")
185
186def StopReasonString(enum):
187 """Returns the stopReason string given an enum."""
188 if enum == lldb.eStopReasonInvalid:
Johnny Chen59b84772010-10-18 15:46:54 +0000189 return "invalid"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000190 elif enum == lldb.eStopReasonNone:
Johnny Chen59b84772010-10-18 15:46:54 +0000191 return "none"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000192 elif enum == lldb.eStopReasonTrace:
Johnny Chen59b84772010-10-18 15:46:54 +0000193 return "trace"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000194 elif enum == lldb.eStopReasonBreakpoint:
Johnny Chen59b84772010-10-18 15:46:54 +0000195 return "breakpoint"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000196 elif enum == lldb.eStopReasonWatchpoint:
Johnny Chen59b84772010-10-18 15:46:54 +0000197 return "watchpoint"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000198 elif enum == lldb.eStopReasonSignal:
Johnny Chen59b84772010-10-18 15:46:54 +0000199 return "signal"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000200 elif enum == lldb.eStopReasonException:
Johnny Chen59b84772010-10-18 15:46:54 +0000201 return "exception"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000202 elif enum == lldb.eStopReasonPlanComplete:
Johnny Chen59b84772010-10-18 15:46:54 +0000203 return "plancomplete"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000204 else:
205 raise Exception("Unknown stopReason enum")
206
Johnny Chen2c8d1592010-11-03 21:37:58 +0000207def ValueTypeString(enum):
208 """Returns the valueType string given an enum."""
209 if enum == lldb.eValueTypeInvalid:
210 return "invalid"
211 elif enum == lldb.eValueTypeVariableGlobal:
212 return "global_variable"
213 elif enum == lldb.eValueTypeVariableStatic:
214 return "static_variable"
215 elif enum == lldb.eValueTypeVariableArgument:
216 return "argument_variable"
217 elif enum == lldb.eValueTypeVariableLocal:
218 return "local_variable"
219 elif enum == lldb.eValueTypeRegister:
220 return "register"
221 elif enum == lldb.eValueTypeRegisterSet:
222 return "register_set"
223 elif enum == lldb.eValueTypeConstResult:
224 return "constant_result"
225 else:
226 raise Exception("Unknown valueType enum")
227
Johnny Chenbe683bc2010-10-07 22:15:58 +0000228
Johnny Chen168a61a2010-10-22 21:31:03 +0000229# ==================================================
230# Utility functions related to Threads and Processes
231# ==================================================
Johnny Chenbe683bc2010-10-07 22:15:58 +0000232
Johnny Chen1605cf62010-09-08 22:54:46 +0000233def GetFunctionNames(thread):
234 """
235 Returns a sequence of function names from the stack frames of this thread.
236 """
237 def GetFuncName(i):
238 return thread.GetFrameAtIndex(i).GetFunction().GetName()
239
240 return map(GetFuncName, range(thread.GetNumFrames()))
241
242
Johnny Chenb51d87d2010-10-07 21:38:28 +0000243def GetSymbolNames(thread):
244 """
245 Returns a sequence of symbols for this thread.
246 """
247 def GetSymbol(i):
248 return thread.GetFrameAtIndex(i).GetSymbol().GetName()
249
250 return map(GetSymbol, range(thread.GetNumFrames()))
251
252
253def GetPCAddresses(thread):
254 """
255 Returns a sequence of pc addresses for this thread.
256 """
257 def GetPCAddress(i):
258 return thread.GetFrameAtIndex(i).GetPCAddress()
259
260 return map(GetPCAddress, range(thread.GetNumFrames()))
261
262
Johnny Chen1605cf62010-09-08 22:54:46 +0000263def GetFilenames(thread):
264 """
265 Returns a sequence of file names from the stack frames of this thread.
266 """
267 def GetFilename(i):
268 return thread.GetFrameAtIndex(i).GetLineEntry().GetFileSpec().GetFilename()
269
270 return map(GetFilename, range(thread.GetNumFrames()))
271
272
273def GetLineNumbers(thread):
274 """
275 Returns a sequence of line numbers from the stack frames of this thread.
276 """
277 def GetLineNumber(i):
278 return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
279
280 return map(GetLineNumber, range(thread.GetNumFrames()))
281
282
283def GetModuleNames(thread):
284 """
285 Returns a sequence of module names from the stack frames of this thread.
286 """
287 def GetModuleName(i):
288 return thread.GetFrameAtIndex(i).GetModule().GetFileSpec().GetFilename()
289
290 return map(GetModuleName, range(thread.GetNumFrames()))
291
292
Johnny Chen88866ac2010-09-09 00:55:07 +0000293def GetStackFrames(thread):
294 """
295 Returns a sequence of stack frames for this thread.
296 """
297 def GetStackFrame(i):
298 return thread.GetFrameAtIndex(i)
299
300 return map(GetStackFrame, range(thread.GetNumFrames()))
301
302
Johnny Chen30425e92010-10-07 18:52:48 +0000303def PrintStackTrace(thread, string_buffer = False):
Johnny Chen1605cf62010-09-08 22:54:46 +0000304 """Prints a simple stack trace of this thread."""
Johnny Chen30425e92010-10-07 18:52:48 +0000305
Johnny Chened5f04e2010-10-15 23:33:18 +0000306 output = StringIO.StringIO() if string_buffer else sys.stdout
Johnny Chenb51d87d2010-10-07 21:38:28 +0000307 target = thread.GetProcess().GetTarget()
308
Johnny Chen1605cf62010-09-08 22:54:46 +0000309 depth = thread.GetNumFrames()
310
311 mods = GetModuleNames(thread)
312 funcs = GetFunctionNames(thread)
Johnny Chenb51d87d2010-10-07 21:38:28 +0000313 symbols = GetSymbolNames(thread)
Johnny Chen1605cf62010-09-08 22:54:46 +0000314 files = GetFilenames(thread)
315 lines = GetLineNumbers(thread)
Johnny Chenb51d87d2010-10-07 21:38:28 +0000316 addrs = GetPCAddresses(thread)
Johnny Chen30425e92010-10-07 18:52:48 +0000317
Johnny Chenad5fd402010-10-25 19:13:52 +0000318 if thread.GetStopReason() != lldb.eStopReasonInvalid:
319 desc = "stop reason=" + StopReasonString(thread.GetStopReason())
320 else:
321 desc = ""
322 print >> output, "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
323 thread.GetThreadID(), thread.GetName(), thread.GetQueueName()) + desc
Johnny Chen1605cf62010-09-08 22:54:46 +0000324
Johnny Chenb51d87d2010-10-07 21:38:28 +0000325 for i in range(depth):
326 frame = thread.GetFrameAtIndex(i)
327 function = frame.GetFunction()
Johnny Chen1605cf62010-09-08 22:54:46 +0000328
Johnny Chenb51d87d2010-10-07 21:38:28 +0000329 load_addr = addrs[i].GetLoadAddress(target)
330 if not function.IsValid():
331 file_addr = addrs[i].GetFileAddress()
332 print >> output, " frame #{num}: {addr:#016x} {mod}`{symbol} + ????".format(
333 num=i, addr=load_addr, mod=mods[i], symbol=symbols[i])
334 else:
335 print >> output, " frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line}".format(
336 num=i, addr=load_addr, mod=mods[i], func=funcs[i], file=files[i], line=lines[i])
337
338 if string_buffer:
Johnny Chened5f04e2010-10-15 23:33:18 +0000339 return output.getvalue()
Johnny Chenb51d87d2010-10-07 21:38:28 +0000340
341
342def PrintStackTraces(process, string_buffer = False):
343 """Prints the stack traces of all the threads."""
344
Johnny Chened5f04e2010-10-15 23:33:18 +0000345 output = StringIO.StringIO() if string_buffer else sys.stdout
Johnny Chenb51d87d2010-10-07 21:38:28 +0000346
347 print >> output, "Stack traces for " + repr(process)
348
349 for i in range(process.GetNumThreads()):
350 print >> output, PrintStackTrace(process.GetThreadAtIndex(i), string_buffer=True)
Johnny Chen30425e92010-10-07 18:52:48 +0000351
352 if string_buffer:
Johnny Chened5f04e2010-10-15 23:33:18 +0000353 return output.getvalue()