[tools] Add basic pointer compression to grokdump
Distinguish between tagged and machine pointer sizes in grokdump, and dump a tagged memory view in addition to the machine-word dump when they don't match. This tagged view tries to decompress pointers for link targets, by masking the slot they're in to get the cage root. Drive-by: Add a .style.yapf to opt in to python formatting using git cl format. Change-Id: Ic5272cd865f995fc670ab2fb7d5e464f317af1bf Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3439906 Reviewed-by: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Auto-Submit: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Commit-Queue: Toon Verwaest <verwaest@chromium.org> Cr-Commit-Position: refs/heads/main@{#78948}
This commit is contained in:
parent
6bb35b8c83
commit
c97337ff5e
2
.style.yapf
Normal file
2
.style.yapf
Normal file
@ -0,0 +1,2 @@
|
||||
[style]
|
||||
based_on_style = chromium
|
@ -168,7 +168,7 @@ def FullDump(reader, heap):
|
||||
print("%s - %s" % (reader.FormatIntPtr(start),
|
||||
reader.FormatIntPtr(start + size)))
|
||||
print(start + size + 1);
|
||||
for i in range(0, size, reader.PointerSize()):
|
||||
for i in range(0, size, reader.MachinePointerSize()):
|
||||
slot = start + i
|
||||
maybe_address = reader.ReadUIntPtr(slot)
|
||||
heap_object = heap.FindObject(maybe_address)
|
||||
@ -710,7 +710,7 @@ class MinidumpReader(object):
|
||||
|
||||
def _FindObjdump(self, options):
|
||||
if options.objdump:
|
||||
objdump_bin = options.objdump
|
||||
objdump_bin = options.objdump
|
||||
else:
|
||||
objdump_bin = self._FindThirdPartyObjdump()
|
||||
if not objdump_bin or not os.path.exists(objdump_bin):
|
||||
@ -722,29 +722,29 @@ class MinidumpReader(object):
|
||||
disasm.OBJDUMP_BIN = objdump_bin
|
||||
|
||||
def _FindThirdPartyObjdump(self):
|
||||
# Try to find the platform specific objdump
|
||||
third_party_dir = os.path.join(
|
||||
os.path.dirname(os.path.dirname(__file__)), 'third_party')
|
||||
objdumps = []
|
||||
for root, dirs, files in os.walk(third_party_dir):
|
||||
for file in files:
|
||||
if file.endswith("objdump"):
|
||||
objdumps.append(os.path.join(root, file))
|
||||
if self.arch == MD_CPU_ARCHITECTURE_ARM:
|
||||
platform_filter = 'arm-linux'
|
||||
elif self.arch == MD_CPU_ARCHITECTURE_ARM64:
|
||||
platform_filter = 'aarch64'
|
||||
else:
|
||||
# use default otherwise
|
||||
return None
|
||||
print(("# Looking for platform specific (%s) objdump in "
|
||||
"third_party directory.") % platform_filter)
|
||||
objdumps = filter(lambda file: platform_filter in file >= 0, objdumps)
|
||||
if len(objdumps) == 0:
|
||||
print("# Could not find platform specific objdump in third_party.")
|
||||
print("# Make sure you installed the correct SDK.")
|
||||
return None
|
||||
return objdumps[0]
|
||||
# Try to find the platform specific objdump
|
||||
third_party_dir = os.path.join(
|
||||
os.path.dirname(os.path.dirname(__file__)), 'third_party')
|
||||
objdumps = []
|
||||
for root, dirs, files in os.walk(third_party_dir):
|
||||
for file in files:
|
||||
if file.endswith("objdump"):
|
||||
objdumps.append(os.path.join(root, file))
|
||||
if self.arch == MD_CPU_ARCHITECTURE_ARM:
|
||||
platform_filter = 'arm-linux'
|
||||
elif self.arch == MD_CPU_ARCHITECTURE_ARM64:
|
||||
platform_filter = 'aarch64'
|
||||
else:
|
||||
# use default otherwise
|
||||
return None
|
||||
print(("# Looking for platform specific (%s) objdump in "
|
||||
"third_party directory.") % platform_filter)
|
||||
objdumps = filter(lambda file: platform_filter in file >= 0, objdumps)
|
||||
if len(objdumps) == 0:
|
||||
print("# Could not find platform specific objdump in third_party.")
|
||||
print("# Make sure you installed the correct SDK.")
|
||||
return None
|
||||
return objdumps[0]
|
||||
|
||||
def ContextDescriptor(self):
|
||||
if self.arch == MD_CPU_ARCHITECTURE_X86:
|
||||
@ -765,7 +765,7 @@ class MinidumpReader(object):
|
||||
return self.FindLocation(address) is not None
|
||||
|
||||
def IsAlignedAddress(self, address):
|
||||
return (address % self.PointerSize()) == 0
|
||||
return (address % self.MachinePointerSize()) == 0
|
||||
|
||||
def IsExceptionStackAddress(self, address):
|
||||
if not self.IsAlignedAddress(address): return False
|
||||
@ -804,11 +804,29 @@ class MinidumpReader(object):
|
||||
return (self.arch == MD_CPU_ARCHITECTURE_ARM64 or
|
||||
self.arch == MD_CPU_ARCHITECTURE_AMD64)
|
||||
|
||||
def IsPointerCompressed(self):
|
||||
# Assume all 64-bit builds are pointer compressed.
|
||||
return self.Is64()
|
||||
|
||||
def Is32BitTagged(self):
|
||||
return not self.Is64() or self.IsPointerCompressed()
|
||||
|
||||
def ReadTagged(self, address):
|
||||
if self.Is32BitTagged():
|
||||
return self.ReadU32(address)
|
||||
return self.ReadU64(address)
|
||||
|
||||
def ReadUIntPtr(self, address):
|
||||
if self.Is64():
|
||||
return self.ReadU64(address)
|
||||
return self.ReadU32(address)
|
||||
|
||||
def ReadSized(self, address, size):
|
||||
if size == 8:
|
||||
return self.ReadU64(address)
|
||||
assert (size == 4)
|
||||
return self.ReadU32(address)
|
||||
|
||||
def ReadBytes(self, address, size):
|
||||
location = self.FindLocation(address)
|
||||
return self.minidump[location:location + size]
|
||||
@ -819,8 +837,10 @@ class MinidumpReader(object):
|
||||
return ctypes.c_uint32.from_buffer(self.minidump, location).value
|
||||
|
||||
def ReadAsciiPtr(self, address):
|
||||
ascii_content = [c if c >= '\x20' and c < '\x7f' else '.'
|
||||
for c in self.ReadBytes(address, self.PointerSize())]
|
||||
ascii_content = [
|
||||
c if c >= '\x20' and c < '\x7f' else '.'
|
||||
for c in self.ReadBytes(address, self.MachinePointerSize())
|
||||
]
|
||||
return ''.join(ascii_content)
|
||||
|
||||
def ReadAsciiString(self, address):
|
||||
@ -908,7 +928,7 @@ class MinidumpReader(object):
|
||||
def FindWord(self, word, alignment=0):
|
||||
def search_inside_region(reader, start, size, location):
|
||||
location = (location + alignment) & ~alignment
|
||||
for i in range(size - self.PointerSize()):
|
||||
for i in range(size - self.MachinePointerSize()):
|
||||
loc = location + i
|
||||
if reader._ReadWord(loc) == word:
|
||||
slot = start + (loc - location)
|
||||
@ -920,7 +940,7 @@ class MinidumpReader(object):
|
||||
aligned_res = []
|
||||
unaligned_res = []
|
||||
def search_inside_region(reader, start, size, location):
|
||||
for i in range(size - self.PointerSize()):
|
||||
for i in range(size - self.MachinePointerSize()):
|
||||
loc = location + i
|
||||
if reader._ReadWord(loc) == word:
|
||||
slot = start + (loc - location)
|
||||
@ -1023,11 +1043,21 @@ class MinidumpReader(object):
|
||||
return "%016x" % value
|
||||
return "%08x" % value
|
||||
|
||||
def PointerSize(self):
|
||||
def FormatTagged(self, value):
|
||||
if self.Is64() and not self.IsPointerCompressed():
|
||||
return "%016x" % value
|
||||
return "%08x" % value
|
||||
|
||||
def MachinePointerSize(self):
|
||||
if self.Is64():
|
||||
return 8
|
||||
return 4
|
||||
|
||||
def TaggedPointerSize(self):
|
||||
if self.IsPointerCompressed():
|
||||
return 4
|
||||
return self.MachinePointerSize()
|
||||
|
||||
def Register(self, name):
|
||||
return self.exception_context.__getattribute__(name)
|
||||
|
||||
@ -1173,11 +1203,11 @@ class HeapObject(object):
|
||||
instance_type)
|
||||
|
||||
def ObjectField(self, offset):
|
||||
field_value = self.heap.reader.ReadUIntPtr(self.address + offset)
|
||||
field_value = self.heap.reader.ReadTagged(self.address + offset)
|
||||
return self.heap.FindObjectOrSmi(field_value)
|
||||
|
||||
def SmiField(self, offset):
|
||||
field_value = self.heap.reader.ReadUIntPtr(self.address + offset)
|
||||
field_value = self.heap.reader.ReadTagged(self.address + offset)
|
||||
if self.heap.IsSmi(field_value):
|
||||
return self.heap.SmiUntag(field_value)
|
||||
return None
|
||||
@ -1189,7 +1219,7 @@ class Map(HeapObject):
|
||||
|
||||
# Instance Sizes
|
||||
def InstanceSizesOffset(self):
|
||||
return self.heap.PointerSize()
|
||||
return self.heap.TaggedPointerSize()
|
||||
|
||||
def InstanceSizeOffset(self):
|
||||
return self.InstanceSizesOffset()
|
||||
@ -1224,28 +1254,29 @@ class Map(HeapObject):
|
||||
return self.InstanceAttributesOffset() + self.heap.IntSize()
|
||||
|
||||
def PrototypeOffset(self):
|
||||
return self.BitField3Offset() + self.heap.PointerSize()
|
||||
return self.BitField3Offset() + self.heap.TaggedPointerSize()
|
||||
|
||||
def ConstructorOrBackPointerOffset(self):
|
||||
return self.PrototypeOffset() + self.heap.PointerSize()
|
||||
return self.PrototypeOffset() + self.heap.TaggedPointerSize()
|
||||
|
||||
def TransitionsOrPrototypeInfoOffset(self):
|
||||
return self.ConstructorOrBackPointerOffset() + self.heap.PointerSize()
|
||||
return self.ConstructorOrBackPointerOffset() + self.heap.TaggedPointerSize()
|
||||
|
||||
def DescriptorsOffset(self):
|
||||
return self.TransitionsOrPrototypeInfoOffset() + self.heap.PointerSize()
|
||||
return (self.TransitionsOrPrototypeInfoOffset() +
|
||||
self.heap.TaggedPointerSize())
|
||||
|
||||
def CodeCacheOffset(self):
|
||||
return self.DescriptorsOffset() + self.heap.PointerSize()
|
||||
return self.DescriptorsOffset() + self.heap.TaggedPointerSize()
|
||||
|
||||
def DependentCodeOffset(self):
|
||||
return self.CodeCacheOffset() + self.heap.PointerSize()
|
||||
return self.CodeCacheOffset() + self.heap.TaggedPointerSize()
|
||||
|
||||
def ReadByte(self, offset):
|
||||
return self.heap.reader.ReadU8(self.address + offset)
|
||||
|
||||
def ReadWord(self, offset):
|
||||
return self.heap.reader.ReadUIntPtr(self.address + offset)
|
||||
def ReadSlot(self, offset):
|
||||
return self.heap.reader.ReadTagged(self.address + offset)
|
||||
|
||||
def Print(self, p):
|
||||
p.Print("Map(%08x)" % (self.address))
|
||||
@ -1264,7 +1295,7 @@ class Map(HeapObject):
|
||||
|
||||
p.Print(" - kind: %s" % (self.Decode(3, 5, bitfield2)))
|
||||
|
||||
bitfield3 = self.ReadWord(self.BitField3Offset())
|
||||
bitfield3 = self.ReadSlot(self.BitField3Offset())
|
||||
|
||||
p.Print(
|
||||
" - EnumLength: %d NumberOfOwnDescriptors: %d OwnsDescriptors: %s" % (
|
||||
@ -1299,7 +1330,7 @@ class Map(HeapObject):
|
||||
class String(HeapObject):
|
||||
def LengthOffset(self):
|
||||
# First word after the map is the hash, the second is the length.
|
||||
return self.heap.PointerSize() * 2
|
||||
return self.heap.TaggedPointerSize() * 2
|
||||
|
||||
def __init__(self, heap, map, address):
|
||||
HeapObject.__init__(self, heap, map, address)
|
||||
@ -1317,7 +1348,7 @@ class String(HeapObject):
|
||||
|
||||
class SeqString(String):
|
||||
def CharsOffset(self):
|
||||
return self.heap.PointerSize() * 3
|
||||
return self.heap.TaggedPointerSize() * 3
|
||||
|
||||
def __init__(self, heap, map, address):
|
||||
String.__init__(self, heap, map, address)
|
||||
@ -1360,10 +1391,10 @@ class ExternalString(String):
|
||||
|
||||
class ConsString(String):
|
||||
def LeftOffset(self):
|
||||
return self.heap.PointerSize() * 3
|
||||
return self.heap.TaggedPointerSize() * 3
|
||||
|
||||
def RightOffset(self):
|
||||
return self.heap.PointerSize() * 4
|
||||
return self.heap.TaggedPointerSize() * 4
|
||||
|
||||
def __init__(self, heap, map, address):
|
||||
String.__init__(self, heap, map, address)
|
||||
@ -1390,13 +1421,13 @@ class Oddball(HeapObject):
|
||||
]
|
||||
|
||||
def ToStringOffset(self):
|
||||
return self.heap.PointerSize()
|
||||
return self.heap.TaggedPointerSize()
|
||||
|
||||
def ToNumberOffset(self):
|
||||
return self.ToStringOffset() + self.heap.PointerSize()
|
||||
return self.ToStringOffset() + self.heap.TaggedPointerSize()
|
||||
|
||||
def KindOffset(self):
|
||||
return self.ToNumberOffset() + self.heap.PointerSize()
|
||||
return self.ToNumberOffset() + self.heap.TaggedPointerSize()
|
||||
|
||||
def __init__(self, heap, map, address):
|
||||
HeapObject.__init__(self, heap, map, address)
|
||||
@ -1418,13 +1449,13 @@ class Oddball(HeapObject):
|
||||
|
||||
class FixedArray(HeapObject):
|
||||
def LengthOffset(self):
|
||||
return self.heap.PointerSize()
|
||||
return self.heap.TaggedPointerSize()
|
||||
|
||||
def ElementsOffset(self):
|
||||
return self.heap.PointerSize() * 2
|
||||
return self.heap.TaggedPointerSize() * 2
|
||||
|
||||
def MemberOffset(self, i):
|
||||
return self.ElementsOffset() + self.heap.PointerSize() * i
|
||||
return self.ElementsOffset() + self.heap.TaggedPointerSize() * i
|
||||
|
||||
def Get(self, i):
|
||||
return self.ObjectField(self.MemberOffset(i))
|
||||
@ -1561,10 +1592,10 @@ class TransitionArray(object):
|
||||
|
||||
class JSFunction(HeapObject):
|
||||
def CodeEntryOffset(self):
|
||||
return 3 * self.heap.PointerSize()
|
||||
return 3 * self.heap.TaggedPointerSize()
|
||||
|
||||
def SharedOffset(self):
|
||||
return 5 * self.heap.PointerSize()
|
||||
return 5 * self.heap.TaggedPointerSize()
|
||||
|
||||
def __init__(self, heap, map, address):
|
||||
HeapObject.__init__(self, heap, map, address)
|
||||
@ -1611,19 +1642,19 @@ class JSFunction(HeapObject):
|
||||
|
||||
class SharedFunctionInfo(HeapObject):
|
||||
def CodeOffset(self):
|
||||
return 2 * self.heap.PointerSize()
|
||||
return 2 * self.heap.TaggedPointerSize()
|
||||
|
||||
def ScriptOffset(self):
|
||||
return 7 * self.heap.PointerSize()
|
||||
return 7 * self.heap.TaggedPointerSize()
|
||||
|
||||
def InferredNameOffset(self):
|
||||
return 9 * self.heap.PointerSize()
|
||||
return 9 * self.heap.TaggedPointerSize()
|
||||
|
||||
def EndPositionOffset(self):
|
||||
return 12 * self.heap.PointerSize() + 4 * self.heap.IntSize()
|
||||
return 12 * self.heap.TaggedPointerSize() + 4 * self.heap.IntSize()
|
||||
|
||||
def StartPositionAndTypeOffset(self):
|
||||
return 12 * self.heap.PointerSize() + 5 * self.heap.IntSize()
|
||||
return 12 * self.heap.TaggedPointerSize() + 5 * self.heap.IntSize()
|
||||
|
||||
def __init__(self, heap, map, address):
|
||||
HeapObject.__init__(self, heap, map, address)
|
||||
@ -1631,7 +1662,7 @@ class SharedFunctionInfo(HeapObject):
|
||||
self.code = self.ObjectField(self.CodeOffset())
|
||||
self.script = self.ObjectField(self.ScriptOffset())
|
||||
self.inferred_name = self.ObjectField(self.InferredNameOffset())
|
||||
if heap.PointerSize() == 8:
|
||||
if heap.TaggedPointerSize() == 8:
|
||||
start_position_and_type = \
|
||||
heap.reader.ReadU32(self.StartPositionAndTypeOffset())
|
||||
self.start_position = start_position_and_type >> 2
|
||||
@ -1653,10 +1684,10 @@ class SharedFunctionInfo(HeapObject):
|
||||
|
||||
class Script(HeapObject):
|
||||
def SourceOffset(self):
|
||||
return self.heap.PointerSize()
|
||||
return self.heap.TaggedPointerSize()
|
||||
|
||||
def NameOffset(self):
|
||||
return self.SourceOffset() + self.heap.PointerSize()
|
||||
return self.SourceOffset() + self.heap.TaggedPointerSize()
|
||||
|
||||
def __init__(self, heap, map, address):
|
||||
HeapObject.__init__(self, heap, map, address)
|
||||
@ -1666,10 +1697,10 @@ class Script(HeapObject):
|
||||
|
||||
class CodeCache(HeapObject):
|
||||
def DefaultCacheOffset(self):
|
||||
return self.heap.PointerSize()
|
||||
return self.heap.TaggedPointerSize()
|
||||
|
||||
def NormalTypeCacheOffset(self):
|
||||
return self.DefaultCacheOffset() + self.heap.PointerSize()
|
||||
return self.DefaultCacheOffset() + self.heap.TaggedPointerSize()
|
||||
|
||||
def __init__(self, heap, map, address):
|
||||
HeapObject.__init__(self, heap, map, address)
|
||||
@ -1689,12 +1720,12 @@ class Code(HeapObject):
|
||||
CODE_ALIGNMENT_MASK = (1 << 5) - 1
|
||||
|
||||
def InstructionSizeOffset(self):
|
||||
return self.heap.PointerSize()
|
||||
return self.heap.TaggedPointerSize()
|
||||
|
||||
@staticmethod
|
||||
def HeaderSize(heap):
|
||||
return (heap.PointerSize() + heap.IntSize() + \
|
||||
4 * heap.PointerSize() + 3 * heap.IntSize() + \
|
||||
return (heap.TaggedPointerSize() + heap.IntSize() + \
|
||||
4 * heap.TaggedPointerSize() + 3 * heap.IntSize() + \
|
||||
Code.CODE_ALIGNMENT_MASK) & ~Code.CODE_ALIGNMENT_MASK
|
||||
|
||||
def __init__(self, heap, map, address):
|
||||
@ -1763,7 +1794,7 @@ class V8Heap(object):
|
||||
if not self.IsTaggedObjectAddress(tagged_address): return None
|
||||
address = tagged_address - 1
|
||||
if not self.reader.IsValidAddress(address): return None
|
||||
map_tagged_address = self.reader.ReadUIntPtr(address)
|
||||
map_tagged_address = self.reader.ReadTagged(address)
|
||||
if tagged_address == map_tagged_address:
|
||||
# Meta map?
|
||||
meta_map = Map(self, None, address)
|
||||
@ -1796,11 +1827,17 @@ class V8Heap(object):
|
||||
def IntSize(self):
|
||||
return 4
|
||||
|
||||
def PointerSize(self):
|
||||
return self.reader.PointerSize()
|
||||
def MachinePointerSize(self):
|
||||
return self.reader.MachinePointerSize()
|
||||
|
||||
def TaggedPointerSize(self):
|
||||
return self.reader.TaggedPointerSize()
|
||||
|
||||
def IsPointerCompressed(self):
|
||||
return self.reader.IsPointerCompressed()
|
||||
|
||||
def ObjectAlignmentMask(self):
|
||||
return self.PointerSize() - 1
|
||||
return self.TaggedPointerSize() - 1
|
||||
|
||||
def IsTaggedObjectAddress(self, address):
|
||||
return (address & self.ObjectAlignmentMask()) == 1
|
||||
@ -1829,13 +1866,14 @@ class V8Heap(object):
|
||||
return (address & self.ObjectAlignmentMask()) == 1
|
||||
|
||||
def IsSmi(self, tagged_address):
|
||||
if self.reader.Is64():
|
||||
if self.reader.Is64() and not self.reader.IsPointerCompressed():
|
||||
return (tagged_address & 0xFFFFFFFF) == 0
|
||||
return not self.IsTaggedAddress(tagged_address)
|
||||
|
||||
def SmiUntag(self, tagged_address):
|
||||
if self.reader.Is64(): return tagged_address >> 32
|
||||
return tagged_address >> 1
|
||||
if self.reader.Is64() and not self.reader.IsPointerCompressed():
|
||||
return tagged_address >> 32
|
||||
return (tagged_address >> 1) & 0xFFFFFFFF
|
||||
|
||||
def AddressTypeMarker(self, address):
|
||||
if not self.reader.IsValidAddress(address): return " "
|
||||
@ -1858,7 +1896,7 @@ class V8Heap(object):
|
||||
if self.IsTaggedObjectAddress(address):
|
||||
address -= 1
|
||||
if not self.reader.IsValidAlignedAddress(address): return None
|
||||
offset = (address - slot) / self.PointerSize()
|
||||
offset = (address - slot) / self.MachinePointerSize()
|
||||
|
||||
lower_limit = -32
|
||||
upper_limit = 128
|
||||
@ -1873,12 +1911,12 @@ class V8Heap(object):
|
||||
def FindObjectPointers(self, start=0, end=0):
|
||||
objects = set()
|
||||
def find_object_in_region(reader, start, size, location):
|
||||
for slot in range(start, start+size, self.reader.PointerSize()):
|
||||
for slot in range(start, start + size, self.reader.TaggedPointerSize()):
|
||||
if not self.reader.IsValidAddress(slot): break
|
||||
# Collect only tagged pointers (object) to tagged pointers (map)
|
||||
tagged_address = self.reader.ReadUIntPtr(slot)
|
||||
tagged_address = self.reader.ReadTagged(slot)
|
||||
if not self.IsValidTaggedObjectAddress(tagged_address): continue
|
||||
map_address = self.reader.ReadUIntPtr(tagged_address - 1)
|
||||
map_address = self.reader.ReadTagged(tagged_address - 1)
|
||||
if not self.IsTaggedMapAddress(map_address): continue
|
||||
objects.add(tagged_address)
|
||||
|
||||
@ -1951,10 +1989,12 @@ class InspectionInfo(object):
|
||||
exception_thread.stack.memory.data_size
|
||||
frame_pointer = self.reader.ExceptionFP()
|
||||
self.styles[frame_pointer] = "frame"
|
||||
for slot in range(stack_top, stack_bottom, self.reader.PointerSize()):
|
||||
for slot in range(stack_top, stack_bottom,
|
||||
self.reader.MachinePointerSize()):
|
||||
# stack address
|
||||
self.styles[slot] = "sa"
|
||||
for slot in range(stack_top, stack_bottom, self.reader.PointerSize()):
|
||||
for slot in range(stack_top, stack_bottom,
|
||||
self.reader.MachinePointerSize()):
|
||||
maybe_address = self.reader.ReadUIntPtr(slot)
|
||||
# stack value
|
||||
self.styles[maybe_address] = "sv"
|
||||
@ -2026,7 +2066,7 @@ class InspectionPadawan(object):
|
||||
# Frame markers only occur directly after a frame pointer and only on the
|
||||
# stack.
|
||||
if not self.reader.IsExceptionStackAddress(slot): return False
|
||||
next_slot = slot + self.reader.PointerSize()
|
||||
next_slot = slot + self.reader.MachinePointerSize()
|
||||
if not self.reader.IsValidAddress(next_slot): return False
|
||||
next_address = self.reader.ReadUIntPtr(next_slot)
|
||||
return self.reader.IsExceptionStackAddress(next_address)
|
||||
@ -2058,7 +2098,7 @@ class InspectionPadawan(object):
|
||||
if found_obj: return found_obj
|
||||
address = tagged_address - 1
|
||||
if self.reader.IsValidAddress(address):
|
||||
map_tagged_address = self.reader.ReadUIntPtr(address)
|
||||
map_tagged_address = self.reader.ReadTagged(address)
|
||||
map = self.SenseMap(map_tagged_address)
|
||||
if map is None: return None
|
||||
instance_type_name = INSTANCE_TYPES.get(map.instance_type)
|
||||
@ -2118,7 +2158,7 @@ class InspectionPadawan(object):
|
||||
Returns the first address where the normal stack starts again.
|
||||
"""
|
||||
# Only look at the first 1k words on the stack
|
||||
ptr_size = self.reader.PointerSize()
|
||||
ptr_size = self.reader.MachinePointerSize()
|
||||
if start is None: start = self.reader.ExceptionSP()
|
||||
if not self.reader.IsValidAddress(start): return start
|
||||
end = start + ptr_size * 1024 * 4
|
||||
@ -2140,7 +2180,7 @@ class InspectionPadawan(object):
|
||||
print_message)
|
||||
|
||||
def TryExtractStackTrace(self, slot, start, end, print_message):
|
||||
ptr_size = self.reader.PointerSize()
|
||||
ptr_size = self.reader.MachinePointerSize()
|
||||
assert self.reader.ReadUIntPtr(slot) & 0xFFFFFFFF == STACK_TRACE_MARKER
|
||||
end_marker = STACK_TRACE_MARKER + 1;
|
||||
header_size = 10
|
||||
@ -2163,7 +2203,7 @@ class InspectionPadawan(object):
|
||||
return stack_start
|
||||
|
||||
def FindPtr(self, expected_value, start, end):
|
||||
ptr_size = self.reader.PointerSize()
|
||||
ptr_size = self.reader.MachinePointerSize()
|
||||
for slot in range(start, end, ptr_size):
|
||||
if not self.reader.IsValidAddress(slot): return None
|
||||
value = self.reader.ReadUIntPtr(slot)
|
||||
@ -2171,7 +2211,7 @@ class InspectionPadawan(object):
|
||||
return None
|
||||
|
||||
def TryExtractErrorMessage(self, slot, start, end, print_message):
|
||||
ptr_size = self.reader.PointerSize()
|
||||
ptr_size = self.reader.MachinePointerSize()
|
||||
end_marker = ERROR_MESSAGE_MARKER + 1;
|
||||
header_size = 1
|
||||
end_search = start + 1024 + (header_size * ptr_size);
|
||||
@ -2186,7 +2226,7 @@ class InspectionPadawan(object):
|
||||
|
||||
def TryExtractOldStyleStackTrace(self, message_slot, start, end,
|
||||
print_message):
|
||||
ptr_size = self.reader.PointerSize()
|
||||
ptr_size = self.reader.MachinePointerSize()
|
||||
if message_slot == 0:
|
||||
"""
|
||||
On Mac we don't always get proper magic markers, so just try printing
|
||||
@ -2225,7 +2265,7 @@ class InspectionPadawan(object):
|
||||
print(" Use `dsa` to print the message with annotated addresses.")
|
||||
print("")
|
||||
return
|
||||
ptr_size = self.reader.PointerSize()
|
||||
ptr_size = self.reader.MachinePointerSize()
|
||||
# Annotate all addresses in the dumped message
|
||||
prog = re.compile("[0-9a-fA-F]{%s}" % ptr_size*2)
|
||||
addresses = list(set(prog.findall(message)))
|
||||
@ -2252,7 +2292,7 @@ class InspectionPadawan(object):
|
||||
|
||||
def TryInferContext(self, address):
|
||||
if self.context: return
|
||||
ptr_size = self.reader.PointerSize()
|
||||
ptr_size = self.reader.MachinePointerSize()
|
||||
possible_context = dict()
|
||||
count = 0
|
||||
while self.reader.IsExceptionStackAddress(address):
|
||||
@ -2287,7 +2327,7 @@ class InspectionPadawan(object):
|
||||
in_oom_dump_area = False
|
||||
is_stack = self.reader.IsExceptionStackAddress(start)
|
||||
free_space_end = 0
|
||||
ptr_size = self.reader.PointerSize()
|
||||
ptr_size = self.reader.TaggedPointerSize()
|
||||
|
||||
for slot in range(start, end, ptr_size):
|
||||
if not self.reader.IsValidAddress(slot):
|
||||
@ -2309,7 +2349,7 @@ class InspectionPadawan(object):
|
||||
if isinstance(heap_object, KnownMap) and \
|
||||
heap_object.known_name == "FreeSpaceMap":
|
||||
# The free-space length is is stored as a Smi in the next slot.
|
||||
length = self.reader.ReadUIntPtr(slot + ptr_size)
|
||||
length = self.reader.ReadTagged(slot + ptr_size)
|
||||
if self.heap.IsSmi(length):
|
||||
length = self.heap.SmiUntag(length)
|
||||
free_space_end = slot + length - ptr_size
|
||||
@ -2711,7 +2751,8 @@ class InspectionWebFormatter(object):
|
||||
stack_bottom = exception_thread.stack.start + \
|
||||
exception_thread.stack.memory.data_size
|
||||
stack_map = {self.reader.ExceptionIP(): -1}
|
||||
for slot in range(stack_top, stack_bottom, self.reader.PointerSize()):
|
||||
for slot in range(stack_top, stack_bottom,
|
||||
self.reader.MachinePointerSize()):
|
||||
maybe_address = self.reader.ReadUIntPtr(slot)
|
||||
if not maybe_address in stack_map:
|
||||
stack_map[maybe_address] = slot
|
||||
@ -2757,6 +2798,18 @@ class InspectionWebFormatter(object):
|
||||
return ("<a %s href=s?%s&val=%s>%s</a>" %
|
||||
(style_class, self.encfilename, straddress, straddress))
|
||||
|
||||
def format_onheap_address(self, size, maybeaddress, uncompressed):
|
||||
if maybeaddress is None:
|
||||
return "not in dump"
|
||||
else:
|
||||
straddress = "0x" + self.reader.FormatTagged(maybeaddress)
|
||||
struncompressed = "0x" + self.reader.FormatIntPtr(uncompressed)
|
||||
style_class = ""
|
||||
if not self.reader.IsValidAddress(maybeaddress):
|
||||
style_class = "class=nd"
|
||||
return ("<a %s href=s?%s&val=%s>%s</a>" %
|
||||
(style_class, self.encfilename, struncompressed, straddress))
|
||||
|
||||
def output_header(self, f):
|
||||
f.write(WEB_HEADER %
|
||||
{ "query_dump" : self.encfilename,
|
||||
@ -2779,7 +2832,8 @@ class InspectionWebFormatter(object):
|
||||
stack_bottom = min(exception_thread.stack.start + \
|
||||
exception_thread.stack.memory.data_size,
|
||||
stack_top + self.MAX_CONTEXT_STACK)
|
||||
self.output_words(f, stack_top - 16, stack_bottom, stack_top, "Stack")
|
||||
self.output_words(f, stack_top - 16, stack_bottom, stack_top, "Stack",
|
||||
self.heap.MachinePointerSize())
|
||||
|
||||
f.write('</div>')
|
||||
self.output_footer(f)
|
||||
@ -2900,7 +2954,11 @@ class InspectionWebFormatter(object):
|
||||
return
|
||||
region = self.reader.FindRegion(address)
|
||||
if datakind == "address":
|
||||
self.output_words(f, region[0], region[0] + region[1], address, "Dump")
|
||||
self.output_words(f, region[0], region[0] + region[1], address, "Dump",
|
||||
self.heap.MachinePointerSize())
|
||||
if datakind == "tagged":
|
||||
self.output_words(f, region[0], region[0] + region[1], address,
|
||||
"Tagged Dump", self.heap.TaggedPointerSize())
|
||||
elif datakind == "ascii":
|
||||
self.output_ascii(f, region[0], region[0] + region[1], address)
|
||||
self.output_footer(f)
|
||||
@ -2909,14 +2967,13 @@ class InspectionWebFormatter(object):
|
||||
f.write("<h3>Unrecognized address format \"%s\".</h3>" % straddress)
|
||||
return
|
||||
|
||||
def output_words(self, f, start_address, end_address,
|
||||
highlight_address, desc):
|
||||
def output_words(self, f, start_address, end_address, highlight_address, desc,
|
||||
size):
|
||||
region = self.reader.FindRegion(highlight_address)
|
||||
if region is None:
|
||||
f.write("<h3>Address 0x%x not found in the dump.</h3>" %
|
||||
(highlight_address))
|
||||
return
|
||||
size = self.heap.PointerSize()
|
||||
start_address = self.align_down(start_address, size)
|
||||
low = self.align_down(region[0], size)
|
||||
high = self.align_up(region[0] + region[1], size)
|
||||
@ -2943,6 +3000,7 @@ class InspectionWebFormatter(object):
|
||||
slot = start_address + j
|
||||
heap_object = ""
|
||||
maybe_address = None
|
||||
maybe_uncompressed_address = None
|
||||
end_region = region[0] + region[1]
|
||||
if slot < region[0] or slot + size > end_region:
|
||||
straddress = "0x"
|
||||
@ -2954,10 +3012,20 @@ class InspectionWebFormatter(object):
|
||||
for i in range(slot, region[0]):
|
||||
straddress += "??"
|
||||
else:
|
||||
maybe_address = self.reader.ReadUIntPtr(slot)
|
||||
straddress = self.format_address(maybe_address)
|
||||
if maybe_address:
|
||||
heap_object = self.format_object(maybe_address)
|
||||
maybe_address = self.reader.ReadSized(slot, size)
|
||||
if size == self.reader.MachinePointerSize():
|
||||
maybe_uncompressed_address = maybe_address
|
||||
else:
|
||||
maybe_uncompressed_address = (slot & (0xFFFFFF << 32)) | (
|
||||
maybe_address & 0xFFFFFF)
|
||||
|
||||
if size == self.reader.TaggedPointerSize():
|
||||
straddress = self.format_onheap_address(size, maybe_address,
|
||||
maybe_uncompressed_address)
|
||||
if maybe_address:
|
||||
heap_object = self.format_object(maybe_address)
|
||||
else:
|
||||
straddress = self.format_address(maybe_address)
|
||||
|
||||
address_fmt = "%s </td>"
|
||||
if slot == highlight_address:
|
||||
@ -2974,12 +3042,12 @@ class InspectionWebFormatter(object):
|
||||
f.write("</td>")
|
||||
self.td_from_address(f, slot)
|
||||
f.write(address_fmt % self.format_address(slot))
|
||||
self.td_from_address(f, maybe_address)
|
||||
self.td_from_address(f, maybe_uncompressed_address)
|
||||
f.write(": %s </td>" % straddress)
|
||||
f.write("<td>")
|
||||
if maybe_address != None:
|
||||
self.output_comment_box(
|
||||
f, "sv-" + self.reader.FormatIntPtr(slot), maybe_address)
|
||||
if maybe_uncompressed_address != None:
|
||||
self.output_comment_box(f, "sv-" + self.reader.FormatIntPtr(slot),
|
||||
maybe_uncompressed_address)
|
||||
f.write("</td>")
|
||||
f.write("<td>%s</td>" % (heap_object or ''))
|
||||
f.write("</tr>")
|
||||
@ -3134,9 +3202,9 @@ class InspectionWebFormatter(object):
|
||||
# Some disassemblers insert spaces between each byte,
|
||||
# while some do not.
|
||||
if code[2] == " ":
|
||||
op_offset = 3 * num_bytes - 1
|
||||
op_offset = 3 * num_bytes - 1
|
||||
else:
|
||||
op_offset = 2 * num_bytes
|
||||
op_offset = 2 * num_bytes
|
||||
|
||||
# Compute the actual call target which the disassembler is too stupid
|
||||
# to figure out (it adds the call offset to the disassembly offset rather
|
||||
@ -3230,7 +3298,12 @@ class InspectionWebFormatter(object):
|
||||
straddress)
|
||||
else:
|
||||
# Print as words
|
||||
self.output_words(f, address - 8, address + 32, address, "Dump")
|
||||
self.output_words(f, address - 8, address + 32, address, "Dump",
|
||||
self.heap.MachinePointerSize())
|
||||
|
||||
if self.heap.IsPointerCompressed():
|
||||
self.output_words(f, address - 8, address + 32, address,
|
||||
"Tagged Dump", self.heap.TaggedPointerSize())
|
||||
|
||||
# Print as ASCII
|
||||
f.write("<hr>")
|
||||
@ -3534,10 +3607,10 @@ class InspectionShell(cmd.Cmd):
|
||||
self.dd_start = self.ParseAddressExpr(args[0])
|
||||
self.dd_num = int(args[1], 16) if len(args) > 1 else 0x10
|
||||
else:
|
||||
self.dd_start += self.dd_num * self.reader.PointerSize()
|
||||
self.dd_start += self.dd_num * self.reader.MachinePointerSize()
|
||||
if not self.reader.IsAlignedAddress(self.dd_start):
|
||||
print("Warning: Dumping un-aligned memory, is this what you had in mind?")
|
||||
end = self.dd_start + self.reader.PointerSize() * self.dd_num
|
||||
end = self.dd_start + self.reader.MachinePointerSize() * self.dd_num
|
||||
self.padawan.InterpretMemory(self.dd_start, end)
|
||||
|
||||
def do_do(self, address):
|
||||
@ -3828,7 +3901,7 @@ def AnalyzeMinidump(options, minidump_name):
|
||||
stack_top = reader.ExceptionSP()
|
||||
stack_bottom = reader.StackBottom()
|
||||
stack_map = {reader.ExceptionIP(): -1}
|
||||
for slot in range(stack_top, stack_bottom, reader.PointerSize()):
|
||||
for slot in range(stack_top, stack_bottom, reader.MachinePointerSize()):
|
||||
maybe_address = reader.ReadUIntPtr(slot)
|
||||
if not maybe_address in stack_map:
|
||||
stack_map[maybe_address] = slot
|
||||
|
Loading…
Reference in New Issue
Block a user