Commit 5cd40f74 authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

Grokdump -f: Automatically detect memory that is x86/x64 instructions or text...

Grokdump -f: Automatically detect memory that is x86/x64 instructions or text and dump appropriately.
Review URL: https://chromiumcodereview.appspot.com/10356150

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11621 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 367757b7
...@@ -111,18 +111,56 @@ class Descriptor(object): ...@@ -111,18 +111,56 @@ class Descriptor(object):
def do_dump(reader, heap): def do_dump(reader, heap):
"""Dump all available memory regions.""" """Dump all available memory regions."""
def dump_region(reader, start, size, location): def dump_region(reader, start, size, location):
print "%s - %s" % (reader.FormatIntPtr(start), print
reader.FormatIntPtr(start + size)) while start & 3 != 0:
for slot in xrange(start, start += 1
start + size, size -= 1
reader.PointerSize()): location += 1
maybe_address = reader.ReadUIntPtr(slot) is_executable = reader.IsProbableExecutableRegion(location, size)
heap_object = heap.FindObject(maybe_address) is_ascii = reader.IsProbableASCIIRegion(location, size)
print "%s: %s" % (reader.FormatIntPtr(slot),
reader.FormatIntPtr(maybe_address)) if is_executable is not False:
if heap_object: lines = reader.GetDisasmLines(start, size)
heap_object.Print(Printer()) for line in lines:
print print FormatDisasmLine(start, heap, line)
print
if is_ascii is not False:
# Output in the same format as the Unix hd command
addr = start
for slot in xrange(location, location + size, 16):
hex_line = ""
asc_line = ""
for i in xrange(0, 16):
if slot + i < location + size:
byte = ctypes.c_uint8.from_buffer(reader.minidump, slot + i).value
if byte >= 0x20 and byte < 0x7f:
asc_line += chr(byte)
else:
asc_line += "."
hex_line += " %02x" % (byte)
else:
hex_line += " "
if i == 7:
hex_line += " "
print "%s %s |%s|" % (reader.FormatIntPtr(addr),
hex_line,
asc_line)
addr += 16
if is_executable is not True and is_ascii is not True:
print "%s - %s" % (reader.FormatIntPtr(start),
reader.FormatIntPtr(start + size))
for slot in xrange(start,
start + size,
reader.PointerSize()):
maybe_address = reader.ReadUIntPtr(slot)
heap_object = heap.FindObject(maybe_address)
print "%s: %s" % (reader.FormatIntPtr(slot),
reader.FormatIntPtr(maybe_address))
if heap_object:
heap_object.Print(Printer())
print
reader.ForEachMemoryRegion(dump_region) reader.ForEachMemoryRegion(dump_region)
...@@ -470,6 +508,64 @@ class MinidumpReader(object): ...@@ -470,6 +508,64 @@ class MinidumpReader(object):
elif self.arch == MD_CPU_ARCHITECTURE_X86: elif self.arch == MD_CPU_ARCHITECTURE_X86:
return ctypes.c_uint32.from_buffer(self.minidump, location).value return ctypes.c_uint32.from_buffer(self.minidump, location).value
def IsProbableASCIIRegion(self, location, length):
ascii_bytes = 0
non_ascii_bytes = 0
for loc in xrange(location, location + length):
byte = ctypes.c_uint8.from_buffer(self.minidump, loc).value
if byte >= 0x7f:
non_ascii_bytes += 1
if byte < 0x20 and byte != 0:
non_ascii_bytes += 1
if byte < 0x7f and byte >= 0x20:
ascii_bytes += 1
if byte == 0xa: # newline
ascii_bytes += 1
if ascii_bytes * 10 <= length:
return False
if length > 0 and ascii_bytes > non_ascii_bytes * 7:
return True
if ascii_bytes > non_ascii_bytes * 3:
return None # Maybe
return False
def IsProbableExecutableRegion(self, location, length):
opcode_bytes = 0
sixty_four = self.arch == MD_CPU_ARCHITECTURE_AMD64
for loc in xrange(location, location + length):
byte = ctypes.c_uint8.from_buffer(self.minidump, loc).value
if (byte == 0x8b or # mov
byte == 0x89 or # mov reg-reg
(byte & 0xf0) == 0x50 or # push/pop
(sixty_four and (byte & 0xf0) == 0x40) or # rex prefix
byte == 0xc3 or # return
byte == 0x74 or # jeq
byte == 0x84 or # jeq far
byte == 0x75 or # jne
byte == 0x85 or # jne far
byte == 0xe8 or # call
byte == 0xe9 or # jmp far
byte == 0xeb): # jmp near
opcode_bytes += 1
opcode_percent = (opcode_bytes * 100) / length
threshold = 20
if opcode_percent > threshold + 2:
return True
if opcode_percent > threshold - 2:
return None # Maybe
return False
def FindRegion(self, addr):
answer = [-1, -1]
def is_in(reader, start, size, location):
if addr >= start and addr < start + size:
answer[0] = start
answer[1] = size
self.ForEachMemoryRegion(is_in)
if answer[0] == -1:
return None
return answer
def ForEachMemoryRegion(self, cb): def ForEachMemoryRegion(self, cb):
if self.memory_list64 is not None: if self.memory_list64 is not None:
for r in self.memory_list64.ranges: for r in self.memory_list64.ranges:
...@@ -1099,37 +1195,49 @@ class InspectionShell(cmd.Cmd): ...@@ -1099,37 +1195,49 @@ class InspectionShell(cmd.Cmd):
def AnalyzeMinidump(options, minidump_name): def AnalyzeMinidump(options, minidump_name):
reader = MinidumpReader(options, minidump_name) reader = MinidumpReader(options, minidump_name)
heap = None
DebugPrint("========================================") DebugPrint("========================================")
if reader.exception is None: if reader.exception is None:
print "Minidump has no exception info" print "Minidump has no exception info"
return else:
print "Exception info:" print "Exception info:"
exception_thread = reader.thread_map[reader.exception.thread_id] exception_thread = reader.thread_map[reader.exception.thread_id]
print " thread id: %d" % exception_thread.id print " thread id: %d" % exception_thread.id
print " code: %08X" % reader.exception.exception.code print " code: %08X" % reader.exception.exception.code
print " context:" print " context:"
for r in CONTEXT_FOR_ARCH[reader.arch]: for r in CONTEXT_FOR_ARCH[reader.arch]:
print " %s: %s" % (r, reader.FormatIntPtr(reader.Register(r))) print " %s: %s" % (r, reader.FormatIntPtr(reader.Register(r)))
# TODO(vitalyr): decode eflags. # TODO(vitalyr): decode eflags.
print " eflags: %s" % bin(reader.exception_context.eflags)[2:] print " eflags: %s" % bin(reader.exception_context.eflags)[2:]
print print
stack_top = reader.ExceptionSP() stack_top = reader.ExceptionSP()
stack_bottom = exception_thread.stack.start + \ stack_bottom = exception_thread.stack.start + \
exception_thread.stack.memory.data_size exception_thread.stack.memory.data_size
stack_map = {reader.ExceptionIP(): -1} stack_map = {reader.ExceptionIP(): -1}
for slot in xrange(stack_top, stack_bottom, reader.PointerSize()): for slot in xrange(stack_top, stack_bottom, reader.PointerSize()):
maybe_address = reader.ReadUIntPtr(slot) maybe_address = reader.ReadUIntPtr(slot)
if not maybe_address in stack_map: if not maybe_address in stack_map:
stack_map[maybe_address] = slot stack_map[maybe_address] = slot
heap = V8Heap(reader, stack_map) heap = V8Heap(reader, stack_map)
print "Disassembly around exception.eip:" print "Disassembly around exception.eip:"
start = reader.ExceptionIP() - EIP_PROXIMITY disasm_start = reader.ExceptionIP() - EIP_PROXIMITY
lines = reader.GetDisasmLines(start, 2 * EIP_PROXIMITY) disasm_bytes = 2 * EIP_PROXIMITY
for line in lines: if (options.full):
print FormatDisasmLine(start, heap, line) full_range = reader.FindRegion(reader.ExceptionIP())
print if full_range is not None:
disasm_start = full_range[0]
disasm_bytes = full_range[1]
lines = reader.GetDisasmLines(disasm_start, disasm_bytes)
for line in lines:
print FormatDisasmLine(disasm_start, heap, line)
print
if heap is None:
heap = V8Heap(reader, None)
if options.full: if options.full:
do_dump(reader, heap) do_dump(reader, heap)
...@@ -1137,15 +1245,16 @@ def AnalyzeMinidump(options, minidump_name): ...@@ -1137,15 +1245,16 @@ def AnalyzeMinidump(options, minidump_name):
if options.shell: if options.shell:
InspectionShell(reader, heap).cmdloop("type help to get help") InspectionShell(reader, heap).cmdloop("type help to get help")
else: else:
print "Annotated stack (from exception.esp to bottom):" if reader.exception is not None:
for slot in xrange(stack_top, stack_bottom, reader.PointerSize()): print "Annotated stack (from exception.esp to bottom):"
maybe_address = reader.ReadUIntPtr(slot) for slot in xrange(stack_top, stack_bottom, reader.PointerSize()):
heap_object = heap.FindObject(maybe_address) maybe_address = reader.ReadUIntPtr(slot)
print "%s: %s" % (reader.FormatIntPtr(slot), heap_object = heap.FindObject(maybe_address)
reader.FormatIntPtr(maybe_address)) print "%s: %s" % (reader.FormatIntPtr(slot),
if heap_object: reader.FormatIntPtr(maybe_address))
heap_object.Print(Printer()) if heap_object:
print heap_object.Print(Printer())
print
reader.Dispose() reader.Dispose()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment