From c97337ff5ece3c4838fedebddd762984d90ba6f4 Mon Sep 17 00:00:00 2001 From: Leszek Swirski Date: Fri, 4 Feb 2022 14:33:39 +0100 Subject: [PATCH] [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 Reviewed-by: Jakob Kummerow Auto-Submit: Leszek Swirski Reviewed-by: Toon Verwaest Commit-Queue: Toon Verwaest Cr-Commit-Position: refs/heads/main@{#78948} --- .style.yapf | 2 + tools/grokdump.py | 297 +++++++++++++++++++++++++++++----------------- 2 files changed, 187 insertions(+), 112 deletions(-) create mode 100644 .style.yapf diff --git a/.style.yapf b/.style.yapf new file mode 100644 index 0000000000..de0c6a70f3 --- /dev/null +++ b/.style.yapf @@ -0,0 +1,2 @@ +[style] +based_on_style = chromium diff --git a/tools/grokdump.py b/tools/grokdump.py index 368580f0c3..1d73b43ace 100755 --- a/tools/grokdump.py +++ b/tools/grokdump.py @@ -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 ("%s" % (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 ("%s" % + (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('') 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("

Unrecognized address format \"%s\".

" % 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("

Address 0x%x not found in the dump.

" % (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 " if slot == highlight_address: @@ -2974,12 +3042,12 @@ class InspectionWebFormatter(object): f.write("") 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 " % straddress) f.write("") - 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("") f.write("%s" % (heap_object or '')) f.write("") @@ -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("
") @@ -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