[tools] Add support for new stack error messages and js stack traces
Change-Id: I809b10935c92a129bd633c98759ba9d800aaa91c Reviewed-on: https://chromium-review.googlesource.com/934503 Reviewed-by: Peter Marshall <petermarshall@chromium.org> Commit-Queue: Camillo Bruni <cbruni@chromium.org> Cr-Commit-Position: refs/heads/master@{#51587}
This commit is contained in:
parent
ea97a8fb32
commit
78cba2ae00
@ -185,6 +185,10 @@ MAGIC_MARKER_PAIRS = (
|
|||||||
(0xbbbbbbbb, 0xbbbbbbbb),
|
(0xbbbbbbbb, 0xbbbbbbbb),
|
||||||
(0xfefefefe, 0xfefefeff),
|
(0xfefefefe, 0xfefefeff),
|
||||||
)
|
)
|
||||||
|
# See StackTraceFailureMessage in isolate.h
|
||||||
|
STACK_TRACE_MARKER = 0xdecade30
|
||||||
|
# See FailureMessage in logging.cc
|
||||||
|
ERROR_MESSAGE_MARKER = 0xdecade10
|
||||||
|
|
||||||
# Set of structures and constants that describe the layout of minidump
|
# Set of structures and constants that describe the layout of minidump
|
||||||
# files. Based on MSDN and Google Breakpad.
|
# files. Based on MSDN and Google Breakpad.
|
||||||
@ -2105,11 +2109,9 @@ class InspectionPadawan(object):
|
|||||||
"""
|
"""
|
||||||
# Only look at the first 1k words on the stack
|
# Only look at the first 1k words on the stack
|
||||||
ptr_size = self.reader.PointerSize()
|
ptr_size = self.reader.PointerSize()
|
||||||
if start is None:
|
if start is None: start = self.reader.ExceptionSP()
|
||||||
start = self.reader.ExceptionSP()
|
|
||||||
if not self.reader.IsValidAddress(start): return start
|
if not self.reader.IsValidAddress(start): return start
|
||||||
end = start + ptr_size * 1024 * 4
|
end = start + ptr_size * 1024 * 4
|
||||||
message_start = 0
|
|
||||||
magic1 = None
|
magic1 = None
|
||||||
for slot in xrange(start, end, ptr_size):
|
for slot in xrange(start, end, ptr_size):
|
||||||
if not self.reader.IsValidAddress(slot + ptr_size): break
|
if not self.reader.IsValidAddress(slot + ptr_size): break
|
||||||
@ -2117,10 +2119,64 @@ class InspectionPadawan(object):
|
|||||||
magic2 = self.reader.ReadUIntPtr(slot + ptr_size)
|
magic2 = self.reader.ReadUIntPtr(slot + ptr_size)
|
||||||
pair = (magic1 & 0xFFFFFFFF, magic2 & 0xFFFFFFFF)
|
pair = (magic1 & 0xFFFFFFFF, magic2 & 0xFFFFFFFF)
|
||||||
if pair in MAGIC_MARKER_PAIRS:
|
if pair in MAGIC_MARKER_PAIRS:
|
||||||
message_slot = slot + ptr_size * 4
|
return self.TryExtractOldStyleStackTrace(slot, start, end,
|
||||||
message_start = self.reader.ReadUIntPtr(message_slot)
|
print_message)
|
||||||
break
|
if pair[0] == STACK_TRACE_MARKER:
|
||||||
if message_start == 0:
|
return self.TryExtractStackTrace(slot, start, end, print_message)
|
||||||
|
elif pair[0] == ERROR_MESSAGE_MARKER:
|
||||||
|
return self.TryExtractErrorMessage(slot, start, end, print_message)
|
||||||
|
# Simple fallback in case not stack trace object was found
|
||||||
|
return self.TryExtractOldStyleStackTrace(0, start, end,
|
||||||
|
print_message)
|
||||||
|
|
||||||
|
def TryExtractStackTrace(self, slot, start, end, print_message):
|
||||||
|
ptr_size = self.reader.PointerSize()
|
||||||
|
assert self.reader.ReadUIntPtr(slot) & 0xFFFFFFFF == STACK_TRACE_MARKER
|
||||||
|
end_marker = STACK_TRACE_MARKER + 1;
|
||||||
|
header_size = 10
|
||||||
|
# Look for the end marker after the fields and the message buffer.
|
||||||
|
end_search = start + (32 * 1024) + (header_size * ptr_size);
|
||||||
|
end_slot = self.FindPtr(end_marker, end_search, end_search + ptr_size * 512)
|
||||||
|
if not end_slot: return start
|
||||||
|
print "Stack Message (start=%s):" % self.heap.FormatIntPtr(slot)
|
||||||
|
slot += ptr_size
|
||||||
|
for name in ("isolate","ptr1", "ptr2", "ptr3", "ptr4", "codeObject1",
|
||||||
|
"codeObject2", "codeObject3", "codeObject4"):
|
||||||
|
value = self.reader.ReadUIntPtr(slot)
|
||||||
|
print " %s: %s" % (name.rjust(14), self.heap.FormatIntPtr(value))
|
||||||
|
slot += ptr_size
|
||||||
|
print " message start: %s" % self.heap.FormatIntPtr(slot)
|
||||||
|
stack_start = end_slot + ptr_size
|
||||||
|
print " stack_start: %s" % self.heap.FormatIntPtr(stack_start)
|
||||||
|
(message_start, message) = self.FindFirstAsciiString(slot)
|
||||||
|
self.FormatStackTrace(message, print_message)
|
||||||
|
return stack_start
|
||||||
|
|
||||||
|
def FindPtr(self, expected_value, start, end):
|
||||||
|
ptr_size = self.reader.PointerSize()
|
||||||
|
for slot in xrange(start, end, ptr_size):
|
||||||
|
if not self.reader.IsValidAddress(slot): return None
|
||||||
|
value = self.reader.ReadUIntPtr(slot)
|
||||||
|
if value == expected_value: return slot
|
||||||
|
return None
|
||||||
|
|
||||||
|
def TryExtractErrorMessage(self, slot, start, end, print_message):
|
||||||
|
end_marker = ERROR_MESSAGE_MARKER + 1;
|
||||||
|
header_size = 1
|
||||||
|
end_search = start + 1024 + (header_size * ptr_size);
|
||||||
|
end_slot = self.FindPtr(end_marker, end_search, end_search + ptr_size * 512)
|
||||||
|
if not end_slot: return start
|
||||||
|
print "Error Message (start=%s):" % self.heap.FormatIntPtr(slot)
|
||||||
|
slot += ptr_size
|
||||||
|
(message_start, message) = self.FindFirstAsciiString(slot)
|
||||||
|
self.FormatStackTrace(message, print_message)
|
||||||
|
stack_start = end_slot + ptr_size
|
||||||
|
return stack_start
|
||||||
|
|
||||||
|
def TryExtractOldStyleStackTrace(self, message_slot, start, end,
|
||||||
|
print_message):
|
||||||
|
ptr_size = self.reader.PointerSize()
|
||||||
|
if message_slot == 0:
|
||||||
"""
|
"""
|
||||||
On Mac we don't always get proper magic markers, so just try printing
|
On Mac we don't always get proper magic markers, so just try printing
|
||||||
the first long ascii string found on the stack.
|
the first long ascii string found on the stack.
|
||||||
@ -2130,6 +2186,7 @@ class InspectionPadawan(object):
|
|||||||
message_start, message = self.FindFirstAsciiString(start, end, 128)
|
message_start, message = self.FindFirstAsciiString(start, end, 128)
|
||||||
if message_start is None: return start
|
if message_start is None: return start
|
||||||
else:
|
else:
|
||||||
|
message_start = self.reader.ReadUIntPtr(message_slot + ptr_size * 4)
|
||||||
message = self.reader.ReadAsciiString(message_start)
|
message = self.reader.ReadAsciiString(message_start)
|
||||||
stack_start = message_start + len(message) + 1
|
stack_start = message_start + len(message) + 1
|
||||||
# Make sure the address is word aligned
|
# Make sure the address is word aligned
|
||||||
@ -2149,10 +2206,15 @@ class InspectionPadawan(object):
|
|||||||
print " message start: %s" % self.heap.FormatIntPtr(message_start)
|
print " message start: %s" % self.heap.FormatIntPtr(message_start)
|
||||||
print " stack_start: %s" % self.heap.FormatIntPtr(stack_start )
|
print " stack_start: %s" % self.heap.FormatIntPtr(stack_start )
|
||||||
print ""
|
print ""
|
||||||
|
self.FormatStackTrace(message, print_message)
|
||||||
|
return stack_start
|
||||||
|
|
||||||
|
def FormatStackTrace(self, message, print_message):
|
||||||
if not print_message:
|
if not print_message:
|
||||||
print " Use `dsa` to print the message with annotated addresses."
|
print " Use `dsa` to print the message with annotated addresses."
|
||||||
print ""
|
print ""
|
||||||
return stack_start
|
return
|
||||||
|
ptr_size = self.reader.PointerSize()
|
||||||
# Annotate all addresses in the dumped message
|
# Annotate all addresses in the dumped message
|
||||||
prog = re.compile("[0-9a-fA-F]{%s}" % ptr_size*2)
|
prog = re.compile("[0-9a-fA-F]{%s}" % ptr_size*2)
|
||||||
addresses = list(set(prog.findall(message)))
|
addresses = list(set(prog.findall(message)))
|
||||||
@ -2166,7 +2228,7 @@ class InspectionPadawan(object):
|
|||||||
print message
|
print message
|
||||||
print "="*80
|
print "="*80
|
||||||
print ""
|
print ""
|
||||||
return stack_start
|
|
||||||
|
|
||||||
def TryInferFramePointer(self, slot, address):
|
def TryInferFramePointer(self, slot, address):
|
||||||
""" Assume we have a framepointer if we find 4 consecutive links """
|
""" Assume we have a framepointer if we find 4 consecutive links """
|
||||||
|
Loading…
Reference in New Issue
Block a user