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

Side by Side Diff: tools/grokdump.py

Issue 10378087: Extend grokdump with basic interactive shell capabilities. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: clean things a bit 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
11 # copyright notice, this list of conditions and the following 11 # copyright notice, this list of conditions and the following
12 # disclaimer in the documentation and/or other materials provided 12 # disclaimer in the documentation and/or other materials provided
13 # with the distribution. 13 # with the distribution.
14 # * Neither the name of Google Inc. nor the names of its 14 # * Neither the name of Google Inc. nor the names of its
15 # contributors may be used to endorse or promote products derived 15 # contributors may be used to endorse or promote products derived
16 # from this software without specific prior written permission. 16 # from this software without specific prior written permission.
17 # 17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 29
30 import cmd
30 import ctypes 31 import ctypes
31 import mmap 32 import mmap
32 import optparse 33 import optparse
33 import os 34 import os
34 import disasm 35 import disasm
35 import sys 36 import sys
36 import types 37 import types
37 import codecs 38 import codecs
38 import re 39 import re
40 import struct
39 41
40 42
41 USAGE="""usage: %prog [OPTION]... 43 USAGE="""usage: %prog [OPTION]...
42 44
43 Minidump analyzer. 45 Minidump analyzer.
44 46
45 Shows the processor state at the point of exception including the 47 Shows the processor state at the point of exception including the
46 stack of the active thread and the referenced objects in the V8 48 stack of the active thread and the referenced objects in the V8
47 heap. Code objects are disassembled and the addresses linked from the 49 heap. Code objects are disassembled and the addresses linked from the
48 stack (pushed return addresses) are marked with "=>". 50 stack (pushed return addresses) are marked with "=>".
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 def ReadUIntPtr(self, address): 439 def ReadUIntPtr(self, address):
438 if self.arch == MD_CPU_ARCHITECTURE_AMD64: 440 if self.arch == MD_CPU_ARCHITECTURE_AMD64:
439 return self.ReadU64(address) 441 return self.ReadU64(address)
440 elif self.arch == MD_CPU_ARCHITECTURE_X86: 442 elif self.arch == MD_CPU_ARCHITECTURE_X86:
441 return self.ReadU32(address) 443 return self.ReadU32(address)
442 444
443 def ReadBytes(self, address, size): 445 def ReadBytes(self, address, size):
444 location = self.FindLocation(address) 446 location = self.FindLocation(address)
445 return self.minidump[location:location + size] 447 return self.minidump[location:location + size]
446 448
449 def _ReadWord(self, location):
450 if self.arch == MD_CPU_ARCHITECTURE_AMD64:
451 return ctypes.c_uint64.from_buffer(self.minidump, location).value
452 elif self.arch == MD_CPU_ARCHITECTURE_X86:
453 return ctypes.c_uint32.from_buffer(self.minidump, location).value
454
455 def ForEachMemoryRegion(self, cb):
456 if self.memory_list64 is not None:
457 for r in self.memory_list64.ranges:
458 location = self.memory_list64.base_rva + offset
459 cb(self, r.start, r.size, location)
460 offset += r.size
461
462 if self.memory_list is not None:
463 for r in self.memory_list.ranges:
464 cb(self, r.start, r.memory.data_size, r.memory.rva)
465
466 def FindWord(self, word):
467 def search_inside_region(reader, start, size, location):
468 for loc in xrange(location, location + size):
469 if reader._ReadWord(loc) == word:
470 slot = start + (loc - location)
471 print "%s: %s" % (reader.FormatIntPtr(slot),
472 reader.FormatIntPtr(word))
473
474 self.ForEachMemoryRegion(search_inside_region)
475
447 def FindLocation(self, address): 476 def FindLocation(self, address):
448 offset = 0 477 offset = 0
449 if self.memory_list64 is not None: 478 if self.memory_list64 is not None:
450 for r in self.memory_list64.ranges: 479 for r in self.memory_list64.ranges:
451 if r.start <= address < r.start + r.size: 480 if r.start <= address < r.start + r.size:
452 return self.memory_list64.base_rva + offset + address - r.start 481 return self.memory_list64.base_rva + offset + address - r.start
453 offset += r.size 482 offset += r.size
454 if self.memory_list is not None: 483 if self.memory_list is not None:
455 for r in self.memory_list.ranges: 484 for r in self.memory_list.ranges:
456 if r.start <= address < r.start + r.memory.data_size: 485 if r.start <= address < r.start + r.memory.data_size:
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after
1004 1033
1005 EIP_PROXIMITY = 64 1034 EIP_PROXIMITY = 64
1006 1035
1007 CONTEXT_FOR_ARCH = { 1036 CONTEXT_FOR_ARCH = {
1008 MD_CPU_ARCHITECTURE_AMD64: 1037 MD_CPU_ARCHITECTURE_AMD64:
1009 ['rax', 'rbx', 'rcx', 'rdx', 'rdi', 'rsi', 'rbp', 'rsp', 'rip'], 1038 ['rax', 'rbx', 'rcx', 'rdx', 'rdi', 'rsi', 'rbp', 'rsp', 'rip'],
1010 MD_CPU_ARCHITECTURE_X86: 1039 MD_CPU_ARCHITECTURE_X86:
1011 ['eax', 'ebx', 'ecx', 'edx', 'edi', 'esi', 'ebp', 'esp', 'eip'] 1040 ['eax', 'ebx', 'ecx', 'edx', 'edi', 'esi', 'ebp', 'esp', 'eip']
1012 } 1041 }
1013 1042
1043 class InspectionShell(cmd.Cmd):
1044 def __init__(self, reader, heap):
1045 cmd.Cmd.__init__(self)
1046 self.reader = reader
1047 self.heap = heap
1048 self.prompt = "(grok) "
1049
1050 def do_dd(self, address):
1051 """Interpret memory at the given address (if available)
1052 as a sequence of words."""
1053 start = int(address, 0)
1054 for slot in xrange(start,
1055 start + self.reader.PointerSize() * 10,
1056 self.reader.PointerSize()):
1057 maybe_address = self.reader.ReadUIntPtr(slot)
1058 heap_object = self.heap.FindObject(maybe_address)
1059 print "%s: %s" % (self.reader.FormatIntPtr(slot),
1060 self.reader.FormatIntPtr(maybe_address))
1061 if heap_object:
1062 heap_object.Print(Printer())
1063 print
1064
1065 def do_s(self, word):
1066 "Search for a given word in available memory regions"
1067 word = int(word, 0)
1068 print "searching for word", word
1069 self.reader.FindWord(word)
1070
1071 def do_list(self, smth):
1072 """List all available memory regions."""
1073 def print_region(reader, start, size, location):
1074 print "%s - %s" % (reader.FormatIntPtr(start),
1075 reader.FormatIntPtr(start + size))
1076
1077 self.reader.ForEachMemoryRegion(print_region)
1078
1014 def AnalyzeMinidump(options, minidump_name): 1079 def AnalyzeMinidump(options, minidump_name):
1015 reader = MinidumpReader(options, minidump_name) 1080 reader = MinidumpReader(options, minidump_name)
1016 DebugPrint("========================================") 1081 DebugPrint("========================================")
1017 if reader.exception is None: 1082 if reader.exception is None:
1018 print "Minidump has no exception info" 1083 print "Minidump has no exception info"
1019 return 1084 return
1020 print "Exception info:" 1085 print "Exception info:"
1021 exception_thread = reader.thread_map[reader.exception.thread_id] 1086 exception_thread = reader.thread_map[reader.exception.thread_id]
1022 print " thread id: %d" % exception_thread.id 1087 print " thread id: %d" % exception_thread.id
1023 print " code: %08X" % reader.exception.exception.code 1088 print " code: %08X" % reader.exception.exception.code
(...skipping 14 matching lines...) Expand all
1038 stack_map[maybe_address] = slot 1103 stack_map[maybe_address] = slot
1039 heap = V8Heap(reader, stack_map) 1104 heap = V8Heap(reader, stack_map)
1040 1105
1041 print "Disassembly around exception.eip:" 1106 print "Disassembly around exception.eip:"
1042 start = reader.ExceptionIP() - EIP_PROXIMITY 1107 start = reader.ExceptionIP() - EIP_PROXIMITY
1043 lines = reader.GetDisasmLines(start, 2 * EIP_PROXIMITY) 1108 lines = reader.GetDisasmLines(start, 2 * EIP_PROXIMITY)
1044 for line in lines: 1109 for line in lines:
1045 print FormatDisasmLine(start, heap, line) 1110 print FormatDisasmLine(start, heap, line)
1046 print 1111 print
1047 1112
1048 print "Annotated stack (from exception.esp to bottom):" 1113 if options.shell:
1049 for slot in xrange(stack_top, stack_bottom, reader.PointerSize()): 1114 InspectionShell(reader, heap).cmdloop()
1050 maybe_address = reader.ReadUIntPtr(slot) 1115 else:
1051 heap_object = heap.FindObject(maybe_address) 1116 print "Annotated stack (from exception.esp to bottom):"
1052 print "%s: %s" % (reader.FormatIntPtr(slot), 1117 for slot in xrange(stack_top, stack_bottom, reader.PointerSize()):
1053 reader.FormatIntPtr(maybe_address)) 1118 maybe_address = reader.ReadUIntPtr(slot)
1054 if heap_object: 1119 heap_object = heap.FindObject(maybe_address)
1055 heap_object.Print(Printer()) 1120 print "%s: %s" % (reader.FormatIntPtr(slot),
1056 print 1121 reader.FormatIntPtr(maybe_address))
1122 if heap_object:
1123 heap_object.Print(Printer())
1124 print
1057 1125
1058 reader.Dispose() 1126 reader.Dispose()
1059 1127
1060 1128
1061 if __name__ == "__main__": 1129 if __name__ == "__main__":
1062 parser = optparse.OptionParser(USAGE) 1130 parser = optparse.OptionParser(USAGE)
1131 parser.add_option("-s", "--shell", dest="shell", action="store_true")
1063 options, args = parser.parse_args() 1132 options, args = parser.parse_args()
1064 if len(args) != 1: 1133 if len(args) != 1:
1065 parser.print_help() 1134 parser.print_help()
1066 sys.exit(1) 1135 sys.exit(1)
1067 AnalyzeMinidump(options, args[0]) 1136 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