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

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: 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" % self.Details(di, array.Ge t(i + 1))
Michael Starzinger 2013/03/05 16:14:57 Longer than 80 characters.
Toon Verwaest 2013/03/06 15:24:11 Done.
1468 print "[%i] value: %s" % (di, array.Get(i + 2))
1469
1470 end = self.array.length // 3
1471 if length != end:
1472 print "[%i-%i] slack descriptors" % (length, end)
1473
1474
1475 class TransitionArray(object):
1476 def __init__(self, array):
1477 self.array = array
1478
1479 def IsSimpleTransition(self):
1480 return self.array.length <= 2
1481
1482 def Length(self):
1483 # SimpleTransition cases
1484 if self.IsSimpleTransition():
1485 return self.array.length - 1
1486 return (self.array.length - 3) // 2
1487
1488 def Print(self):
1489 length = self.Length()
1490 array = self.array
1491
1492 print "Transitions(%08x, length=%d)" % (array.address, length)
1493 print "[backpointer] %s" % (array.Get(0))
1494 if self.IsSimpleTransition():
1495 if length == 1:
1496 print "[simple target] %s" % (array.Get(1))
1497 return
1498
1499 elements = array.Get(1)
1500 if elements is not None:
1501 print "[elements ] %s" % (elements)
1502
1503 prototype = array.Get(2)
1504 if prototype is not None:
1505 print "[prototype ] %s" % (prototype)
1506
1507 for di in xrange(length):
1508 i = 3 + di * 2
1509 print "[%i] symbol: %s" % (di, array.Get(i + 0))
1510 print "[%i] target: %s" % (di, array.Get(i + 1))
1511
1512
1308 class JSFunction(HeapObject): 1513 class JSFunction(HeapObject):
1309 def CodeEntryOffset(self): 1514 def CodeEntryOffset(self):
1310 return 3 * self.heap.PointerSize() 1515 return 3 * self.heap.PointerSize()
1311 1516
1312 def SharedOffset(self): 1517 def SharedOffset(self):
1313 return 5 * self.heap.PointerSize() 1518 return 5 * self.heap.PointerSize()
1314 1519
1315 def __init__(self, heap, map, address): 1520 def __init__(self, heap, map, address):
1316 HeapObject.__init__(self, heap, map, address) 1521 HeapObject.__init__(self, heap, map, address)
1317 code_entry = \ 1522 code_entry = \
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after
1795 self.reader.FindWord(word) 2000 self.reader.FindWord(word)
1796 2001
1797 def do_sh(self, none): 2002 def do_sh(self, none):
1798 """ 2003 """
1799 Search for the V8 Heap object in all available memory regions. You 2004 Search for the V8 Heap object in all available memory regions. You
1800 might get lucky and find this rare treasure full of invaluable 2005 might get lucky and find this rare treasure full of invaluable
1801 information. 2006 information.
1802 """ 2007 """
1803 raise NotImplementedError 2008 raise NotImplementedError
1804 2009
2010 def do_desc(self, address):
Michael Starzinger 2013/03/05 16:14:57 Can we rename these commands to have a common pref
Toon Verwaest 2013/03/06 15:24:11 Done.
2011 """
2012 Print a descriptor array in a readable format.
2013 """
2014 start = int(address, 16)
2015 if ((start & 1) == 1): start = start + 1
2016 DescriptorArray(FixedArray(self.heap, None, start)).Print()
2017
2018 def do_trans(self, address):
2019 """
2020 Print a transition array in a readable format.
2021 """
2022 start = int(address, 16)
2023 if ((start & 1) == 1): start = start - 1
2024 TransitionArray(FixedArray(self.heap, None, start)).Print()
2025
2026 def do_map(self, address):
2027 """
2028 Print a descriptor array in a readable format.
2029 """
2030 start = int(address, 16)
2031 if ((start & 1) == 1): start = start - 1
2032 Map(self.heap, None, start).Print()
2033
1805 def do_u(self, args): 2034 def do_u(self, args):
1806 """ 2035 """
1807 u 0x<address> 0x<size> 2036 u 0x<address> 0x<size>
1808 Unassemble memory in the region [address, address + size) 2037 Unassemble memory in the region [address, address + size)
1809 """ 2038 """
1810 args = args.split(' ') 2039 args = args.split(' ')
1811 start = int(args[0], 16) 2040 start = int(args[0], 16)
1812 size = int(args[1], 16) 2041 size = int(args[1], 16)
1813 lines = self.reader.GetDisasmLines(start, size) 2042 lines = self.reader.GetDisasmLines(start, size)
1814 for line in lines: 2043 for line in lines:
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
1930 options, args = parser.parse_args() 2159 options, args = parser.parse_args()
1931 if os.path.exists(options.objdump): 2160 if os.path.exists(options.objdump):
1932 disasm.OBJDUMP_BIN = options.objdump 2161 disasm.OBJDUMP_BIN = options.objdump
1933 OBJDUMP_BIN = options.objdump 2162 OBJDUMP_BIN = options.objdump
1934 else: 2163 else:
1935 print "Cannot find %s, falling back to default objdump" % options.objdump 2164 print "Cannot find %s, falling back to default objdump" % options.objdump
1936 if len(args) != 1: 2165 if len(args) != 1:
1937 parser.print_help() 2166 parser.print_help()
1938 sys.exit(1) 2167 sys.exit(1)
1939 AnalyzeMinidump(options, args[0]) 2168 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