blob: 826b15ceb2ac03e9905eb9ecb86e1988adc7a7c4 [file] [log] [blame]
Greg Clayton01f7c962012-01-20 03:15:45 +00001#!/usr/bin/python
2
3#----------------------------------------------------------------------
4# Be sure to add the python path that points to the LLDB shared library.
Greg Claytona3698c62012-01-21 00:37:19 +00005#
6# To use this in the embedded python interpreter using "lldb":
7#
8# cd /path/containing/crashlog.py
9# lldb
10# (lldb) script import crashlog
11# "crashlog" command installed, type "crashlog --help" for detailed help
12# (lldb) crashlog ~/Library/Logs/DiagnosticReports/a.crash
13#
14# The benefit of running the crashlog command inside lldb in the
15# embedded python interpreter is when the command completes, there
16# will be a target with all of the files loaded at the locations
17# described in the crash log. Only the files that have stack frames
18# in the backtrace will be loaded unless the "--load-all" option
19# has been specified. This allows users to explore the program in the
20# state it was in right at crash time.
21#
Greg Clayton01f7c962012-01-20 03:15:45 +000022# On MacOSX csh, tcsh:
Greg Claytona3698c62012-01-21 00:37:19 +000023# ( setenv PYTHONPATH /path/to/LLDB.framework/Resources/Python ; ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash )
24#
Greg Clayton01f7c962012-01-20 03:15:45 +000025# On MacOSX sh, bash:
Greg Claytona3698c62012-01-21 00:37:19 +000026# PYTHONPATH=/path/to/LLDB.framework/Resources/Python ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash
Greg Clayton01f7c962012-01-20 03:15:45 +000027#----------------------------------------------------------------------
28
29import lldb
Greg Claytona3698c62012-01-21 00:37:19 +000030import commands
Greg Clayton01f7c962012-01-20 03:15:45 +000031import optparse
32import os
33import plistlib
Greg Clayton3d39f832012-04-03 21:35:43 +000034import pprint # pp = pprint.PrettyPrinter(indent=4); pp.pprint(command_args)
Greg Clayton01f7c962012-01-20 03:15:45 +000035import re
Greg Clayton223e8082012-01-21 04:26:24 +000036import shlex
Greg Clayton01f7c962012-01-20 03:15:45 +000037import sys
38import time
Greg Claytoncd793122012-01-20 06:12:47 +000039import uuid
Greg Clayton6f2f0ab2012-04-25 01:49:50 +000040import lldb.utils.symbolication
Greg Clayton01f7c962012-01-20 03:15:45 +000041
42PARSE_MODE_NORMAL = 0
43PARSE_MODE_THREAD = 1
44PARSE_MODE_IMAGES = 2
45PARSE_MODE_THREGS = 3
46PARSE_MODE_SYSTEM = 4
47
Greg Clayton6f2f0ab2012-04-25 01:49:50 +000048class CrashLog(lldb.utils.symbolication.Symbolicator):
Greg Clayton01f7c962012-01-20 03:15:45 +000049 """Class that does parses darwin crash logs"""
50 thread_state_regex = re.compile('^Thread ([0-9]+) crashed with')
51 thread_regex = re.compile('^Thread ([0-9]+)([^:]*):(.*)')
Greg Clayton8077a532012-01-20 03:32:35 +000052 frame_regex = re.compile('^([0-9]+) +([^ ]+) *\t(0x[0-9a-fA-F]+) +(.*)')
53 image_regex_uuid = re.compile('(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +[+]?([^ ]+) +([^<]+)<([-0-9a-fA-F]+)> (.*)');
54 image_regex_no_uuid = re.compile('(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +[+]?([^ ]+) +([^/]+)/(.*)');
Greg Clayton01f7c962012-01-20 03:15:45 +000055 empty_line_regex = re.compile('^$')
56
57 class Thread:
58 """Class that represents a thread in a darwin crash log"""
59 def __init__(self, index):
60 self.index = index
61 self.frames = list()
62 self.registers = dict()
63 self.reason = None
64 self.queue = None
65
66 def dump(self, prefix):
67 print "%sThread[%u] %s" % (prefix, self.index, self.reason)
68 if self.frames:
69 print "%s Frames:" % (prefix)
70 for frame in self.frames:
71 frame.dump(prefix + ' ')
72 if self.registers:
73 print "%s Registers:" % (prefix)
74 for reg in self.registers.keys():
75 print "%s %-5s = %#16.16x" % (prefix, reg, self.registers[reg])
76
77 def did_crash(self):
78 return self.reason != None
79
80 def __str__(self):
81 s = "Thread[%u]" % self.index
82 if self.reason:
83 s += ' %s' % self.reason
84 return s
85
86
87 class Frame:
88 """Class that represents a stack frame in a thread in a darwin crash log"""
Greg Clayton3d39f832012-04-03 21:35:43 +000089 def __init__(self, index, pc, description):
Greg Clayton01f7c962012-01-20 03:15:45 +000090 self.pc = pc
Greg Clayton3d39f832012-04-03 21:35:43 +000091 self.description = description
92 self.index = index
Greg Clayton01f7c962012-01-20 03:15:45 +000093
94 def __str__(self):
Greg Clayton3d39f832012-04-03 21:35:43 +000095 if self.description:
96 return "[%3u] 0x%16.16x %s" % (self.index, self.pc, self.description)
97 else:
Johnny Chen4e468672012-05-03 18:46:28 +000098 return "[%3u] 0x%16.16x" % (self.index, self.pc)
99
100 def dump(self, prefix):
101 print "%s%s" % (prefix, str(self))
Greg Clayton01f7c962012-01-20 03:15:45 +0000102
Greg Clayton6f2f0ab2012-04-25 01:49:50 +0000103 class DarwinImage(lldb.utils.symbolication.Image):
Greg Clayton01f7c962012-01-20 03:15:45 +0000104 """Class that represents a binary images in a darwin crash log"""
Greg Clayton8077a532012-01-20 03:32:35 +0000105 dsymForUUIDBinary = os.path.expanduser('~rc/bin/dsymForUUID')
Greg Claytoncd793122012-01-20 06:12:47 +0000106 if not os.path.exists(dsymForUUIDBinary):
107 dsymForUUIDBinary = commands.getoutput('which dsymForUUID')
108
109 dwarfdump_uuid_regex = re.compile('UUID: ([-0-9a-fA-F]+) \(([^\(]+)\) .*')
Greg Clayton8077a532012-01-20 03:32:35 +0000110
Greg Clayton3d39f832012-04-03 21:35:43 +0000111 def __init__(self, text_addr_lo, text_addr_hi, identifier, version, uuid, path):
Greg Clayton6f2f0ab2012-04-25 01:49:50 +0000112 lldb.utils.symbolication.Image.__init__(self, path, uuid);
113 self.add_section (lldb.utils.symbolication.Section(text_addr_lo, text_addr_hi, "__TEXT"))
Greg Clayton3d39f832012-04-03 21:35:43 +0000114 self.identifier = identifier
Greg Clayton01f7c962012-01-20 03:15:45 +0000115 self.version = version
Greg Clayton01f7c962012-01-20 03:15:45 +0000116
Greg Clayton3d39f832012-04-03 21:35:43 +0000117 def locate_module_and_debug_symbols(self):
Greg Claytoncd793122012-01-20 06:12:47 +0000118 if self.resolved_path:
119 # Don't load a module twice...
Greg Clayton4c983c82012-04-20 23:31:27 +0000120 return True
Greg Clayton1dae6f32012-04-25 18:40:20 +0000121 print 'Getting symbols for %s %s...' % (self.uuid, self.path),
Greg Clayton8077a532012-01-20 03:32:35 +0000122 if os.path.exists(self.dsymForUUIDBinary):
123 dsym_for_uuid_command = '%s %s' % (self.dsymForUUIDBinary, self.uuid)
Greg Clayton8077a532012-01-20 03:32:35 +0000124 s = commands.getoutput(dsym_for_uuid_command)
125 if s:
126 plist_root = plistlib.readPlistFromString (s)
127 if plist_root:
Greg Claytoncd793122012-01-20 06:12:47 +0000128 plist = plist_root[self.uuid]
129 if plist:
130 if 'DBGArchitecture' in plist:
131 self.arch = plist['DBGArchitecture']
132 if 'DBGDSYMPath' in plist:
Greg Clayton3d39f832012-04-03 21:35:43 +0000133 self.symfile = os.path.realpath(plist['DBGDSYMPath'])
Greg Claytoncd793122012-01-20 06:12:47 +0000134 if 'DBGSymbolRichExecutable' in plist:
135 self.resolved_path = os.path.expanduser (plist['DBGSymbolRichExecutable'])
136 if not self.resolved_path and os.path.exists(self.path):
137 dwarfdump_cmd_output = commands.getoutput('dwarfdump --uuid "%s"' % self.path)
138 self_uuid = uuid.UUID(self.uuid)
139 for line in dwarfdump_cmd_output.splitlines():
140 match = self.dwarfdump_uuid_regex.search (line)
141 if match:
142 dwarf_uuid_str = match.group(1)
143 dwarf_uuid = uuid.UUID(dwarf_uuid_str)
144 if self_uuid == dwarf_uuid:
145 self.resolved_path = self.path
146 self.arch = match.group(2)
147 break;
148 if not self.resolved_path:
149 print "error: file %s '%s' doesn't match the UUID in the installed file" % (self.uuid, self.path)
Greg Clayton4c983c82012-04-20 23:31:27 +0000150 return False
Greg Claytoncd793122012-01-20 06:12:47 +0000151 if (self.resolved_path and os.path.exists(self.resolved_path)) or (self.path and os.path.exists(self.path)):
152 print 'ok'
Greg Clayton1dae6f32012-04-25 18:40:20 +0000153 # if self.resolved_path:
154 # print ' exe = "%s"' % self.resolved_path
155 # if self.symfile:
156 # print ' dsym = "%s"' % self.symfile
Greg Clayton4c983c82012-04-20 23:31:27 +0000157 return True
158 return False
Greg Clayton01f7c962012-01-20 03:15:45 +0000159
Greg Clayton3d39f832012-04-03 21:35:43 +0000160
Greg Clayton01f7c962012-01-20 03:15:45 +0000161
162 def __init__(self, path):
163 """CrashLog constructor that take a path to a darwin crash log file"""
Greg Clayton6f2f0ab2012-04-25 01:49:50 +0000164 lldb.utils.symbolication.Symbolicator.__init__(self);
Greg Clayton223e8082012-01-21 04:26:24 +0000165 self.path = os.path.expanduser(path);
Greg Clayton01f7c962012-01-20 03:15:45 +0000166 self.info_lines = list()
167 self.system_profile = list()
168 self.threads = list()
Greg Clayton01f7c962012-01-20 03:15:45 +0000169 self.idents = list() # A list of the required identifiers for doing all stack backtraces
170 self.crashed_thread_idx = -1
171 self.version = -1
Greg Clayton223e8082012-01-21 04:26:24 +0000172 self.error = None
Greg Clayton01f7c962012-01-20 03:15:45 +0000173 # With possible initial component of ~ or ~user replaced by that user's home directory.
Greg Clayton223e8082012-01-21 04:26:24 +0000174 try:
175 f = open(self.path)
176 except IOError:
177 self.error = 'error: cannot open "%s"' % self.path
178 return
179
Greg Clayton01f7c962012-01-20 03:15:45 +0000180 self.file_lines = f.read().splitlines()
181 parse_mode = PARSE_MODE_NORMAL
182 thread = None
183 for line in self.file_lines:
184 # print line
185 line_len = len(line)
186 if line_len == 0:
187 if thread:
188 if parse_mode == PARSE_MODE_THREAD:
189 if thread.index == self.crashed_thread_idx:
190 thread.reason = ''
191 if self.thread_exception:
192 thread.reason += self.thread_exception
193 if self.thread_exception_data:
194 thread.reason += " (%s)" % self.thread_exception_data
195 self.threads.append(thread)
196 thread = None
197 else:
198 # only append an extra empty line if the previous line
199 # in the info_lines wasn't empty
200 if len(self.info_lines) > 0 and len(self.info_lines[-1]):
201 self.info_lines.append(line)
202 parse_mode = PARSE_MODE_NORMAL
203 # print 'PARSE_MODE_NORMAL'
204 elif parse_mode == PARSE_MODE_NORMAL:
205 if line.startswith ('Process:'):
206 (self.process_name, pid_with_brackets) = line[8:].strip().split()
207 self.process_id = pid_with_brackets.strip('[]')
208 elif line.startswith ('Path:'):
209 self.process_path = line[5:].strip()
210 elif line.startswith ('Identifier:'):
211 self.process_identifier = line[11:].strip()
212 elif line.startswith ('Version:'):
213 (self.process_version, compatability_version) = line[8:].strip().split()
214 self.process_compatability_version = compatability_version.strip('()')
215 elif line.startswith ('Parent Process:'):
216 (self.parent_process_name, pid_with_brackets) = line[15:].strip().split()
217 self.parent_process_id = pid_with_brackets.strip('[]')
218 elif line.startswith ('Exception Type:'):
219 self.thread_exception = line[15:].strip()
220 continue
221 elif line.startswith ('Exception Codes:'):
222 self.thread_exception_data = line[16:].strip()
223 continue
224 elif line.startswith ('Crashed Thread:'):
225 self.crashed_thread_idx = int(line[15:].strip().split()[0])
226 continue
227 elif line.startswith ('Report Version:'):
228 self.version = int(line[15:].strip())
229 continue
230 elif line.startswith ('System Profile:'):
231 parse_mode = PARSE_MODE_SYSTEM
232 continue
233 elif (line.startswith ('Interval Since Last Report:') or
234 line.startswith ('Crashes Since Last Report:') or
235 line.startswith ('Per-App Interval Since Last Report:') or
236 line.startswith ('Per-App Crashes Since Last Report:') or
237 line.startswith ('Sleep/Wake UUID:') or
238 line.startswith ('Anonymous UUID:')):
239 # ignore these
240 continue
241 elif line.startswith ('Thread'):
242 thread_state_match = self.thread_state_regex.search (line)
243 if thread_state_match:
244 thread_state_match = self.thread_regex.search (line)
245 thread_idx = int(thread_state_match.group(1))
246 parse_mode = PARSE_MODE_THREGS
247 thread = self.threads[thread_idx]
248 else:
249 thread_match = self.thread_regex.search (line)
250 if thread_match:
251 # print 'PARSE_MODE_THREAD'
252 parse_mode = PARSE_MODE_THREAD
253 thread_idx = int(thread_match.group(1))
254 thread = CrashLog.Thread(thread_idx)
255 continue
256 elif line.startswith ('Binary Images:'):
257 parse_mode = PARSE_MODE_IMAGES
258 continue
259 self.info_lines.append(line.strip())
260 elif parse_mode == PARSE_MODE_THREAD:
261 frame_match = self.frame_regex.search(line)
262 if frame_match:
263 ident = frame_match.group(2)
264 if not ident in self.idents:
265 self.idents.append(ident)
266 thread.frames.append (CrashLog.Frame(int(frame_match.group(1)), int(frame_match.group(3), 0), frame_match.group(4)))
267 else:
Greg Clayton8077a532012-01-20 03:32:35 +0000268 print 'error: frame regex failed for line: "%s"' % line
Greg Clayton01f7c962012-01-20 03:15:45 +0000269 elif parse_mode == PARSE_MODE_IMAGES:
270 image_match = self.image_regex_uuid.search (line)
271 if image_match:
Greg Clayton3d39f832012-04-03 21:35:43 +0000272 image = CrashLog.DarwinImage (int(image_match.group(1),0),
273 int(image_match.group(2),0),
274 image_match.group(3).strip(),
275 image_match.group(4).strip(),
276 image_match.group(5),
277 image_match.group(6))
Greg Clayton01f7c962012-01-20 03:15:45 +0000278 self.images.append (image)
279 else:
280 image_match = self.image_regex_no_uuid.search (line)
281 if image_match:
Greg Clayton3d39f832012-04-03 21:35:43 +0000282 image = CrashLog.DarwinImage (int(image_match.group(1),0),
283 int(image_match.group(2),0),
284 image_match.group(3).strip(),
285 image_match.group(4).strip(),
286 None,
287 image_match.group(5))
Greg Clayton01f7c962012-01-20 03:15:45 +0000288 self.images.append (image)
289 else:
290 print "error: image regex failed for: %s" % line
291
292 elif parse_mode == PARSE_MODE_THREGS:
293 stripped_line = line.strip()
294 reg_values = stripped_line.split(' ')
295 for reg_value in reg_values:
296 (reg, value) = reg_value.split(': ')
297 thread.registers[reg.strip()] = int(value, 0)
298 elif parse_mode == PARSE_MODE_SYSTEM:
299 self.system_profile.append(line)
300 f.close()
301
302 def dump(self):
303 print "Crash Log File: %s" % (self.path)
304 print "\nThreads:"
305 for thread in self.threads:
306 thread.dump(' ')
307 print "\nImages:"
308 for image in self.images:
309 image.dump(' ')
310
Greg Clayton3d39f832012-04-03 21:35:43 +0000311 def find_image_with_identifier(self, identifier):
Greg Clayton01f7c962012-01-20 03:15:45 +0000312 for image in self.images:
Greg Clayton3d39f832012-04-03 21:35:43 +0000313 if image.identifier == identifier:
Greg Clayton01f7c962012-01-20 03:15:45 +0000314 return image
315 return None
316
Greg Claytone9ee5502012-01-20 19:25:32 +0000317 def create_target(self):
Greg Clayton3d39f832012-04-03 21:35:43 +0000318 #print 'crashlog.create_target()...'
Greg Clayton6f2f0ab2012-04-25 01:49:50 +0000319 target = lldb.utils.symbolication.Symbolicator.create_target(self)
Greg Clayton3d39f832012-04-03 21:35:43 +0000320 if target:
321 return target
Greg Claytone9ee5502012-01-20 19:25:32 +0000322 # We weren't able to open the main executable as, but we can still symbolicate
Greg Clayton3d39f832012-04-03 21:35:43 +0000323 print 'crashlog.create_target()...2'
Greg Claytone9ee5502012-01-20 19:25:32 +0000324 if self.idents:
Sean Callananf7fb7332012-01-20 19:27:48 +0000325 for ident in self.idents:
Greg Claytone9ee5502012-01-20 19:25:32 +0000326 image = self.find_image_with_identifier (ident)
327 if image:
Greg Clayton3d39f832012-04-03 21:35:43 +0000328 target = image.create_target ()
329 if target:
330 return target # success
331 print 'crashlog.create_target()...3'
Greg Claytone9ee5502012-01-20 19:25:32 +0000332 for image in self.images:
Greg Clayton3d39f832012-04-03 21:35:43 +0000333 target = image.create_target ()
334 if target:
335 return target # success
336 print 'crashlog.create_target()...4'
337 print 'error: unable to locate any executables from the crash log'
338 return None
Greg Claytone9ee5502012-01-20 19:25:32 +0000339
Greg Clayton01f7c962012-01-20 03:15:45 +0000340
341def usage():
342 print "Usage: lldb-symbolicate.py [-n name] executable-image"
343 sys.exit(0)
344
345def Symbolicate(debugger, command, result, dict):
Greg Clayton223e8082012-01-21 04:26:24 +0000346 try:
347 SymbolicateCrashLog (shlex.split(command))
348 except:
349 result.PutCString ("error: python exception %s" % sys.exc_info()[0])
350
Greg Clayton01f7c962012-01-20 03:15:45 +0000351def SymbolicateCrashLog(command_args):
Greg Claytona3698c62012-01-21 00:37:19 +0000352 usage = "usage: %prog [options] <FILE> [FILE ...]"
353 description='''Symbolicate one or more darwin crash log files to provide source file and line information,
354inlined stack frames back to the concrete functions, and disassemble the location of the crash
355for the first frame of the crashed thread.
356If this script is imported into the LLDB command interpreter, a "crashlog" command will be added to the interpreter
357for use at the LLDB command line. After a crash log has been parsed and symbolicated, a target will have been
358created that has all of the shared libraries loaded at the load addresses found in the crash log file. This allows
359you to explore the program as if it were stopped at the locations described in the crash log and functions can
360be disassembled and lookups can be performed using the addresses found in the crash log.'''
361 parser = optparse.OptionParser(description=description, prog='crashlog.py',usage=usage)
Greg Clayton01f7c962012-01-20 03:15:45 +0000362 parser.add_option('--platform', type='string', metavar='platform', dest='platform', help='specify one platform by name')
Greg Clayton2c1fdd02012-01-21 05:10:20 +0000363 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
Greg Clayton01f7c962012-01-20 03:15:45 +0000364 parser.add_option('--no-images', action='store_false', dest='show_images', help='don\'t show images in stack frames', default=True)
Greg Clayton2c1fdd02012-01-21 05:10:20 +0000365 parser.add_option('-a', '--load-all', action='store_true', dest='load_all_images', help='load all executable images, not just the images found in the crashed stack frames', default=False)
Greg Clayton01f7c962012-01-20 03:15:45 +0000366 parser.add_option('--image-list', action='store_true', dest='dump_image_list', help='show image list', default=False)
Greg Clayton2c1fdd02012-01-21 05:10:20 +0000367 parser.add_option('-g', '--debug-delay', type='int', dest='debug_delay', metavar='NSEC', help='pause for NSEC seconds for debugger', default=0)
368 parser.add_option('-c', '--crashed-only', action='store_true', dest='crashed_only', help='only symbolicate the crashed thread', default=False)
369 parser.add_option('-d', '--disasm-depth', type='int', dest='disassemble_depth', help='set the depth in stack frames that should be disassembled (default is 1)', default=1)
370 parser.add_option('-D', '--disasm-all', action='store_true', dest='disassemble_all_threads', help='enabled disassembly of frames on all threads (not just the crashed thread)', default=False)
371 parser.add_option('-B', '--disasm-before', type='int', dest='disassemble_before', help='the number of instructions to disassemble before the frame PC', default=4)
372 parser.add_option('-A', '--disasm-after', type='int', dest='disassemble_after', help='the number of instructions to disassemble after the frame PC', default=4)
Greg Clayton01f7c962012-01-20 03:15:45 +0000373 loaded_addresses = False
Greg Clayton223e8082012-01-21 04:26:24 +0000374 try:
375 (options, args) = parser.parse_args(command_args)
376 except:
377 return
378
Greg Clayton01f7c962012-01-20 03:15:45 +0000379 if options.verbose:
Greg Clayton223e8082012-01-21 04:26:24 +0000380 print 'command_args = %s' % command_args
Greg Clayton01f7c962012-01-20 03:15:45 +0000381 print 'options', options
Greg Clayton223e8082012-01-21 04:26:24 +0000382 print 'args', args
383
Greg Clayton01f7c962012-01-20 03:15:45 +0000384 if options.debug_delay > 0:
385 print "Waiting %u seconds for debugger to attach..." % options.debug_delay
386 time.sleep(options.debug_delay)
Greg Clayton01f7c962012-01-20 03:15:45 +0000387 error = lldb.SBError()
Greg Claytone9ee5502012-01-20 19:25:32 +0000388 if args:
389 for crash_log_file in args:
Greg Clayton01f7c962012-01-20 03:15:45 +0000390 crash_log = CrashLog(crash_log_file)
Greg Clayton3d39f832012-04-03 21:35:43 +0000391
392 #pp = pprint.PrettyPrinter(indent=4); pp.pprint(args)
Greg Clayton223e8082012-01-21 04:26:24 +0000393 if crash_log.error:
394 print crash_log.error
395 return
Greg Clayton8077a532012-01-20 03:32:35 +0000396 if options.verbose:
397 crash_log.dump()
Greg Claytona3698c62012-01-21 00:37:19 +0000398 if not crash_log.images:
399 print 'error: no images in crash log'
400 return
401
Greg Clayton3d39f832012-04-03 21:35:43 +0000402 target = crash_log.create_target ()
403 if not target:
Greg Claytona3698c62012-01-21 00:37:19 +0000404 return
Greg Clayton3d39f832012-04-03 21:35:43 +0000405 exe_module = target.GetModuleAtIndex(0)
Greg Claytona3698c62012-01-21 00:37:19 +0000406 images_to_load = list()
Greg Clayton3d39f832012-04-03 21:35:43 +0000407 loaded_images = list()
Greg Claytona3698c62012-01-21 00:37:19 +0000408 if options.load_all_images:
409 # --load-all option was specified, load everything up
410 for image in crash_log.images:
411 images_to_load.append(image)
412 else:
413 # Only load the images found in stack frames for the crashed threads
414 for ident in crash_log.idents:
Greg Clayton3d39f832012-04-03 21:35:43 +0000415 images = crash_log.find_images_with_identifier (ident)
416 if images:
417 for image in images:
418 images_to_load.append(image)
Greg Claytona3698c62012-01-21 00:37:19 +0000419 else:
420 print 'error: can\'t find image for identifier "%s"' % ident
421
422 for image in images_to_load:
Greg Clayton3d39f832012-04-03 21:35:43 +0000423 if image in loaded_images:
Greg Claytona3698c62012-01-21 00:37:19 +0000424 print "warning: skipping %s loaded at %#16.16x duplicate entry (probably commpage)" % (image.path, image.text_addr_lo)
Greg Clayton01f7c962012-01-20 03:15:45 +0000425 else:
Greg Clayton3d39f832012-04-03 21:35:43 +0000426 err = image.add_module (target)
Greg Claytona3698c62012-01-21 00:37:19 +0000427 if err:
428 print err
429 else:
Greg Clayton1dae6f32012-04-25 18:40:20 +0000430 #print 'loaded %s' % image
Greg Clayton3d39f832012-04-03 21:35:43 +0000431 loaded_images.append(image)
Greg Claytona3698c62012-01-21 00:37:19 +0000432
Greg Claytona3698c62012-01-21 00:37:19 +0000433 for thread in crash_log.threads:
434 this_thread_crashed = thread.did_crash()
435 if options.crashed_only and this_thread_crashed == False:
436 continue
437 print "%s" % thread
Greg Clayton3d39f832012-04-03 21:35:43 +0000438 #prev_frame_index = -1
Greg Claytona3698c62012-01-21 00:37:19 +0000439 for frame_idx, frame in enumerate(thread.frames):
Greg Clayton3d39f832012-04-03 21:35:43 +0000440 disassemble = (this_thread_crashed or options.disassemble_all_threads) and frame_idx < options.disassemble_depth;
441 symbolicated_frame_addresses = crash_log.symbolicate (frame.pc)
442 if symbolicated_frame_addresses:
443 symbolicated_frame_address_idx = 0
444 for symbolicated_frame_address in symbolicated_frame_addresses:
445 print '[%3u] %s' % (frame_idx, symbolicated_frame_address)
446
447 if symbolicated_frame_address_idx == 0:
448 if disassemble:
449 instructions = symbolicated_frame_address.get_instructions()
450 if instructions:
451 print
Greg Clayton6f2f0ab2012-04-25 01:49:50 +0000452 lldb.utils.symbolication.disassemble_instructions (target,
453 instructions,
454 frame.pc,
455 options.disassemble_before,
456 options.disassemble_after, frame.index > 0)
Greg Clayton3d39f832012-04-03 21:35:43 +0000457 print
458 symbolicated_frame_address_idx += 1
459 else:
460 print frame
Greg Claytona3698c62012-01-21 00:37:19 +0000461 print
Greg Clayton01f7c962012-01-20 03:15:45 +0000462
Greg Claytona3698c62012-01-21 00:37:19 +0000463 if options.dump_image_list:
464 print "Binary Images:"
465 for image in crash_log.images:
466 print image
467
Greg Clayton01f7c962012-01-20 03:15:45 +0000468if __name__ == '__main__':
Greg Claytone9ee5502012-01-20 19:25:32 +0000469 # Create a new debugger instance
470 lldb.debugger = lldb.SBDebugger.Create()
Greg Clayton3d39f832012-04-03 21:35:43 +0000471 SymbolicateCrashLog (sys.argv[1:])
Johnny Chena889aee2012-05-03 22:31:30 +0000472elif getattr(lldb, 'debugger', None):
Greg Clayton6f2f0ab2012-04-25 01:49:50 +0000473 lldb.debugger.HandleCommand('command script add -f lldb.macosx.crashlog.Symbolicate crashlog')
Greg Claytone9ee5502012-01-20 19:25:32 +0000474 print '"crashlog" command installed, type "crashlog --help" for detailed help'
Greg Clayton01f7c962012-01-20 03:15:45 +0000475