Add ARM support to tools/grokdump.py

R=svenpanne@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13319 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
ulan@chromium.org 2013-01-07 09:48:04 +00:00
parent 4403daca1a
commit c4bed03342
2 changed files with 93 additions and 11 deletions

View File

@ -53,12 +53,12 @@ _ARCH_MAP = {
} }
def GetDisasmLines(filename, offset, size, arch, inplace): def GetDisasmLines(filename, offset, size, arch, inplace, arch_flags=""):
tmp_name = None tmp_name = None
if not inplace: if not inplace:
# Create a temporary file containing a copy of the code. # Create a temporary file containing a copy of the code.
assert arch in _ARCH_MAP, "Unsupported architecture '%s'" % arch assert arch in _ARCH_MAP, "Unsupported architecture '%s'" % arch
arch_flags = _ARCH_MAP[arch] arch_flags = arch_flags + " " + _ARCH_MAP[arch]
tmp_name = tempfile.mktemp(".v8code") tmp_name = tempfile.mktemp(".v8code")
command = "dd if=%s of=%s bs=1 count=%d skip=%d && " \ command = "dd if=%s of=%s bs=1 count=%d skip=%d && " \
"%s %s -D -b binary %s %s" % ( "%s %s -D -b binary %s %s" % (
@ -66,8 +66,8 @@ def GetDisasmLines(filename, offset, size, arch, inplace):
OBJDUMP_BIN, ' '.join(_COMMON_DISASM_OPTIONS), arch_flags, OBJDUMP_BIN, ' '.join(_COMMON_DISASM_OPTIONS), arch_flags,
tmp_name) tmp_name)
else: else:
command = "%s %s --start-address=%d --stop-address=%d -d %s " % ( command = "%s %s %s --start-address=%d --stop-address=%d -d %s " % (
OBJDUMP_BIN, ' '.join(_COMMON_DISASM_OPTIONS), OBJDUMP_BIN, ' '.join(_COMMON_DISASM_OPTIONS), arch_flags,
offset, offset,
offset + size, offset + size,
filename) filename)

View File

