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
This commit is contained in:
parent
367757b794
commit
5cd40f740d
@ -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):
|
|||||||
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):
|
|||||||
|
|
||||||
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):
|
|||||||
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()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user