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

Side by Side Diff: tools/grokdump.py

Issue 10923003: Extend grokdump.py with simple BreakPad symbol files support. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 3 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 2012 the V8 project authors. All rights reserved. 3 # Copyright 2012 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 bisect
30 import cmd 31 import cmd
31 import ctypes 32 import ctypes
32 import mmap 33 import mmap
33 import optparse 34 import optparse
34 import os 35 import os
35 import disasm 36 import disasm
Michael Starzinger 2012/09/19 09:54:32 I know you didn't touch, but can we alpha-sort the
Vyacheslav Egorov (Google) 2012/09/26 12:48:57 Done.
36 import sys 37 import sys
37 import types 38 import types
38 import codecs 39 import codecs
39 import re 40 import re
40 import struct 41 import struct
41 42
42 43
43 USAGE="""usage: %prog [OPTIONS] [DUMP-FILE] 44 USAGE="""usage: %prog [OPTIONS] [DUMP-FILE]
44 45
45 Minidump analyzer. 46 Minidump analyzer.
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 ("checksum", ctypes.c_uint32), 174 ("checksum", ctypes.c_uint32),
174 ("time_date_stampt", ctypes.c_uint32), 175 ("time_date_stampt", ctypes.c_uint32),
175 ("flags", ctypes.c_uint64) 176 ("flags", ctypes.c_uint64)
176 ]) 177 ])
177 178
178 MINIDUMP_LOCATION_DESCRIPTOR = Descriptor([ 179 MINIDUMP_LOCATION_DESCRIPTOR = Descriptor([
179 ("data_size", ctypes.c_uint32), 180 ("data_size", ctypes.c_uint32),
180 ("rva", ctypes.c_uint32) 181 ("rva", ctypes.c_uint32)
181 ]) 182 ])
182 183
184 MINIDUMP_STRING = Descriptor([
185 ("length", ctypes.c_uint32),
186 ("buffer", lambda t: ctypes.c_uint8 * (t.length + 2))
187 ])
188
183 MINIDUMP_DIRECTORY = Descriptor([ 189 MINIDUMP_DIRECTORY = Descriptor([
184 ("stream_type", ctypes.c_uint32), 190 ("stream_type", ctypes.c_uint32),
185 ("location", MINIDUMP_LOCATION_DESCRIPTOR.ctype) 191 ("location", MINIDUMP_LOCATION_DESCRIPTOR.ctype)
186 ]) 192 ])
187 193
188 MD_EXCEPTION_MAXIMUM_PARAMETERS = 15 194 MD_EXCEPTION_MAXIMUM_PARAMETERS = 15
189 195
190 MINIDUMP_EXCEPTION = Descriptor([ 196 MINIDUMP_EXCEPTION = Descriptor([
191 ("code", ctypes.c_uint32), 197 ("code", ctypes.c_uint32),
192 ("flags", ctypes.c_uint32), 198 ("flags", ctypes.c_uint32),
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 ("ted", ctypes.c_uint64), 399 ("ted", ctypes.c_uint64),
394 ("stack", MINIDUMP_MEMORY_DESCRIPTOR.ctype), 400 ("stack", MINIDUMP_MEMORY_DESCRIPTOR.ctype),
395 ("context", MINIDUMP_LOCATION_DESCRIPTOR.ctype) 401 ("context", MINIDUMP_LOCATION_DESCRIPTOR.ctype)
396 ]) 402 ])
397 403
398 MINIDUMP_THREAD_LIST = Descriptor([ 404 MINIDUMP_THREAD_LIST = Descriptor([
399 ("thread_count", ctypes.c_uint32), 405 ("thread_count", ctypes.c_uint32),
400 ("threads", lambda t: MINIDUMP_THREAD.ctype * t.thread_count) 406 ("threads", lambda t: MINIDUMP_THREAD.ctype * t.thread_count)
401 ]) 407 ])
402 408
409 MINIDUMP_RAW_MODULE = Descriptor([
410 ("base_of_image", ctypes.c_uint64),
411 ("size_of_image", ctypes.c_uint32),
412 ("checksum", ctypes.c_uint32),
413 ("time_date_stamp", ctypes.c_uint32),
414 ("module_name_rva", ctypes.c_uint32),
415 ("version_info", ctypes.c_uint32 * 13),
416 ("cv_record", MINIDUMP_LOCATION_DESCRIPTOR.ctype),
417 ("misc_record", MINIDUMP_LOCATION_DESCRIPTOR.ctype),
418 ("reserved0", ctypes.c_uint32 * 2),
419 ("reserved1", ctypes.c_uint32 * 2)
420 ])
421
422 MINIDUMP_MODULE_LIST = Descriptor([
423 ("number_of_modules", ctypes.c_uint32),
424 ("modules", lambda t: MINIDUMP_RAW_MODULE.ctype * t.number_of_modules)
425 ])
426
403 MINIDUMP_RAW_SYSTEM_INFO = Descriptor([ 427 MINIDUMP_RAW_SYSTEM_INFO = Descriptor([
404 ("processor_architecture", ctypes.c_uint16) 428 ("processor_architecture", ctypes.c_uint16)
405 ]) 429 ])
406 430
407 MD_CPU_ARCHITECTURE_X86 = 0 431 MD_CPU_ARCHITECTURE_X86 = 0
408 MD_CPU_ARCHITECTURE_AMD64 = 9 432 MD_CPU_ARCHITECTURE_AMD64 = 9
409 433
434 class FuncSymbol:
435 def __init__(self, start, size, name):
436 self.start = start
437 self.end = self.start + size
438 self.name = name
439
440 def __cmp__(self, other):
441 if isinstance(other, FuncSymbol):
442 return self.start - other.start
443 return self.start - other
444
445 def Covers(self, addr):
446 return (self.start <= addr) and (addr < self.end)
447
410 class MinidumpReader(object): 448 class MinidumpReader(object):
411 """Minidump (.dmp) reader.""" 449 """Minidump (.dmp) reader."""
412 450
413 _HEADER_MAGIC = 0x504d444d 451 _HEADER_MAGIC = 0x504d444d
414 452
415 def __init__(self, options, minidump_name): 453 def __init__(self, options, minidump_name):
416 self.minidump_name = minidump_name 454 self.minidump_name = minidump_name
417 self.minidump_file = open(minidump_name, "r") 455 self.minidump_file = open(minidump_name, "r")
418 self.minidump = mmap.mmap(self.minidump_file.fileno(), 0, mmap.MAP_PRIVATE) 456 self.minidump = mmap.mmap(self.minidump_file.fileno(), 0, mmap.MAP_PRIVATE)
419 self.header = MINIDUMP_HEADER.Read(self.minidump, 0) 457 self.header = MINIDUMP_HEADER.Read(self.minidump, 0)
420 if self.header.signature != MinidumpReader._HEADER_MAGIC: 458 if self.header.signature != MinidumpReader._HEADER_MAGIC:
421 print >>sys.stderr, "Warning: Unsupported minidump header magic!" 459 print >>sys.stderr, "Warning: Unsupported minidump header magic!"
422 DebugPrint(self.header) 460 DebugPrint(self.header)
423 directories = [] 461 directories = []
424 offset = self.header.stream_directories_rva 462 offset = self.header.stream_directories_rva
425 for _ in xrange(self.header.stream_count): 463 for _ in xrange(self.header.stream_count):
426 directories.append(MINIDUMP_DIRECTORY.Read(self.minidump, offset)) 464 directories.append(MINIDUMP_DIRECTORY.Read(self.minidump, offset))
427 offset += MINIDUMP_DIRECTORY.size 465 offset += MINIDUMP_DIRECTORY.size
428 self.arch = None 466 self.arch = None
429 self.exception = None 467 self.exception = None
430 self.exception_context = None 468 self.exception_context = None
431 self.memory_list = None 469 self.memory_list = None
432 self.memory_list64 = None 470 self.memory_list64 = None
471 self.module_list = None
433 self.thread_map = {} 472 self.thread_map = {}
434 473
474 self.symdir = options.symdir
475 self.modules_with_symbols = []
476 self.symbols = []
477
435 # Find MDRawSystemInfo stream and determine arch. 478 # Find MDRawSystemInfo stream and determine arch.
436 for d in directories: 479 for d in directories:
437 if d.stream_type == MD_SYSTEM_INFO_STREAM: 480 if d.stream_type == MD_SYSTEM_INFO_STREAM:
438 system_info = MINIDUMP_RAW_SYSTEM_INFO.Read( 481 system_info = MINIDUMP_RAW_SYSTEM_INFO.Read(
439 self.minidump, d.location.rva) 482 self.minidump, d.location.rva)
440 self.arch = system_info.processor_architecture 483 self.arch = system_info.processor_architecture
441 assert self.arch in [MD_CPU_ARCHITECTURE_AMD64, MD_CPU_ARCHITECTURE_X86] 484 assert self.arch in [MD_CPU_ARCHITECTURE_AMD64, MD_CPU_ARCHITECTURE_X86]
442 assert not self.arch is None 485 assert not self.arch is None
443 486
444 for d in directories: 487 for d in directories:
445 DebugPrint(d) 488 DebugPrint(d)
446 if d.stream_type == MD_EXCEPTION_STREAM: 489 if d.stream_type == MD_EXCEPTION_STREAM:
447 self.exception = MINIDUMP_EXCEPTION_STREAM.Read( 490 self.exception = MINIDUMP_EXCEPTION_STREAM.Read(
448 self.minidump, d.location.rva) 491 self.minidump, d.location.rva)
449 DebugPrint(self.exception) 492 DebugPrint(self.exception)
450 if self.arch == MD_CPU_ARCHITECTURE_X86: 493 if self.arch == MD_CPU_ARCHITECTURE_X86:
451 self.exception_context = MINIDUMP_CONTEXT_X86.Read( 494 self.exception_context = MINIDUMP_CONTEXT_X86.Read(
452 self.minidump, self.exception.thread_context.rva) 495 self.minidump, self.exception.thread_context.rva)
453 elif self.arch == MD_CPU_ARCHITECTURE_AMD64: 496 elif self.arch == MD_CPU_ARCHITECTURE_AMD64:
454 self.exception_context = MINIDUMP_CONTEXT_AMD64.Read( 497 self.exception_context = MINIDUMP_CONTEXT_AMD64.Read(
455 self.minidump, self.exception.thread_context.rva) 498 self.minidump, self.exception.thread_context.rva)
456 DebugPrint(self.exception_context) 499 DebugPrint(self.exception_context)
457 elif d.stream_type == MD_THREAD_LIST_STREAM: 500 elif d.stream_type == MD_THREAD_LIST_STREAM:
458 thread_list = MINIDUMP_THREAD_LIST.Read(self.minidump, d.location.rva) 501 thread_list = MINIDUMP_THREAD_LIST.Read(self.minidump, d.location.rva)
459 assert ctypes.sizeof(thread_list) == d.location.data_size 502 assert ctypes.sizeof(thread_list) == d.location.data_size
460 DebugPrint(thread_list) 503 DebugPrint(thread_list)
461 for thread in thread_list.threads: 504 for thread in thread_list.threads:
462 DebugPrint(thread) 505 DebugPrint(thread)
463 self.thread_map[thread.id] = thread 506 self.thread_map[thread.id] = thread
507 elif d.stream_type == MD_MODULE_LIST_STREAM:
508 assert self.module_list is None
509 self.module_list = MINIDUMP_MODULE_LIST.Read(
510 self.minidump, d.location.rva)
511 assert ctypes.sizeof(self.module_list) == d.location.data_size
464 elif d.stream_type == MD_MEMORY_LIST_STREAM: 512 elif d.stream_type == MD_MEMORY_LIST_STREAM:
465 print >>sys.stderr, "Warning: This is not a full minidump!" 513 print >>sys.stderr, "Warning: This is not a full minidump!"
466 assert self.memory_list is None 514 assert self.memory_list is None
467 self.memory_list = MINIDUMP_MEMORY_LIST.Read( 515 self.memory_list = MINIDUMP_MEMORY_LIST.Read(
468 self.minidump, d.location.rva) 516 self.minidump, d.location.rva)
469 assert ctypes.sizeof(self.memory_list) == d.location.data_size 517 assert ctypes.sizeof(self.memory_list) == d.location.data_size
470 DebugPrint(self.memory_list) 518 DebugPrint(self.memory_list)
471 elif d.stream_type == MD_MEMORY_64_LIST_STREAM: 519 elif d.stream_type == MD_MEMORY_64_LIST_STREAM:
472 assert self.memory_list64 is None 520 assert self.memory_list64 is None
473 self.memory_list64 = MINIDUMP_MEMORY_LIST64.Read( 521 self.memory_list64 = MINIDUMP_MEMORY_LIST64.Read(
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
637 685
638 def PointerSize(self): 686 def PointerSize(self):
639 if self.arch == MD_CPU_ARCHITECTURE_AMD64: 687 if self.arch == MD_CPU_ARCHITECTURE_AMD64:
640 return 8 688 return 8
641 elif self.arch == MD_CPU_ARCHITECTURE_X86: 689 elif self.arch == MD_CPU_ARCHITECTURE_X86:
642 return 4 690 return 4
643 691
644 def Register(self, name): 692 def Register(self, name):
645 return self.exception_context.__getattribute__(name) 693 return self.exception_context.__getattribute__(name)
646 694
695 def ReadMinidumpString(self, rva):
696 string = bytearray(MINIDUMP_STRING.Read(self.minidump, rva).buffer)
697 string = string.decode("utf16")
698 return string[0:len(string) - 1]
699
700 # Load FUNC records from a BreakPad symbol file
701 #
702 # http://code.google.com/p/google-breakpad/wiki/SymbolFiles
703 #
704 def _LoadSymbolsFrom(self, symfile, baseaddr):
705 print "Loading symbols from %s" % (symfile)
706 funcs = []
707 with open(symfile) as f:
708 for line in f:
709 result = re.match(r"^FUNC ([a-f0-9]+) ([a-f0-9]+) ([a-f0-9]+) (.*)$", li ne)
Michael Starzinger 2012/09/19 09:54:32 More than 80 characters.
Vyacheslav Egorov (Google) 2012/09/26 12:48:57 Done.
710 if result is not None:
711 start = int(result.group(1), 16)
712 size = int(result.group(2), 16)
713 name = result.group(4).rstrip()
714 bisect.insort_left(self.symbols, FuncSymbol(baseaddr + start, size, na me))
Michael Starzinger 2012/09/19 09:54:32 More than 80 characters.
Vyacheslav Egorov (Google) 2012/09/26 12:48:57 Done.
715 print " ... done"
716
717 def TryLoadSymbolsFor(self, modulename, module):
718 try:
719 symfile = os.path.join(self.symdir,
720 modulename.replace('.', '_') + ".pdb.sym")
721 self._LoadSymbolsFrom(symfile, module.base_of_image)
722 self.modules_with_symbols.append(module)
723 except Exception as e:
724 print " ... failure (%s)" % (e)
725
726 # Returns true if address is covered by some module that has loaded symbols.
727 def _IsInModuleWithSymbols(self, addr):
728 for module in self.modules_with_symbols:
729 start = module.base_of_image
730 end = start + module.size_of_image
731 if (start <= addr) and (addr < end):
732 return True
733 return False
734
735 # Find symbol covering the given address and return its name in format
736 # <symbol name>+<offset from the start>
737 def FindSymbol(self, addr):
738 if not self._IsInModuleWithSymbols(addr):
739 return None
740
741 i = bisect.bisect_left(self.symbols, addr)
742 symbol = None
743 if (0 < i) and self.symbols[i - 1].Covers(addr):
744 symbol = self.symbols[i - 1]
745 elif (i < len(self.symbols)) and self.symbols[i].Covers(addr):
746 symbol = self.symbols[i]
747 else:
748 return None
749 diff = addr - symbol.start
750 return "%s+0x%x" % (symbol.name, diff)
751
752
647 753
648 # List of V8 instance types. Obtained by adding the code below to any .cc file. 754 # List of V8 instance types. Obtained by adding the code below to any .cc file.
649 # 755 #
650 # #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", T, #T); 756 # #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", T, #T);
651 # struct P { 757 # struct P {
652 # P() { 758 # P() {
653 # printf("INSTANCE_TYPES = {\n"); 759 # printf("INSTANCE_TYPES = {\n");
654 # INSTANCE_TYPE_LIST(DUMP_TYPE) 760 # INSTANCE_TYPE_LIST(DUMP_TYPE)
655 # printf("}\n"); 761 # printf("}\n");
656 # } 762 # }
(...skipping 975 matching lines...) Expand 10 before | Expand all | Expand 10 after
1632 EIP_PROXIMITY = 64 1738 EIP_PROXIMITY = 64
1633 1739
1634 CONTEXT_FOR_ARCH = { 1740 CONTEXT_FOR_ARCH = {
1635 MD_CPU_ARCHITECTURE_AMD64: 1741 MD_CPU_ARCHITECTURE_AMD64:
1636 ['rax', 'rbx', 'rcx', 'rdx', 'rdi', 'rsi', 'rbp', 'rsp', 'rip', 1742 ['rax', 'rbx', 'rcx', 'rdx', 'rdi', 'rsi', 'rbp', 'rsp', 'rip',
1637 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15'], 1743 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15'],
1638 MD_CPU_ARCHITECTURE_X86: 1744 MD_CPU_ARCHITECTURE_X86:
1639 ['eax', 'ebx', 'ecx', 'edx', 'edi', 'esi', 'ebp', 'esp', 'eip'] 1745 ['eax', 'ebx', 'ecx', 'edx', 'edi', 'esi', 'ebp', 'esp', 'eip']
1640 } 1746 }
1641 1747
1748 KNOWN_MODULES = {'chrome.exe', 'chrome.dll'}
1749
1750 def GetModuleName(reader, module):
1751 name = reader.ReadMinidumpString(module.module_name_rva)
1752 return str(os.path.basename(str(name).replace("\\", "/")))
1642 1753
1643 def AnalyzeMinidump(options, minidump_name): 1754 def AnalyzeMinidump(options, minidump_name):
1644 reader = MinidumpReader(options, minidump_name) 1755 reader = MinidumpReader(options, minidump_name)
1645 heap = None 1756 heap = None
1646 DebugPrint("========================================") 1757 DebugPrint("========================================")
1647 if reader.exception is None: 1758 if reader.exception is None:
1648 print "Minidump has no exception info" 1759 print "Minidump has no exception info"
1649 else: 1760 else:
1650 print "Exception info:" 1761 print "Exception info:"
1651 exception_thread = reader.thread_map[reader.exception.thread_id] 1762 exception_thread = reader.thread_map[reader.exception.thread_id]
1652 print " thread id: %d" % exception_thread.id 1763 print " thread id: %d" % exception_thread.id
1653 print " code: %08X" % reader.exception.exception.code 1764 print " code: %08X" % reader.exception.exception.code
1654 print " context:" 1765 print " context:"
1655 for r in CONTEXT_FOR_ARCH[reader.arch]: 1766 for r in CONTEXT_FOR_ARCH[reader.arch]:
1656 print " %s: %s" % (r, reader.FormatIntPtr(reader.Register(r))) 1767 print " %s: %s" % (r, reader.FormatIntPtr(reader.Register(r)))
1657 # TODO(vitalyr): decode eflags. 1768 # TODO(vitalyr): decode eflags.
1658 print " eflags: %s" % bin(reader.exception_context.eflags)[2:] 1769 print " eflags: %s" % bin(reader.exception_context.eflags)[2:]
1659 print 1770 print
Michael Starzinger 2012/09/19 09:54:32 Can we move this empty print to after the modules
Vyacheslav Egorov (Google) 2012/09/26 12:48:57 I will add another one after modules. I like some
1771 print " Modules:"
Michael Starzinger 2012/09/19 09:54:32 Lowercase "modules:" would be consistent with the
Vyacheslav Egorov (Google) 2012/09/26 12:48:58 Done.
1772 for module in reader.module_list.modules:
1773 name = GetModuleName(reader, module)
1774 if name in KNOWN_MODULES:
1775 print " %s at %08X" % (name, module.base_of_image)
1776 reader.TryLoadSymbolsFor(name, module)
1660 1777
1661 stack_top = reader.ExceptionSP() 1778 stack_top = reader.ExceptionSP()
1662 stack_bottom = exception_thread.stack.start + \ 1779 stack_bottom = exception_thread.stack.start + \
1663 exception_thread.stack.memory.data_size 1780 exception_thread.stack.memory.data_size
1664 stack_map = {reader.ExceptionIP(): -1} 1781 stack_map = {reader.ExceptionIP(): -1}
1665 for slot in xrange(stack_top, stack_bottom, reader.PointerSize()): 1782 for slot in xrange(stack_top, stack_bottom, reader.PointerSize()):
1666 maybe_address = reader.ReadUIntPtr(slot) 1783 maybe_address = reader.ReadUIntPtr(slot)
1667 if not maybe_address in stack_map: 1784 if not maybe_address in stack_map:
1668 stack_map[maybe_address] = slot 1785 stack_map[maybe_address] = slot
1669 heap = V8Heap(reader, stack_map) 1786 heap = V8Heap(reader, stack_map)
1670 1787
1671 print "Disassembly around exception.eip:" 1788 print "Disassembly around exception.eip:"
1789 print reader.FindSymbol(reader.ExceptionIP())
Michael Starzinger 2012/09/19 09:54:32 This will print "None" when no symbol is found, ca
Vyacheslav Egorov (Google) 2012/09/26 12:48:58 Done.
1672 disasm_start = reader.ExceptionIP() - EIP_PROXIMITY 1790 disasm_start = reader.ExceptionIP() - EIP_PROXIMITY
1673 disasm_bytes = 2 * EIP_PROXIMITY 1791 disasm_bytes = 2 * EIP_PROXIMITY
1674 if (options.full): 1792 if (options.full):
1675 full_range = reader.FindRegion(reader.ExceptionIP()) 1793 full_range = reader.FindRegion(reader.ExceptionIP())
1676 if full_range is not None: 1794 if full_range is not None:
1677 disasm_start = full_range[0] 1795 disasm_start = full_range[0]
1678 disasm_bytes = full_range[1] 1796 disasm_bytes = full_range[1]
1679 1797
1680 lines = reader.GetDisasmLines(disasm_start, disasm_bytes) 1798 lines = reader.GetDisasmLines(disasm_start, disasm_bytes)
1681 1799
1682 for line in lines: 1800 for line in lines:
1683 print FormatDisasmLine(disasm_start, heap, line) 1801 print FormatDisasmLine(disasm_start, heap, line)
1684 print 1802 print
1685 1803
1686 if heap is None: 1804 if heap is None:
1687 heap = V8Heap(reader, None) 1805 heap = V8Heap(reader, None)
1688 1806
1689 if options.full: 1807 if options.full:
1690 FullDump(reader, heap) 1808 FullDump(reader, heap)
1691 1809
1692 if options.shell: 1810 if options.shell:
1693 InspectionShell(reader, heap).cmdloop("type help to get help") 1811 InspectionShell(reader, heap).cmdloop("type help to get help")
1694 else: 1812 else:
1695 if reader.exception is not None: 1813 if reader.exception is not None:
1696 print "Annotated stack (from exception.esp to bottom):" 1814 print "Annotated stack (from exception.esp to bottom):"
1697 for slot in xrange(stack_top, stack_bottom, reader.PointerSize()): 1815 for slot in xrange(stack_top, stack_bottom, reader.PointerSize()):
1698 maybe_address = reader.ReadUIntPtr(slot) 1816 maybe_address = reader.ReadUIntPtr(slot)
1699 heap_object = heap.FindObject(maybe_address) 1817 heap_object = heap.FindObject(maybe_address)
1700 print "%s: %s" % (reader.FormatIntPtr(slot), 1818 maybe_symbol = reader.FindSymbol(maybe_address)
1701 reader.FormatIntPtr(maybe_address)) 1819 if maybe_symbol is None:
1820 maybe_symbol = ""
1821
1822 print "%s: %s %s" % (reader.FormatIntPtr(slot),
1823 reader.FormatIntPtr(maybe_address),
1824 maybe_symbol)
Michael Starzinger 2012/09/19 09:54:32 Just use "maybe_symbol or ''" here and drop the if
Vyacheslav Egorov (Google) 2012/09/26 12:48:58 Done.
1702 if heap_object: 1825 if heap_object:
1703 heap_object.Print(Printer()) 1826 heap_object.Print(Printer())
1704 print 1827 print
1705 1828
1706 reader.Dispose() 1829 reader.Dispose()
1707 1830
1708 1831
1709 if __name__ == "__main__": 1832 if __name__ == "__main__":
1710 parser = optparse.OptionParser(USAGE) 1833 parser = optparse.OptionParser(USAGE)
1711 parser.add_option("-s", "--shell", dest="shell", action="store_true", 1834 parser.add_option("-s", "--shell", dest="shell", action="store_true",
1712 help="start an interactive inspector shell") 1835 help="start an interactive inspector shell")
1713 parser.add_option("-f", "--full", dest="full", action="store_true", 1836 parser.add_option("-f", "--full", dest="full", action="store_true",
1714 help="dump all information contained in the minidump") 1837 help="dump all information contained in the minidump")
1838 parser.add_option("--symdir", dest="symdir", default=".",
1839 help="directory containing *.pdb.sym file with symbols")
1715 options, args = parser.parse_args() 1840 options, args = parser.parse_args()
1716 if len(args) != 1: 1841 if len(args) != 1:
1717 parser.print_help() 1842 parser.print_help()
1718 sys.exit(1) 1843 sys.exit(1)
1719 AnalyzeMinidump(options, args[0]) 1844 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