Extend grokdump with basic interactive shell capabilities.
authorvegorov@chromium.org <vegorov@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 10 May 2012 12:44:15 +0000 (12:44 +0000)
committervegorov@chromium.org <vegorov@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 10 May 2012 12:44:15 +0000 (12:44 +0000)
Supported commands:

- dd: to print memory region
- s: to search for a word in available memory regions
- list: to list available memory regions

R=mstarzinger@chromium.org

Review URL: https://chromiumcodereview.appspot.com/10378087

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11537 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

tools/grokdump.py

index 9977289..f5df489 100755 (executable)
@@ -27,6 +27,7 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+import cmd
 import ctypes
 import mmap
 import optparse
@@ -36,6 +37,7 @@ import sys
 import types
 import codecs
 import re
+import struct
 
 
 USAGE="""usage: %prog [OPTION]...
@@ -444,6 +446,33 @@ class MinidumpReader(object):
     location = self.FindLocation(address)
     return self.minidump[location:location + size]
 
+  def _ReadWord(self, location):
+    if self.arch == MD_CPU_ARCHITECTURE_AMD64:
+      return ctypes.c_uint64.from_buffer(self.minidump, location).value
+    elif self.arch == MD_CPU_ARCHITECTURE_X86:
+      return ctypes.c_uint32.from_buffer(self.minidump, location).value
+
+  def ForEachMemoryRegion(self, cb):
+    if self.memory_list64 is not None:
+      for r in self.memory_list64.ranges:
+        location = self.memory_list64.base_rva + offset
+        cb(self, r.start, r.size, location)
+        offset += r.size
+
+    if self.memory_list is not None:
+      for r in self.memory_list.ranges:
+        cb(self, r.start, r.memory.data_size, r.memory.rva)
+
+  def FindWord(self, word):
+    def search_inside_region(reader, start, size, location):
+      for loc in xrange(location, location + size):
+        if reader._ReadWord(loc) == word:
+          slot = start + (loc - location)
+          print "%s: %s" % (reader.FormatIntPtr(slot),
+                            reader.FormatIntPtr(word))
+
+    self.ForEachMemoryRegion(search_inside_region)
+
   def FindLocation(self, address):
     offset = 0
     if self.memory_list64 is not None:
@@ -1011,6 +1040,42 @@ CONTEXT_FOR_ARCH = {
       ['eax', 'ebx', 'ecx', 'edx', 'edi', 'esi', 'ebp', 'esp', 'eip']
 }
 
+class InspectionShell(cmd.Cmd):
+  def __init__(self, reader, heap):
+    cmd.Cmd.__init__(self)
+    self.reader = reader
+    self.heap = heap
+    self.prompt = "(grok) "
+
+  def do_dd(self, address):
+    "Interpret memory at the given address (if available)"\
+    " as a sequence of words."
+    start = int(address, 16)
+    for slot in xrange(start,
+                       start + self.reader.PointerSize() * 10,
+                       self.reader.PointerSize()):
+      maybe_address = self.reader.ReadUIntPtr(slot)
+      heap_object = self.heap.FindObject(maybe_address)
+      print "%s: %s" % (self.reader.FormatIntPtr(slot),
+                        self.reader.FormatIntPtr(maybe_address))
+      if heap_object:
+        heap_object.Print(Printer())
+        print
+
+  def do_s(self, word):
+    "Search for a given word in available memory regions"
+    word = int(word, 0)
+    print "searching for word", word
+    self.reader.FindWord(word)
+
+  def do_list(self, smth):
+    """List all available memory regions."""
+    def print_region(reader, start, size, location):
+      print "%s - %s" % (reader.FormatIntPtr(start),
+                         reader.FormatIntPtr(start + size))
+
+    self.reader.ForEachMemoryRegion(print_region)
+
 def AnalyzeMinidump(options, minidump_name):
   reader = MinidumpReader(options, minidump_name)
   DebugPrint("========================================")
@@ -1045,21 +1110,25 @@ def AnalyzeMinidump(options, minidump_name):
     print FormatDisasmLine(start, heap, line)
   print
 
-  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 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
 
   reader.Dispose()
 
 
 if __name__ == "__main__":
   parser = optparse.OptionParser(USAGE)
+  parser.add_option("-s", "--shell", dest="shell", action="store_true")
   options, args = parser.parse_args()
   if len(args) != 1:
     parser.print_help()