@ -296,6 +296,42 @@ MINIDUMP_CONTEXT_X86 = Descriptor([
MD_CONTEXT_X86_EXTENDED_REGISTERS)) MD_CONTEXT_X86_EXTENDED_REGISTERS))
]) ])
MD_CONTEXT_ARM = 0x40000000
MD_CONTEXT_ARM_INTEGER = (MD_CONTEXT_ARM | 0x00000002)
MD_CONTEXT_ARM_FLOATING_POINT = (MD_CONTEXT_ARM | 0x00000004)
MD_FLOATINGSAVEAREA_ARM_FPR_COUNT = 32
MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT = 8
MINIDUMP_FLOATING_SAVE_AREA_ARM = Descriptor([
("fpscr", ctypes.c_uint64),
("regs", ctypes.c_uint64 * MD_FLOATINGSAVEAREA_ARM_FPR_COUNT),
("extra", ctypes.c_uint64 * MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT)
])
MINIDUMP_CONTEXT_ARM = Descriptor([
("context_flags", ctypes.c_uint32),
# MD_CONTEXT_ARM_INTEGER.
("r0", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
("r1", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
("r2", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
("r3", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
("r4", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
("r5", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
("r6", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
("r7", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
("r8", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
("r9", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
("r10", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
("r11", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
("r12", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
("sp", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
("lr", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
("pc", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
("cpsr", ctypes.c_uint32),
("float_save", EnableOnFlag(MINIDUMP_FLOATING_SAVE_AREA_ARM.ctype,
MD_CONTEXT_ARM_FLOATING_POINT))
])
MD_CONTEXT_AMD64 = 0x00100000 MD_CONTEXT_AMD64 = 0x00100000
MD_CONTEXT_AMD64_CONTROL = (MD_CONTEXT_AMD64 | 0x00000001) MD_CONTEXT_AMD64_CONTROL = (MD_CONTEXT_AMD64 | 0x00000001)
MD_CONTEXT_AMD64_INTEGER = (MD_CONTEXT_AMD64 | 0x00000002) MD_CONTEXT_AMD64_INTEGER = (MD_CONTEXT_AMD64 | 0x00000002)
@ -429,6 +465,7 @@ MINIDUMP_RAW_SYSTEM_INFO = Descriptor([
]) ])
MD_CPU_ARCHITECTURE_X86 = 0 MD_CPU_ARCHITECTURE_X86 = 0
MD_CPU_ARCHITECTURE_ARM = 5
MD_CPU_ARCHITECTURE_AMD64 = 9 MD_CPU_ARCHITECTURE_AMD64 = 9
class FuncSymbol: class FuncSymbol:
@ -481,7 +518,9 @@ class MinidumpReader(object):
system_info = MINIDUMP_RAW_SYSTEM_INFO.Read( system_info = MINIDUMP_RAW_SYSTEM_INFO.Read(
self.minidump, d.location.rva) self.minidump, d.location.rva)
self.arch = system_info.processor_architecture self.arch = system_info.processor_architecture
assert self.arch in [MD_CPU_ARCHITECTURE_AMD64, MD_CPU_ARCHITECTURE_X86] assert self.arch in [MD_CPU_ARCHITECTURE_AMD64,
MD_CPU_ARCHITECTURE_ARM,
MD_CPU_ARCHITECTURE_X86]
assert not self.arch is None assert not self.arch is None
for d in directories: for d in directories:
@ -496,6 +535,9 @@ class MinidumpReader(object):
elif self.arch == MD_CPU_ARCHITECTURE_AMD64: elif self.arch == MD_CPU_ARCHITECTURE_AMD64:
self.exception_context = MINIDUMP_CONTEXT_AMD64.Read( self.exception_context = MINIDUMP_CONTEXT_AMD64.Read(
self.minidump, self.exception.thread_context.rva) self.minidump, self.exception.thread_context.rva)
elif self.arch == MD_CPU_ARCHITECTURE_ARM:
self.exception_context = MINIDUMP_CONTEXT_ARM.Read(
self.minidump, self.exception.thread_context.rva)
DebugPrint(self.exception_context) DebugPrint(self.exception_context)
elif d.stream_type == MD_THREAD_LIST_STREAM: elif d.stream_type == MD_THREAD_LIST_STREAM:
thread_list = MINIDUMP_THREAD_LIST.Read(self.minidump, d.location.rva) thread_list = MINIDUMP_THREAD_LIST.Read(self.minidump, d.location.rva)
@ -541,6 +583,8 @@ class MinidumpReader(object):
def ReadUIntPtr(self, address): def ReadUIntPtr(self, address):
if self.arch == MD_CPU_ARCHITECTURE_AMD64: if self.arch == MD_CPU_ARCHITECTURE_AMD64:
return self.ReadU64(address) return self.ReadU64(address)
elif self.arch == MD_CPU_ARCHITECTURE_ARM:
return self.ReadU32(address)
elif self.arch == MD_CPU_ARCHITECTURE_X86: elif self.arch == MD_CPU_ARCHITECTURE_X86:
return self.ReadU32(address) return self.ReadU32(address)
@ -551,6 +595,8 @@ class MinidumpReader(object):
def _ReadWord(self, location): def _ReadWord(self, location):
if self.arch == MD_CPU_ARCHITECTURE_AMD64: if self.arch == MD_CPU_ARCHITECTURE_AMD64:
return ctypes.c_uint64.from_buffer(self.minidump, location).value return ctypes.c_uint64.from_buffer(self.minidump, location).value
elif self.arch == MD_CPU_ARCHITECTURE_ARM:
return ctypes.c_uint32.from_buffer(self.minidump, location).value
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
@ -647,18 +693,29 @@ class MinidumpReader(object):
return None return None
def GetDisasmLines(self, address, size): def GetDisasmLines(self, address, size):
def CountUndefinedInstructions(lines):
pattern = "<UNDEFINED>"
return sum([line.count(pattern) for (ignore, line) in lines])
location = self.FindLocation(address) location = self.FindLocation(address)
if location is None: return [] if location is None: return []
arch = None arch = None
possible_objdump_flags = [""]
if self.arch == MD_CPU_ARCHITECTURE_X86: if self.arch == MD_CPU_ARCHITECTURE_X86:
arch = "ia32" arch = "ia32"
elif self.arch == MD_CPU_ARCHITECTURE_ARM:
arch = "arm"
possible_objdump_flags = ["", "--disassembler-options=force-thumb"]
elif self.arch == MD_CPU_ARCHITECTURE_AMD64: elif self.arch == MD_CPU_ARCHITECTURE_AMD64:
arch = "x64" arch = "x64"
return disasm.GetDisasmLines(self.minidump_name, results = [ disasm.GetDisasmLines(self.minidump_name,
location, location,
size, size,
arch, arch,
False) False,
objdump_flags)
for objdump_flags in possible_objdump_flags ]
return min(results, key=CountUndefinedInstructions)
def Dispose(self): def Dispose(self):
@ -668,24 +725,32 @@ class MinidumpReader(object):
def ExceptionIP(self): def ExceptionIP(self):
if self.arch == MD_CPU_ARCHITECTURE_AMD64: if self.arch == MD_CPU_ARCHITECTURE_AMD64:
return self.exception_context.rip return self.exception_context.rip
elif self.arch == MD_CPU_ARCHITECTURE_ARM:
return self.exception_context.pc
elif self.arch == MD_CPU_ARCHITECTURE_X86: elif self.arch == MD_CPU_ARCHITECTURE_X86:
return self.exception_context.eip return self.exception_context.eip
def ExceptionSP(self): def ExceptionSP(self):
if self.arch == MD_CPU_ARCHITECTURE_AMD64: if self.arch == MD_CPU_ARCHITECTURE_AMD64:
return self.exception_context.rsp return self.exception_context.rsp
elif self.arch == MD_CPU_ARCHITECTURE_ARM:
return self.exception_context.sp
elif self.arch == MD_CPU_ARCHITECTURE_X86: elif self.arch == MD_CPU_ARCHITECTURE_X86:
return self.exception_context.esp return self.exception_context.esp
def FormatIntPtr(self, value): def FormatIntPtr(self, value):
if self.arch == MD_CPU_ARCHITECTURE_AMD64: if self.arch == MD_CPU_ARCHITECTURE_AMD64:
return "%016x" % value return "%016x" % value
elif self.arch == MD_CPU_ARCHITECTURE_ARM:
return "%08x" % value
elif self.arch == MD_CPU_ARCHITECTURE_X86: elif self.arch == MD_CPU_ARCHITECTURE_X86:
return "%08x" % value return "%08x" % value
def PointerSize(self): def PointerSize(self):
if self.arch == MD_CPU_ARCHITECTURE_AMD64: if self.arch == MD_CPU_ARCHITECTURE_AMD64:
return 8 return 8
elif self.arch == MD_CPU_ARCHITECTURE_ARM:
return 4
elif self.arch == MD_CPU_ARCHITECTURE_X86: elif self.arch == MD_CPU_ARCHITECTURE_X86:
return 4 return 4
@ -1462,6 +1527,8 @@ class V8Heap(object):
def MapAlignmentMask(self): def MapAlignmentMask(self):
if self.reader.arch == MD_CPU_ARCHITECTURE_AMD64: if self.reader.arch == MD_CPU_ARCHITECTURE_AMD64:
return (1 << 4) - 1 return (1 << 4) - 1
elif self.reader.arch == MD_CPU_ARCHITECTURE_ARM:
return (1 << 4) - 1
elif self.reader.arch == MD_CPU_ARCHITECTURE_X86: elif self.reader.arch == MD_CPU_ARCHITECTURE_X86:
return (1 << 5) - 1 return (1 << 5) - 1
@ -1746,6 +1813,9 @@ CONTEXT_FOR_ARCH = {
MD_CPU_ARCHITECTURE_AMD64: MD_CPU_ARCHITECTURE_AMD64:
['rax', 'rbx', 'rcx', 'rdx', 'rdi', 'rsi', 'rbp', 'rsp', 'rip', ['rax', 'rbx', 'rcx', 'rdx', 'rdi', 'rsi', 'rbp', 'rsp', 'rip',
'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15'], 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15'],
MD_CPU_ARCHITECTURE_ARM:
['r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9',
'r10', 'r11', 'r12', 'sp', 'lr', 'pc'],
MD_CPU_ARCHITECTURE_X86: MD_CPU_ARCHITECTURE_X86:
['eax', 'ebx', 'ecx', 'edx', 'edi', 'esi', 'ebp', 'esp', 'eip'] ['eax', 'ebx', 'ecx', 'edx', 'edi', 'esi', 'ebp', 'esp', 'eip']
} }
@ -1771,7 +1841,11 @@ def AnalyzeMinidump(options, minidump_name):
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:] if reader.arch == MD_CPU_ARCHITECTURE_ARM:
print " cpsr: %s" % bin(reader.exception_context.cpsr)[2:]
else:
print " eflags: %s" % bin(reader.exception_context.eflags)[2:]
print print
print " modules:" print " modules:"
for module in reader.module_list.modules: for module in reader.module_list.modules:
@ -1842,7 +1916,15 @@ if __name__ == "__main__":
help="dump all information contained in the minidump") help="dump all information contained in the minidump")
parser.add_option("--symdir", dest="symdir", default=".", parser.add_option("--symdir", dest="symdir", default=".",
help="directory containing *.pdb.sym file with symbols") help="directory containing *.pdb.sym file with symbols")
parser.add_option("--objdump",
default="/usr/bin/objdump",
help="objdump tool to use [default: %default]")
options, args = parser.parse_args() options, args = parser.parse_args()
if os.path.exists(options.objdump):
disasm.OBJDUMP_BIN = options.objdump
OBJDUMP_BIN = options.objdump
else:
print "Cannot find %s, falling back to default objdump" % options.objdump
if len(args) != 1: if len(args) != 1:
parser.print_help() parser.print_help()
sys.exit(1) sys.exit(1)