blob: e7a8572bbd552269c9b51af6eb96b5cf90c1f203 [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 Chen42da4da2011-03-05 01:20:11 +0000165 elif enum == lldb.eStateConnected:
166 return "connected"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000167 elif enum == lldb.eStateAttaching:
Johnny Chen59b84772010-10-18 15:46:54 +0000168 return "attaching"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000169 elif enum == lldb.eStateLaunching:
Johnny Chen59b84772010-10-18 15:46:54 +0000170 return "launching"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000171 elif enum == lldb.eStateStopped:
Johnny Chen59b84772010-10-18 15:46:54 +0000172 return "stopped"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000173 elif enum == lldb.eStateRunning:
Johnny Chen59b84772010-10-18 15:46:54 +0000174 return "running"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000175 elif enum == lldb.eStateStepping:
Johnny Chen59b84772010-10-18 15:46:54 +0000176 return "stepping"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000177 elif enum == lldb.eStateCrashed:
Johnny Chen59b84772010-10-18 15:46:54 +0000178 return "crashed"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000179 elif enum == lldb.eStateDetached:
Johnny Chen59b84772010-10-18 15:46:54 +0000180 return "detached"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000181 elif enum == lldb.eStateExited:
Johnny Chen59b84772010-10-18 15:46:54 +0000182 return "exited"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000183 elif enum == lldb.eStateSuspended:
Johnny Chen59b84772010-10-18 15:46:54 +0000184 return "suspended"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000185 else:
Johnny Chen42da4da2011-03-05 01:20:11 +0000186 raise Exception("Unknown StateType enum")
Johnny Chenbe683bc2010-10-07 22:15:58 +0000187
188def StopReasonString(enum):
189 """Returns the stopReason string given an enum."""
190 if enum == lldb.eStopReasonInvalid:
Johnny Chen59b84772010-10-18 15:46:54 +0000191 return "invalid"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000192 elif enum == lldb.eStopReasonNone:
Johnny Chen59b84772010-10-18 15:46:54 +0000193 return "none"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000194 elif enum == lldb.eStopReasonTrace:
Johnny Chen59b84772010-10-18 15:46:54 +0000195 return "trace"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000196 elif enum == lldb.eStopReasonBreakpoint:
Johnny Chen59b84772010-10-18 15:46:54 +0000197 return "breakpoint"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000198 elif enum == lldb.eStopReasonWatchpoint:
Johnny Chen59b84772010-10-18 15:46:54 +0000199 return "watchpoint"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000200 elif enum == lldb.eStopReasonSignal:
Johnny Chen59b84772010-10-18 15:46:54 +0000201 return "signal"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000202 elif enum == lldb.eStopReasonException:
Johnny Chen59b84772010-10-18 15:46:54 +0000203 return "exception"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000204 elif enum == lldb.eStopReasonPlanComplete:
Johnny Chen59b84772010-10-18 15:46:54 +0000205 return "plancomplete"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000206 else:
Johnny Chen42da4da2011-03-05 01:20:11 +0000207 raise Exception("Unknown StopReason enum")
Johnny Chenbe683bc2010-10-07 22:15:58 +0000208
Johnny Chen2c8d1592010-11-03 21:37:58 +0000209def ValueTypeString(enum):
210 """Returns the valueType string given an enum."""
211 if enum == lldb.eValueTypeInvalid:
212 return "invalid"
213 elif enum == lldb.eValueTypeVariableGlobal:
214 return "global_variable"
215 elif enum == lldb.eValueTypeVariableStatic:
216 return "static_variable"
217 elif enum == lldb.eValueTypeVariableArgument:
218 return "argument_variable"
219 elif enum == lldb.eValueTypeVariableLocal:
220 return "local_variable"
221 elif enum == lldb.eValueTypeRegister:
222 return "register"
223 elif enum == lldb.eValueTypeRegisterSet:
224 return "register_set"
225 elif enum == lldb.eValueTypeConstResult:
226 return "constant_result"
227 else:
Johnny Chen42da4da2011-03-05 01:20:11 +0000228 raise Exception("Unknown ValueType enum")
Johnny Chen2c8d1592010-11-03 21:37:58 +0000229
Johnny Chenbe683bc2010-10-07 22:15:58 +0000230
Johnny Chen168a61a2010-10-22 21:31:03 +0000231# ==================================================
232# Utility functions related to Threads and Processes
233# ==================================================
Johnny Chenbe683bc2010-10-07 22:15:58 +0000234
Johnny Chen1605cf62010-09-08 22:54:46 +0000235def GetFunctionNames(thread):
236 """
237 Returns a sequence of function names from the stack frames of this thread.
238 """
239 def GetFuncName(i):
240 return thread.GetFrameAtIndex(i).GetFunction().GetName()
241
242 return map(GetFuncName, range(thread.GetNumFrames()))
243
244
Johnny Chenb51d87d2010-10-07 21:38:28 +0000245def GetSymbolNames(thread):
246 """
247 Returns a sequence of symbols for this thread.
248 """
249 def GetSymbol(i):
250 return thread.GetFrameAtIndex(i).GetSymbol().GetName()
251
252 return map(GetSymbol, range(thread.GetNumFrames()))
253
254
255def GetPCAddresses(thread):
256 """
257 Returns a sequence of pc addresses for this thread.
258 """
259 def GetPCAddress(i):
260 return thread.GetFrameAtIndex(i).GetPCAddress()
261
262 return map(GetPCAddress, range(thread.GetNumFrames()))
263
264
Johnny Chen1605cf62010-09-08 22:54:46 +0000265def GetFilenames(thread):
266 """
267 Returns a sequence of file names from the stack frames of this thread.
268 """
269 def GetFilename(i):
270 return thread.GetFrameAtIndex(i).GetLineEntry().GetFileSpec().GetFilename()
271
272 return map(GetFilename, range(thread.GetNumFrames()))
273
274
275def GetLineNumbers(thread):
276 """
277 Returns a sequence of line numbers from the stack frames of this thread.
278 """
279 def GetLineNumber(i):
280 return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
281
282 return map(GetLineNumber, range(thread.GetNumFrames()))
283
284
285def GetModuleNames(thread):
286 """
287 Returns a sequence of module names from the stack frames of this thread.
288 """
289 def GetModuleName(i):
290 return thread.GetFrameAtIndex(i).GetModule().GetFileSpec().GetFilename()
291
292 return map(GetModuleName, range(thread.GetNumFrames()))
293
294
Johnny Chen88866ac2010-09-09 00:55:07 +0000295def GetStackFrames(thread):
296 """
297 Returns a sequence of stack frames for this thread.
298 """
299 def GetStackFrame(i):
300 return thread.GetFrameAtIndex(i)
301
302 return map(GetStackFrame, range(thread.GetNumFrames()))
303
304
Johnny Chen30425e92010-10-07 18:52:48 +0000305def PrintStackTrace(thread, string_buffer = False):
Johnny Chen1605cf62010-09-08 22:54:46 +0000306 """Prints a simple stack trace of this thread."""
Johnny Chen30425e92010-10-07 18:52:48 +0000307
Johnny Chened5f04e2010-10-15 23:33:18 +0000308 output = StringIO.StringIO() if string_buffer else sys.stdout
Johnny Chenb51d87d2010-10-07 21:38:28 +0000309 target = thread.GetProcess().GetTarget()
310
Johnny Chen1605cf62010-09-08 22:54:46 +0000311 depth = thread.GetNumFrames()
312
313 mods = GetModuleNames(thread)
314 funcs = GetFunctionNames(thread)
Johnny Chenb51d87d2010-10-07 21:38:28 +0000315 symbols = GetSymbolNames(thread)
Johnny Chen1605cf62010-09-08 22:54:46 +0000316 files = GetFilenames(thread)
317 lines = GetLineNumbers(thread)
Johnny Chenb51d87d2010-10-07 21:38:28 +0000318 addrs = GetPCAddresses(thread)
Johnny Chen30425e92010-10-07 18:52:48 +0000319
Johnny Chenad5fd402010-10-25 19:13:52 +0000320 if thread.GetStopReason() != lldb.eStopReasonInvalid:
321 desc = "stop reason=" + StopReasonString(thread.GetStopReason())
322 else:
323 desc = ""
324 print >> output, "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
325 thread.GetThreadID(), thread.GetName(), thread.GetQueueName()) + desc
Johnny Chen1605cf62010-09-08 22:54:46 +0000326
Johnny Chenb51d87d2010-10-07 21:38:28 +0000327 for i in range(depth):
328 frame = thread.GetFrameAtIndex(i)
329 function = frame.GetFunction()
Johnny Chen1605cf62010-09-08 22:54:46 +0000330
Johnny Chenb51d87d2010-10-07 21:38:28 +0000331 load_addr = addrs[i].GetLoadAddress(target)
332 if not function.IsValid():
333 file_addr = addrs[i].GetFileAddress()
334 print >> output, " frame #{num}: {addr:#016x} {mod}`{symbol} + ????".format(
335 num=i, addr=load_addr, mod=mods[i], symbol=symbols[i])
336 else:
337 print >> output, " frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line}".format(
338 num=i, addr=load_addr, mod=mods[i], func=funcs[i], file=files[i], line=lines[i])
339
340 if string_buffer:
Johnny Chened5f04e2010-10-15 23:33:18 +0000341 return output.getvalue()
Johnny Chenb51d87d2010-10-07 21:38:28 +0000342
343
344def PrintStackTraces(process, string_buffer = False):
345 """Prints the stack traces of all the threads."""
346
Johnny Chened5f04e2010-10-15 23:33:18 +0000347 output = StringIO.StringIO() if string_buffer else sys.stdout
Johnny Chenb51d87d2010-10-07 21:38:28 +0000348
349 print >> output, "Stack traces for " + repr(process)
350
351 for i in range(process.GetNumThreads()):
352 print >> output, PrintStackTrace(process.GetThreadAtIndex(i), string_buffer=True)
Johnny Chen30425e92010-10-07 18:52:48 +0000353
354 if string_buffer:
Johnny Chened5f04e2010-10-15 23:33:18 +0000355 return output.getvalue()