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:
parent
4403daca1a
commit
c4bed03342
@ -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)
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user