Revision: 11621
Author:   [email protected]
Date:     Tue May 22 04:08:05 2012
Log: Grokdump -f: Automatically detect memory that is x86/x64 instructions or text and dump appropriately.
Review URL: https://chromiumcodereview.appspot.com/10356150
http://code.google.com/p/v8/source/detail?r=11621

Modified:
 /branches/bleeding_edge/tools/grokdump.py

=======================================
--- /branches/bleeding_edge/tools/grokdump.py   Mon May 14 00:57:56 2012
+++ /branches/bleeding_edge/tools/grokdump.py   Tue May 22 04:08:05 2012
@@ -111,18 +111,56 @@
 def do_dump(reader, heap):
   """Dump all available memory regions."""
   def dump_region(reader, start, size, location):
-    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
+    print
+    while start & 3 != 0:
+      start += 1
+      size -= 1
+      location += 1
+    is_executable = reader.IsProbableExecutableRegion(location, size)
+    is_ascii = reader.IsProbableASCIIRegion(location, size)
+
+    if is_executable is not False:
+      lines = reader.GetDisasmLines(start, size)
+      for line in lines:
+        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)

@@ -470,6 +508,64 @@
     elif self.arch == MD_CPU_ARCHITECTURE_X86:
       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):
     if self.memory_list64 is not None:
       for r in self.memory_list64.ranges:
@@ -1099,37 +1195,49 @@

 def AnalyzeMinidump(options, minidump_name):
   reader = MinidumpReader(options, minidump_name)
+  heap = None
   DebugPrint("========================================")
   if reader.exception is None:
     print "Minidump has no exception info"
-    return
-  print "Exception info:"
-  exception_thread = reader.thread_map[reader.exception.thread_id]
-  print "  thread id: %d" % exception_thread.id
-  print "  code: %08X" % reader.exception.exception.code
-  print "  context:"
-  for r in CONTEXT_FOR_ARCH[reader.arch]:
-    print "    %s: %s" % (r, reader.FormatIntPtr(reader.Register(r)))
-  # TODO(vitalyr): decode eflags.
-  print "    eflags: %s" % bin(reader.exception_context.eflags)[2:]
-  print
-
-  stack_top = reader.ExceptionSP()
-  stack_bottom = exception_thread.stack.start + \
-      exception_thread.stack.memory.data_size
-  stack_map = {reader.ExceptionIP(): -1}
-  for slot in xrange(stack_top, stack_bottom, reader.PointerSize()):
-    maybe_address = reader.ReadUIntPtr(slot)
-    if not maybe_address in stack_map:
-      stack_map[maybe_address] = slot
-  heap = V8Heap(reader, stack_map)
-
-  print "Disassembly around exception.eip:"
-  start = reader.ExceptionIP() - EIP_PROXIMITY
-  lines = reader.GetDisasmLines(start, 2 * EIP_PROXIMITY)
-  for line in lines:
-    print FormatDisasmLine(start, heap, line)
-  print
+  else:
+    print "Exception info:"
+    exception_thread = reader.thread_map[reader.exception.thread_id]
+    print "  thread id: %d" % exception_thread.id
+    print "  code: %08X" % reader.exception.exception.code
+    print "  context:"
+    for r in CONTEXT_FOR_ARCH[reader.arch]:
+      print "    %s: %s" % (r, reader.FormatIntPtr(reader.Register(r)))
+    # TODO(vitalyr): decode eflags.
+    print "    eflags: %s" % bin(reader.exception_context.eflags)[2:]
+    print
+
+    stack_top = reader.ExceptionSP()
+    stack_bottom = exception_thread.stack.start + \
+        exception_thread.stack.memory.data_size
+    stack_map = {reader.ExceptionIP(): -1}
+    for slot in xrange(stack_top, stack_bottom, reader.PointerSize()):
+      maybe_address = reader.ReadUIntPtr(slot)
+      if not maybe_address in stack_map:
+        stack_map[maybe_address] = slot
+    heap = V8Heap(reader, stack_map)
+
+    print "Disassembly around exception.eip:"
+    disasm_start = reader.ExceptionIP() - EIP_PROXIMITY
+    disasm_bytes = 2 * EIP_PROXIMITY
+    if (options.full):
+      full_range = reader.FindRegion(reader.ExceptionIP())
+      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:
     do_dump(reader, heap)
@@ -1137,15 +1245,16 @@
   if options.shell:
     InspectionShell(reader, heap).cmdloop("type help to get help")
   else:
-    print "Annotated stack (from exception.esp to bottom):"
-    for slot in xrange(stack_top, stack_bottom, 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
+    if reader.exception is not None:
+      print "Annotated stack (from exception.esp to bottom):"
+      for slot in xrange(stack_top, stack_bottom, 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.Dispose()

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to