Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(203)

Side by Side Diff: tools/grokdump.py

Issue 12389077: Extend grokdump with support for maps, transition and descriptor arrays. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comments Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright 2012 the V8 project authors. All rights reserved. 3 # Copyright 2012 the V8 project authors. All rights reserved.
4 # Redistribution and use in source and binary forms, with or without 4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are 5 # modification, are permitted provided that the following conditions are
6 # met: 6 # met:
7 # 7 #
8 # * Redistributions of source code must retain the above copyright 8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer. 9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above 10 # * Redistributions in binary form must reproduce the above
(...skipping 1127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1138 field_value = self.heap.reader.ReadUIntPtr(self.address + offset) 1138 field_value = self.heap.reader.ReadUIntPtr(self.address + offset)
1139 return self.heap.FindObjectOrSmi(field_value) 1139 return self.heap.FindObjectOrSmi(field_value)
1140 1140
1141 def SmiField(self, offset): 1141 def SmiField(self, offset):
1142 field_value = self.heap.reader.ReadUIntPtr(self.address + offset) 1142 field_value = self.heap.reader.ReadUIntPtr(self.address + offset)
1143 assert (field_value & 1) == 0 1143 assert (field_value & 1) == 0
1144 return field_value / 2 1144 return field_value / 2
1145 1145
1146 1146
1147 class Map(HeapObject): 1147 class Map(HeapObject):
1148 def Decode(self, offset, size, value):
1149 return (value >> offset) & ((1 << size) - 1)
1150
1151 # Instance Sizes
1152 def InstanceSizesOffset(self):
1153 return self.heap.PointerSize()
1154
1155 def InstanceSizeOffset(self):
1156 return self.InstanceSizesOffset()
1157
1158 def InObjectProperties(self):
1159 return self.InstanceSizeOffset() + 1
1160
1161 def PreAllocatedPropertyFields(self):
1162 return self.InObjectProperties() + 1
1163
1164 def VisitorId(self):
1165 return self.PreAllocatedPropertyFields() + 1
1166
1167 # Instance Attributes
1168 def InstanceAttributesOffset(self):
1169 return self.InstanceSizesOffset() + self.heap.IntSize()
1170
1148 def InstanceTypeOffset(self): 1171 def InstanceTypeOffset(self):
1149 return self.heap.PointerSize() + self.heap.IntSize() 1172 return self.InstanceAttributesOffset()
1173
1174 def UnusedPropertyFieldsOffset(self):
1175 return self.InstanceTypeOffset() + 1
1176
1177 def BitFieldOffset(self):
1178 return self.UnusedPropertyFieldsOffset() + 1
1179
1180 def BitField2Offset(self):
1181 return self.BitFieldOffset() + 1
1182
1183 # Other fields
1184 def PrototypeOffset(self):
1185 return self.InstanceAttributesOffset() + self.heap.IntSize()
1186
1187 def ConstructorOffset(self):
1188 return self.PrototypeOffset() + self.heap.PointerSize()
1189
1190 def TransitionsOrBackPointerOffset(self):
1191 return self.ConstructorOffset() + self.heap.PointerSize()
1192
1193 def DescriptorsOffset(self):
1194 return self.TransitionsOrBackPointerOffset() + self.heap.PointerSize()
1195
1196 def CodeCacheOffset(self):
1197 return self.DescriptorsOffset() + self.heap.PointerSize()
1198
1199 def DependentCodeOffset(self):
1200 return self.CodeCacheOffset() + self.heap.PointerSize()
1201
1202 def BitField3Offset(self):
1203 return self.DependentCodeOffset() + self.heap.PointerSize()
1204
1205 def ReadByte(self, offset):
1206 return self.heap.reader.ReadU8(self.address + offset)
1207
1208 def Print(self):
1209 print "Map(%08x)" % (self.address)
1210 print "- size: %d, inobject: %d, preallocated: %d, visitor: %d" % (
1211 self.ReadByte(self.InstanceSizeOffset()),
1212 self.ReadByte(self.InObjectProperties()),
1213 self.ReadByte(self.PreAllocatedPropertyFields()),
1214 self.VisitorId())
1215
1216 bitfield = self.ReadByte(self.BitFieldOffset())
1217 bitfield2 = self.ReadByte(self.BitField2Offset())
1218 print "- %s, unused: %d, bf: %d, bf2: %d" % (
1219 INSTANCE_TYPES[self.ReadByte(self.InstanceTypeOffset())],
1220 self.ReadByte(self.UnusedPropertyFieldsOffset()),
1221 bitfield, bitfield2)
1222
1223 print "- kind: %s" % (self.Decode(3, 5, bitfield2))
1224
1225 bitfield3 = self.ObjectField(self.BitField3Offset())
1226 print "- EnumLength: %d NumberOfOwnDescriptors: %d OwnsDescriptors: %s" % (
1227 self.Decode(0, 11, bitfield3),
1228 self.Decode(11, 11, bitfield3),
1229 self.Decode(25, 1, bitfield3))
1230 print "- IsShared: %s" % (self.Decode(22, 1, bitfield3))
1231 print "- FunctionWithPrototype: %s" % (self.Decode(23, 1, bitfield3))
1232 print "- DictionaryMap: %s" % (self.Decode(24, 1, bitfield3))
1233
1234 descriptors = self.ObjectField(self.DescriptorsOffset())
1235 if descriptors.__class__ == FixedArray:
1236 DescriptorArray(descriptors).Print()
1237 else:
1238 print "Descriptors: %s" % (descriptors)
1239
1240 transitions = self.ObjectField(self.TransitionsOrBackPointerOffset())
1241 if transitions.__class__ == FixedArray:
1242 TransitionArray(transitions).Print()
1243 else:
1244 print "TransitionsOrBackPointer: %s" % (transitions)
1150 1245
1151 def __init__(self, heap, map, address): 1246 def __init__(self, heap, map, address):
1152 HeapObject.__init__(self, heap, map, address) 1247 HeapObject.__init__(self, heap, map, address)
1153 self.instance_type = \ 1248 self.instance_type = \
1154 heap.reader.ReadU8(self.address + self.InstanceTypeOffset()) 1249 heap.reader.ReadU8(self.address + self.InstanceTypeOffset())
1155 1250
1156 1251
1157 class String(HeapObject): 1252 class String(HeapObject):
1158 def LengthOffset(self): 1253 def LengthOffset(self):
1159 return self.heap.PointerSize() 1254 return self.heap.PointerSize()
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1273 return "Oddball(%08x, kind=%s)" % (self.address, kind) 1368 return "Oddball(%08x, kind=%s)" % (self.address, kind)
1274 1369
1275 1370
1276 class FixedArray(HeapObject): 1371 class FixedArray(HeapObject):
1277 def LengthOffset(self): 1372 def LengthOffset(self):
1278 return self.heap.PointerSize() 1373 return self.heap.PointerSize()
1279 1374
1280 def ElementsOffset(self): 1375 def ElementsOffset(self):
1281 return self.heap.PointerSize() * 2 1376 return self.heap.PointerSize() * 2
1282 1377
1378 def MemberOffset(self, i):
1379 return self.ElementsOffset() + self.heap.PointerSize() * i
1380
1381 def Get(self, i):
1382 return self.ObjectField(self.MemberOffset(i))
1383
1283 def __init__(self, heap, map, address): 1384 def __init__(self, heap, map, address):
1284 HeapObject.__init__(self, heap, map, address) 1385 HeapObject.__init__(self, heap, map, address)
1285 self.length = self.SmiField(self.LengthOffset()) 1386 self.length = self.SmiField(self.LengthOffset())
1286 1387
1287 def Print(self, p): 1388 def Print(self, p):
1288 p.Print("FixedArray(%s) {" % self.heap.reader.FormatIntPtr(self.address)) 1389 p.Print("FixedArray(%s) {" % self.heap.reader.FormatIntPtr(self.address))
1289 p.Indent() 1390 p.Indent()
1290 p.Print("length: %d" % self.length) 1391 p.Print("length: %d" % self.length)
1291 base_offset = self.ElementsOffset() 1392 base_offset = self.ElementsOffset()
1292 for i in xrange(self.length): 1393 for i in xrange(self.length):
1293 offset = base_offset + 4 * i 1394 offset = base_offset + 4 * i
1294 try: 1395 try:
1295 p.Print("[%08d] = %s" % (i, self.ObjectField(offset))) 1396 p.Print("[%08d] = %s" % (i, self.ObjectField(offset)))
1296 except TypeError: 1397 except TypeError:
1297 p.Dedent() 1398 p.Dedent()
1298 p.Print("...") 1399 p.Print("...")
1299 p.Print("}") 1400 p.Print("}")
1300 return 1401 return
1301 p.Dedent() 1402 p.Dedent()
1302 p.Print("}") 1403 p.Print("}")
1303 1404
1304 def __str__(self): 1405 def __str__(self):
1305 return "FixedArray(%08x, length=%d)" % (self.address, self.length) 1406 return "FixedArray(%08x, length=%d)" % (self.address, self.length)
1306 1407
1307 1408
1409 class DescriptorArray(object):
1410 def __init__(self, array):
1411 self.array = array
1412
1413 def Length(self):
1414 return self.array.Get(0)
1415
1416 def Decode(self, offset, size, value):
1417 return (value >> offset) & ((1 << size) - 1)
1418
1419 TYPES = [
1420 "normal",
1421 "field",
1422 "function",
1423 "callbacks"
1424 ]
1425
1426 def Type(self, value):
1427 return DescriptorArray.TYPES[self.Decode(0, 3, value)]
1428
1429 def Attributes(self, value):
1430 attributes = self.Decode(3, 3, value)
1431 result = []
1432 if (attributes & 0): result += ["ReadOnly"]
1433 if (attributes & 1): result += ["DontEnum"]
1434 if (attributes & 2): result += ["DontDelete"]
1435 return "[" + (",".join(result)) + "]"
1436
1437 def Deleted(self, value):
1438 return self.Decode(6, 1, value) == 1
1439
1440 def Storage(self, value):
1441 return self.Decode(7, 11, value)
1442
1443 def Pointer(self, value):
1444 return self.Decode(18, 11, value)
1445
1446 def Details(self, di, value):
1447 return (
1448 di,
1449 self.Type(value),
1450 self.Attributes(value),
1451 self.Storage(value),
1452 self.Pointer(value)
1453 )
1454
1455
1456 def Print(self):
1457 length = self.Length()
1458 array = self.array
1459
1460 print "Descriptors(%08x, length=%d)" % (array.address, length)
1461 print "[et] %s" % (array.Get(1))
1462
1463 for di in xrange(length):
1464 i = 2 + di * 3
1465 print "0x%x" % (array.address + array.MemberOffset(i))
1466 print "[%i] name: %s" % (di, array.Get(i + 0))
1467 print "[%i] details: %s %s enum %i pointer %i" % \
1468 self.Details(di, array.Get(i + 1))
1469 print "[%i] value: %s" % (di, array.Get(i + 2))
1470
1471 end = self.array.length // 3
1472 if length != end:
1473 print "[%i-%i] slack descriptors" % (length, end)
1474
1475
1476 class TransitionArray(object):
1477 def __init__(self, array):
1478 self.array = array
1479
1480 def IsSimpleTransition(self):
1481 return self.array.length <= 2
1482
1483 def Length(self):
1484 # SimpleTransition cases
1485 if self.IsSimpleTransition():
1486 return self.array.length - 1
1487 return (self.array.length - 3) // 2
1488
1489 def Print(self):
1490 length = self.Length()
1491 array = self.array
1492
1493 print "Transitions(%08x, length=%d)" % (array.address, length)
1494 print "[backpointer] %s" % (array.Get(0))
1495 if self.IsSimpleTransition():
1496 if length == 1:
1497 print "[simple target] %s" % (array.Get(1))
1498 return
1499
1500 elements = array.Get(1)
1501 if elements is not None:
1502 print "[elements ] %s" % (elements)
1503
1504 prototype = array.Get(2)
1505 if prototype is not None:
1506 print "[prototype ] %s" % (prototype)
1507
1508 for di in xrange(length):
1509 i = 3 + di * 2
1510 print "[%i] symbol: %s" % (di, array.Get(i + 0))
1511 print "[%i] target: %s" % (di, array.Get(i + 1))
1512
1513
1308 class JSFunction(HeapObject): 1514 class JSFunction(HeapObject):
1309 def CodeEntryOffset(self): 1515 def CodeEntryOffset(self):
1310 return 3 * self.heap.PointerSize() 1516 return 3 * self.heap.PointerSize()
1311 1517
1312 def SharedOffset(self): 1518 def SharedOffset(self):
1313 return 5 * self.heap.PointerSize() 1519 return 5 * self.heap.PointerSize()
1314 1520
1315 def __init__(self, heap, map, address): 1521 def __init__(self, heap, map, address):
1316 HeapObject.__init__(self, heap, map, address) 1522 HeapObject.__init__(self, heap, map, address)
1317 code_entry = \ 1523 code_entry = \
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
1713 address = address + 1 1919 address = address + 1
1714 elif (address & self.heap.ObjectAlignmentMask()) != 1: 1920 elif (address & self.heap.ObjectAlignmentMask()) != 1:
1715 print "Address doesn't look like a valid pointer!" 1921 print "Address doesn't look like a valid pointer!"
1716 return 1922 return
1717 heap_object = self.padawan.SenseObject(address) 1923 heap_object = self.padawan.SenseObject(address)
1718 if heap_object: 1924 if heap_object:
1719 heap_object.Print(Printer()) 1925 heap_object.Print(Printer())
1720 else: 1926 else:
1721 print "Address cannot be interpreted as object!" 1927 print "Address cannot be interpreted as object!"
1722 1928
1929 def do_do_desc(self, address):
1930 """
1931 Print a descriptor array in a readable format.
1932 """
1933 start = int(address, 16)
1934 if ((start & 1) == 1): start = start + 1
1935 DescriptorArray(FixedArray(self.heap, None, start)).Print()
1936
1937 def do_do_map(self, address):
1938 """
1939 Print a descriptor array in a readable format.
1940 """
1941 start = int(address, 16)
1942 if ((start & 1) == 1): start = start - 1
1943 Map(self.heap, None, start).Print()
1944
1945 def do_do_trans(self, address):
1946 """
1947 Print a transition array in a readable format.
1948 """
1949 start = int(address, 16)
1950 if ((start & 1) == 1): start = start - 1
1951 TransitionArray(FixedArray(self.heap, None, start)).Print()
1952
1723 def do_dp(self, address): 1953 def do_dp(self, address):
1724 """ 1954 """
1725 Interpret memory at the given address as being on a V8 heap page 1955 Interpret memory at the given address as being on a V8 heap page
1726 and print information about the page header (if available). 1956 and print information about the page header (if available).
1727 """ 1957 """
1728 address = int(address, 16) 1958 address = int(address, 16)
1729 page_address = address & ~self.heap.PageAlignmentMask() 1959 page_address = address & ~self.heap.PageAlignmentMask()
1730 if self.reader.IsValidAddress(page_address): 1960 if self.reader.IsValidAddress(page_address):
1731 raise NotImplementedError 1961 raise NotImplementedError
1732 else: 1962 else:
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
1930 options, args = parser.parse_args() 2160 options, args = parser.parse_args()
1931 if os.path.exists(options.objdump): 2161 if os.path.exists(options.objdump):
1932 disasm.OBJDUMP_BIN = options.objdump 2162 disasm.OBJDUMP_BIN = options.objdump
1933 OBJDUMP_BIN = options.objdump 2163 OBJDUMP_BIN = options.objdump
1934 else: 2164 else:
1935 print "Cannot find %s, falling back to default objdump" % options.objdump 2165 print "Cannot find %s, falling back to default objdump" % options.objdump
1936 if len(args) != 1: 2166 if len(args) != 1:
1937 parser.print_help() 2167 parser.print_help()
1938 sys.exit(1) 2168 sys.exit(1)
1939 AnalyzeMinidump(options, args[0]) 2169 AnalyzeMinidump(options, args[0])
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698