Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(369)

Side by Side Diff: tools/grokdump.py

Issue 10356150: Grokdump -f: Automatically detect memory that is x86/x64 instructions or text and dump appropriatel… (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright 2011 the V8 project authors. All rights reserved. 3 # Copyright 2011 the V8 project authors. All rights reserved.
4 # Redistribution and use in source and binary forms, with or without 4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are 5 # modification, are permitted provided that the following conditions are
6 # met: 6 # met:
7 # 7 #
8 # * Redistributions of source code must retain the above copyright 8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer. 9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above 10 # * Redistributions in binary form must reproduce the above
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 104
105 def __str__(self): 105 def __str__(self):
106 return "{" + ", ".join("%s: %s" % (field, self.__getattribute__(field)) 106 return "{" + ", ".join("%s: %s" % (field, self.__getattribute__(field))
107 for field, _ in Raw._fields_) + "}" 107 for field, _ in Raw._fields_) + "}"
108 return Raw 108 return Raw
109 109
110 110
111 def do_dump(reader, heap): 111 def do_dump(reader, heap):
112 """Dump all available memory regions.""" 112 """Dump all available memory regions."""
113 def dump_region(reader, start, size, location): 113 def dump_region(reader, start, size, location):
114 print "%s - %s" % (reader.FormatIntPtr(start), 114 print
115 reader.FormatIntPtr(start + size)) 115 while start & 3 != 0:
116 for slot in xrange(start, 116 start += 1
117 start + size, 117 size -= 1
118 reader.PointerSize()): 118 location += 1
119 maybe_address = reader.ReadUIntPtr(slot) 119 is_executable = reader.IsExecutableRegion(location, size)
120 heap_object = heap.FindObject(maybe_address) 120 is_ascii = reader.IsASCIIRegion(location, size)
121 print "%s: %s" % (reader.FormatIntPtr(slot), 121
122 reader.FormatIntPtr(maybe_address)) 122 if is_executable is not False:
123 if heap_object: 123 lines = reader.GetDisasmLines(start, size)
124 heap_object.Print(Printer()) 124 for line in lines:
125 print 125 print FormatDisasmLine(start, heap, line)
126 print
127
128 if is_ascii is not False:
129 # Output in the same format as the Unix hd command
130 addr = start
131 for slot in xrange(location, location + size, 16):
132 hex_line = ""
133 asc_line = ""
134 for i in xrange(0, 16):
135 if slot + i < location + size:
136 byte = ctypes.c_uint8.from_buffer(reader.minidump, slot + i).value
137 if byte >= 0x20 and byte < 0x7f:
138 asc_line += chr(byte)
139 else:
140 asc_line += "."
141 hex_line += " %02x" % (byte)
142 else:
143 hex_line += " "
144 if i == 7:
145 hex_line += " "
146 print "%s %s |%s|" % (reader.FormatIntPtr(addr),
147 hex_line,
148 asc_line)
149 addr += 16
150
151 if is_executable is not True and is_ascii is not True:
152 print "%s - %s" % (reader.FormatIntPtr(start),
153 reader.FormatIntPtr(start + size))
154 for slot in xrange(start,
155 start + size,
156 reader.PointerSize()):
157 maybe_address = reader.ReadUIntPtr(slot)
158 heap_object = heap.FindObject(maybe_address)
159 print "%s: %s" % (reader.FormatIntPtr(slot),
160 reader.FormatIntPtr(maybe_address))
161 if heap_object:
162 heap_object.Print(Printer())
163 print
126 164
127 reader.ForEachMemoryRegion(dump_region) 165 reader.ForEachMemoryRegion(dump_region)
128 166
129 # Set of structures and constants that describe the layout of minidump 167 # Set of structures and constants that describe the layout of minidump
130 # files. Based on MSDN and Google Breakpad. 168 # files. Based on MSDN and Google Breakpad.
131 169
132 MINIDUMP_HEADER = Descriptor([ 170 MINIDUMP_HEADER = Descriptor([
133 ("signature", ctypes.c_uint32), 171 ("signature", ctypes.c_uint32),
134 ("version", ctypes.c_uint32), 172 ("version", ctypes.c_uint32),
135 ("stream_count", ctypes.c_uint32), 173 ("stream_count", ctypes.c_uint32),
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 def ReadBytes(self, address, size): 501 def ReadBytes(self, address, size):
464 location = self.FindLocation(address) 502 location = self.FindLocation(address)
465 return self.minidump[location:location + size] 503 return self.minidump[location:location + size]
466 504
467 def _ReadWord(self, location): 505 def _ReadWord(self, location):
468 if self.arch == MD_CPU_ARCHITECTURE_AMD64: 506 if self.arch == MD_CPU_ARCHITECTURE_AMD64:
469 return ctypes.c_uint64.from_buffer(self.minidump, location).value 507 return ctypes.c_uint64.from_buffer(self.minidump, location).value
470 elif self.arch == MD_CPU_ARCHITECTURE_X86: 508 elif self.arch == MD_CPU_ARCHITECTURE_X86:
471 return ctypes.c_uint32.from_buffer(self.minidump, location).value 509 return ctypes.c_uint32.from_buffer(self.minidump, location).value
472 510
511 def IsASCIIRegion(self, location, length):
Michael Starzinger 2012/05/21 12:03:13 Maybe we should rename this to IsProbableASCIIRegi
512 ascii_bytes = 0
513 non_ascii_bytes = 0
514 for loc in xrange(location, location + length):
515 byte = ctypes.c_uint8.from_buffer(self.minidump, loc).value
516 if byte >= 0x7f:
517 non_ascii_bytes += 1
518 if byte < 0x20 and byte != 0:
519 non_ascii_bytes += 1
520 if byte < 0x7f and byte >= 0x20:
521 ascii_bytes += 1
522 if byte == 0xa: # newline
523 ascii_bytes += 1
524 if ascii_bytes * 10 <= length:
525 return False
526 if length > 0 and ascii_bytes > non_ascii_bytes * 7:
527 return True
528 if ascii_bytes > non_ascii_bytes * 3:
529 return None # Maybe
530 return False
531
532 def IsExecutableRegion(self, location, length):
Michael Starzinger 2012/05/21 12:03:13 Likewise.
533 opcode_bytes = 0
534 sixty_four = self.arch == MD_CPU_ARCHITECTURE_AMD64
535 for loc in xrange(location, location + length):
536 byte = ctypes.c_uint8.from_buffer(self.minidump, loc).value
537 if (byte == 0x8b or # mov
538 byte == 0x89 or # mov reg-reg
539 (byte & 0xf0) == 0x50 or # push/pop
540 (sixty_four and (byte & 0xf0) == 0x40) or # rex prefix
541 byte == 0xc3 or # return
542 byte == 0x74 or # jeq
543 byte == 0x84 or # jeq far
544 byte == 0x75 or # jne
545 byte == 0x85 or # jne far
546 byte == 0xe8 or # call
547 byte == 0xe9 or # jmp far
548 byte == 0xeb): # jmp near
549 opcode_bytes += 1
550 opcode_percent = (opcode_bytes * 100) / length
551 threshold = 20
552 if opcode_percent > threshold + 2:
553 return True
554 if opcode_percent > threshold - 2:
555 return None # Maybe
556 return False
557
558 def FindRegion(self, addr):
559 answer = [-1, -1]
560 def is_in(reader, start, size, location):
561 if addr >= start and addr < start + size:
562 answer[0] = start
563 answer[1] = size
564 self.ForEachMemoryRegion(is_in)
565 if answer[0] == -1:
566 return None
567 return answer
568
473 def ForEachMemoryRegion(self, cb): 569 def ForEachMemoryRegion(self, cb):
474 if self.memory_list64 is not None: 570 if self.memory_list64 is not None:
475 for r in self.memory_list64.ranges: 571 for r in self.memory_list64.ranges:
476 location = self.memory_list64.base_rva + offset 572 location = self.memory_list64.base_rva + offset
477 cb(self, r.start, r.size, location) 573 cb(self, r.start, r.size, location)
478 offset += r.size 574 offset += r.size
479 575
480 if self.memory_list is not None: 576 if self.memory_list is not None:
481 for r in self.memory_list.ranges: 577 for r in self.memory_list.ranges:
482 cb(self, r.start, r.memory.data_size, r.memory.rva) 578 cb(self, r.start, r.memory.data_size, r.memory.rva)
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after
1092 def do_list(self, smth): 1188 def do_list(self, smth):
1093 """List all available memory regions.""" 1189 """List all available memory regions."""
1094 def print_region(reader, start, size, location): 1190 def print_region(reader, start, size, location):
1095 print "%s - %s" % (reader.FormatIntPtr(start), 1191 print "%s - %s" % (reader.FormatIntPtr(start),
1096 reader.FormatIntPtr(start + size)) 1192 reader.FormatIntPtr(start + size))
1097 1193
1098 self.reader.ForEachMemoryRegion(print_region) 1194 self.reader.ForEachMemoryRegion(print_region)
1099 1195
1100 def AnalyzeMinidump(options, minidump_name): 1196 def AnalyzeMinidump(options, minidump_name):
1101 reader = MinidumpReader(options, minidump_name) 1197 reader = MinidumpReader(options, minidump_name)
1198 heap = None
1102 DebugPrint("========================================") 1199 DebugPrint("========================================")
1103 if reader.exception is None: 1200 if reader.exception is None:
1104 print "Minidump has no exception info" 1201 print "Minidump has no exception info"
1105 return 1202 else:
1106 print "Exception info:" 1203 print "Exception info:"
1107 exception_thread = reader.thread_map[reader.exception.thread_id] 1204 exception_thread = reader.thread_map[reader.exception.thread_id]
1108 print " thread id: %d" % exception_thread.id 1205 print " thread id: %d" % exception_thread.id
1109 print " code: %08X" % reader.exception.exception.code 1206 print " code: %08X" % reader.exception.exception.code
1110 print " context:" 1207 print " context:"
1111 for r in CONTEXT_FOR_ARCH[reader.arch]: 1208 for r in CONTEXT_FOR_ARCH[reader.arch]:
1112 print " %s: %s" % (r, reader.FormatIntPtr(reader.Register(r))) 1209 print " %s: %s" % (r, reader.FormatIntPtr(reader.Register(r)))
1113 # TODO(vitalyr): decode eflags. 1210 # TODO(vitalyr): decode eflags.
1114 print " eflags: %s" % bin(reader.exception_context.eflags)[2:] 1211 print " eflags: %s" % bin(reader.exception_context.eflags)[2:]
1115 print 1212 print
1116 1213
1117 stack_top = reader.ExceptionSP() 1214 stack_top = reader.ExceptionSP()
1118 stack_bottom = exception_thread.stack.start + \ 1215 stack_bottom = exception_thread.stack.start + \
1119 exception_thread.stack.memory.data_size 1216 exception_thread.stack.memory.data_size
1120 stack_map = {reader.ExceptionIP(): -1} 1217 stack_map = {reader.ExceptionIP(): -1}
1121 for slot in xrange(stack_top, stack_bottom, reader.PointerSize()): 1218 for slot in xrange(stack_top, stack_bottom, reader.PointerSize()):
1122 maybe_address = reader.ReadUIntPtr(slot) 1219 maybe_address = reader.ReadUIntPtr(slot)
1123 if not maybe_address in stack_map: 1220 if not maybe_address in stack_map:
1124 stack_map[maybe_address] = slot 1221 stack_map[maybe_address] = slot
1125 heap = V8Heap(reader, stack_map) 1222 heap = V8Heap(reader, stack_map)
1126 1223
1127 print "Disassembly around exception.eip:" 1224 print "Disassembly around exception.eip:"
1128 start = reader.ExceptionIP() - EIP_PROXIMITY 1225 disasm_start = reader.ExceptionIP() - EIP_PROXIMITY
1129 lines = reader.GetDisasmLines(start, 2 * EIP_PROXIMITY) 1226 disasm_bytes = 2 * EIP_PROXIMITY
1130 for line in lines: 1227 if (options.full):
1131 print FormatDisasmLine(start, heap, line) 1228 full_range = reader.FindRegion(reader.ExceptionIP())
1132 print 1229 if full_range is not None:
1230 disasm_start = full_range[0]
1231 disasm_bytes = full_range[1]
1232
1233 lines = reader.GetDisasmLines(disasm_start, disasm_bytes)
1234
1235 for line in lines:
1236 print FormatDisasmLine(disasm_start, heap, line)
1237 print
1238
1239 if heap is None:
1240 heap = V8Heap(reader, None)
1133 1241
1134 if options.full: 1242 if options.full:
1135 do_dump(reader, heap) 1243 do_dump(reader, heap)
1136 1244
1137 if options.shell: 1245 if options.shell:
1138 InspectionShell(reader, heap).cmdloop("type help to get help") 1246 InspectionShell(reader, heap).cmdloop("type help to get help")
1139 else: 1247 else:
1140 print "Annotated stack (from exception.esp to bottom):" 1248 if reader.exception is not None:
1141 for slot in xrange(stack_top, stack_bottom, reader.PointerSize()): 1249 print "Annotated stack (from exception.esp to bottom):"
1142 maybe_address = reader.ReadUIntPtr(slot) 1250 for slot in xrange(stack_top, stack_bottom, reader.PointerSize()):
1143 heap_object = heap.FindObject(maybe_address) 1251 maybe_address = reader.ReadUIntPtr(slot)
1144 print "%s: %s" % (reader.FormatIntPtr(slot), 1252 heap_object = heap.FindObject(maybe_address)
1145 reader.FormatIntPtr(maybe_address)) 1253 print "%s: %s" % (reader.FormatIntPtr(slot),
1146 if heap_object: 1254 reader.FormatIntPtr(maybe_address))
1147 heap_object.Print(Printer()) 1255 if heap_object:
1148 print 1256 heap_object.Print(Printer())
1257 print
1149 1258
1150 reader.Dispose() 1259 reader.Dispose()
1151 1260
1152 1261
1153 if __name__ == "__main__": 1262 if __name__ == "__main__":
1154 parser = optparse.OptionParser(USAGE) 1263 parser = optparse.OptionParser(USAGE)
1155 parser.add_option("-s", "--shell", dest="shell", action="store_true") 1264 parser.add_option("-s", "--shell", dest="shell", action="store_true")
1156 parser.add_option("-f", "--full", dest="full", action="store_true") 1265 parser.add_option("-f", "--full", dest="full", action="store_true")
1157 options, args = parser.parse_args() 1266 options, args = parser.parse_args()
1158 if len(args) != 1: 1267 if len(args) != 1:
1159 parser.print_help() 1268 parser.print_help()
1160 sys.exit(1) 1269 sys.exit(1)
1161 AnalyzeMinidump(options, args[0]) 1270 AnalyzeMinidump(options, args[0])
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698