xref: /aosp_15_r20/art/tools/ahat/etc/hprofdump.py (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker# Copyright (C) 2018 The Android Open Source Project
2*795d594fSAndroid Build Coastguard Worker#
3*795d594fSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*795d594fSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*795d594fSAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*795d594fSAndroid Build Coastguard Worker#
7*795d594fSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
8*795d594fSAndroid Build Coastguard Worker#
9*795d594fSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*795d594fSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*795d594fSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*795d594fSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*795d594fSAndroid Build Coastguard Worker# limitations under the License.
14*795d594fSAndroid Build Coastguard Worker
15*795d594fSAndroid Build Coastguard Worker# usage: python hprofdump.py FILE
16*795d594fSAndroid Build Coastguard Worker#   Dumps a binary heap dump file to text, to facilitate debugging of heap
17*795d594fSAndroid Build Coastguard Worker#   dumps and heap dump viewers.
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Workerimport time
20*795d594fSAndroid Build Coastguard Workerimport struct
21*795d594fSAndroid Build Coastguard Workerimport sys
22*795d594fSAndroid Build Coastguard Worker
23*795d594fSAndroid Build Coastguard Workerfilename = sys.argv[1]
24*795d594fSAndroid Build Coastguard Workerhprof = open(filename, "rb")
25*795d594fSAndroid Build Coastguard Worker
26*795d594fSAndroid Build Coastguard Workerdef readu1(hprof):
27*795d594fSAndroid Build Coastguard Worker  return struct.unpack('!B', hprof.read(1))[0]
28*795d594fSAndroid Build Coastguard Worker
29*795d594fSAndroid Build Coastguard Workerdef readu2(hprof):
30*795d594fSAndroid Build Coastguard Worker  return struct.unpack('!H', hprof.read(2))[0]
31*795d594fSAndroid Build Coastguard Worker
32*795d594fSAndroid Build Coastguard Workerdef readu4(hprof):
33*795d594fSAndroid Build Coastguard Worker  return struct.unpack('!I', hprof.read(4))[0]
34*795d594fSAndroid Build Coastguard Worker
35*795d594fSAndroid Build Coastguard Workerdef readu8(hprof):
36*795d594fSAndroid Build Coastguard Worker  return struct.unpack('!Q', hprof.read(8))[0]
37*795d594fSAndroid Build Coastguard Worker
38*795d594fSAndroid Build Coastguard Workerdef readN(n, hprof):
39*795d594fSAndroid Build Coastguard Worker  if n == 1:
40*795d594fSAndroid Build Coastguard Worker    return readu1(hprof)
41*795d594fSAndroid Build Coastguard Worker  if n == 2:
42*795d594fSAndroid Build Coastguard Worker    return readu2(hprof)
43*795d594fSAndroid Build Coastguard Worker  if n == 4:
44*795d594fSAndroid Build Coastguard Worker    return readu4(hprof)
45*795d594fSAndroid Build Coastguard Worker  if n == 8:
46*795d594fSAndroid Build Coastguard Worker    return readu8(hprof)
47*795d594fSAndroid Build Coastguard Worker  raise Exception("Unsupported size of readN: %d" % n)
48*795d594fSAndroid Build Coastguard Worker
49*795d594fSAndroid Build Coastguard WorkerTY_OBJECT = 2
50*795d594fSAndroid Build Coastguard WorkerTY_BOOLEAN = 4
51*795d594fSAndroid Build Coastguard WorkerTY_CHAR = 5
52*795d594fSAndroid Build Coastguard WorkerTY_FLOAT = 6
53*795d594fSAndroid Build Coastguard WorkerTY_DOUBLE = 7
54*795d594fSAndroid Build Coastguard WorkerTY_BYTE = 8
55*795d594fSAndroid Build Coastguard WorkerTY_SHORT = 9
56*795d594fSAndroid Build Coastguard WorkerTY_INT = 10
57*795d594fSAndroid Build Coastguard WorkerTY_LONG = 11
58*795d594fSAndroid Build Coastguard Worker
59*795d594fSAndroid Build Coastguard Workerdef showty(ty):
60*795d594fSAndroid Build Coastguard Worker  if ty == TY_OBJECT:
61*795d594fSAndroid Build Coastguard Worker    return "Object"
62*795d594fSAndroid Build Coastguard Worker  if ty == TY_BOOLEAN:
63*795d594fSAndroid Build Coastguard Worker    return "boolean"
64*795d594fSAndroid Build Coastguard Worker  if ty == TY_CHAR:
65*795d594fSAndroid Build Coastguard Worker    return "char"
66*795d594fSAndroid Build Coastguard Worker  if ty == TY_FLOAT:
67*795d594fSAndroid Build Coastguard Worker    return "float"
68*795d594fSAndroid Build Coastguard Worker  if ty == TY_DOUBLE:
69*795d594fSAndroid Build Coastguard Worker    return "double"
70*795d594fSAndroid Build Coastguard Worker  if ty == TY_BYTE:
71*795d594fSAndroid Build Coastguard Worker    return "byte"
72*795d594fSAndroid Build Coastguard Worker  if ty == TY_SHORT:
73*795d594fSAndroid Build Coastguard Worker    return "short"
74*795d594fSAndroid Build Coastguard Worker  if ty == TY_INT:
75*795d594fSAndroid Build Coastguard Worker    return "int"
76*795d594fSAndroid Build Coastguard Worker  if ty == TY_LONG:
77*795d594fSAndroid Build Coastguard Worker    return "long"
78*795d594fSAndroid Build Coastguard Worker  raise Exception("Unsupported type %d" % ty)
79*795d594fSAndroid Build Coastguard Worker
80*795d594fSAndroid Build Coastguard Workerstrs = { }
81*795d594fSAndroid Build Coastguard Workerdef showstr(id):
82*795d594fSAndroid Build Coastguard Worker  if id in strs:
83*795d594fSAndroid Build Coastguard Worker    return strs[id]
84*795d594fSAndroid Build Coastguard Worker  return "STR[@%x]" % id
85*795d594fSAndroid Build Coastguard Worker
86*795d594fSAndroid Build Coastguard Workerloaded = { }
87*795d594fSAndroid Build Coastguard Workerdef showloaded(serial):
88*795d594fSAndroid Build Coastguard Worker  if serial in loaded:
89*795d594fSAndroid Build Coastguard Worker    return showstr(loaded[serial])
90*795d594fSAndroid Build Coastguard Worker  return "SERIAL[@%x]" % serial
91*795d594fSAndroid Build Coastguard Worker
92*795d594fSAndroid Build Coastguard Workerclassobjs = { }
93*795d594fSAndroid Build Coastguard Workerdef showclassobj(id):
94*795d594fSAndroid Build Coastguard Worker  if id in classobjs:
95*795d594fSAndroid Build Coastguard Worker    return "%s @%x" % (showstr(classobjs[id]), id)
96*795d594fSAndroid Build Coastguard Worker  return "@%x" % id
97*795d594fSAndroid Build Coastguard Worker
98*795d594fSAndroid Build Coastguard Worker
99*795d594fSAndroid Build Coastguard Worker# [u1]* An initial NULL terminate series of bytes representing the format name
100*795d594fSAndroid Build Coastguard Worker# and version.
101*795d594fSAndroid Build Coastguard Workerversion = ""
102*795d594fSAndroid Build Coastguard Workerc = hprof.read(1)
103*795d594fSAndroid Build Coastguard Workerwhile (c != '\0'):
104*795d594fSAndroid Build Coastguard Worker  version += c
105*795d594fSAndroid Build Coastguard Worker  c = hprof.read(1)
106*795d594fSAndroid Build Coastguard Workerprint "Version: %s" % version
107*795d594fSAndroid Build Coastguard Worker
108*795d594fSAndroid Build Coastguard Worker# [u4] size of identifiers.
109*795d594fSAndroid Build Coastguard Workeridsize = readu4(hprof)
110*795d594fSAndroid Build Coastguard Workerprint "ID Size: %d bytes" % idsize
111*795d594fSAndroid Build Coastguard Workerdef readID(hprof):
112*795d594fSAndroid Build Coastguard Worker  return readN(idsize, hprof)
113*795d594fSAndroid Build Coastguard Worker
114*795d594fSAndroid Build Coastguard Workerdef valsize(ty):
115*795d594fSAndroid Build Coastguard Worker  if ty == TY_OBJECT:
116*795d594fSAndroid Build Coastguard Worker    return idsize
117*795d594fSAndroid Build Coastguard Worker  if ty == TY_BOOLEAN:
118*795d594fSAndroid Build Coastguard Worker    return 1
119*795d594fSAndroid Build Coastguard Worker  if ty == TY_CHAR:
120*795d594fSAndroid Build Coastguard Worker    return 2
121*795d594fSAndroid Build Coastguard Worker  if ty == TY_FLOAT:
122*795d594fSAndroid Build Coastguard Worker    return 4
123*795d594fSAndroid Build Coastguard Worker  if ty == TY_DOUBLE:
124*795d594fSAndroid Build Coastguard Worker    return 8
125*795d594fSAndroid Build Coastguard Worker  if ty == TY_BYTE:
126*795d594fSAndroid Build Coastguard Worker    return 1
127*795d594fSAndroid Build Coastguard Worker  if ty == TY_SHORT:
128*795d594fSAndroid Build Coastguard Worker    return 2
129*795d594fSAndroid Build Coastguard Worker  if ty == TY_INT:
130*795d594fSAndroid Build Coastguard Worker    return 4
131*795d594fSAndroid Build Coastguard Worker  if ty == TY_LONG:
132*795d594fSAndroid Build Coastguard Worker    return 8
133*795d594fSAndroid Build Coastguard Worker  raise Exception("Unsupported type %d" % ty)
134*795d594fSAndroid Build Coastguard Worker
135*795d594fSAndroid Build Coastguard Workerdef readval(ty, hprof):
136*795d594fSAndroid Build Coastguard Worker  return readN(valsize(ty), hprof)
137*795d594fSAndroid Build Coastguard Worker
138*795d594fSAndroid Build Coastguard Worker# [u4] high word of number of ms since 0:00 GMT, 1/1/70
139*795d594fSAndroid Build Coastguard Worker# [u4] low word of number of ms since 0:00 GMT, 1/1/70
140*795d594fSAndroid Build Coastguard Workertimestamp = (readu4(hprof) << 32) | readu4(hprof)
141*795d594fSAndroid Build Coastguard Workers, ms = divmod(timestamp, 1000)
142*795d594fSAndroid Build Coastguard Workerprint "Date: %s.%03d" % (time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(s)), ms)
143*795d594fSAndroid Build Coastguard Worker
144*795d594fSAndroid Build Coastguard Workerwhile hprof.read(1):
145*795d594fSAndroid Build Coastguard Worker  hprof.seek(-1,1)
146*795d594fSAndroid Build Coastguard Worker  pos = hprof.tell()
147*795d594fSAndroid Build Coastguard Worker  tag = readu1(hprof)
148*795d594fSAndroid Build Coastguard Worker  time = readu4(hprof)
149*795d594fSAndroid Build Coastguard Worker  length = readu4(hprof)
150*795d594fSAndroid Build Coastguard Worker  if tag == 0x01:
151*795d594fSAndroid Build Coastguard Worker    id = readID(hprof)
152*795d594fSAndroid Build Coastguard Worker    string = hprof.read(length - idsize)
153*795d594fSAndroid Build Coastguard Worker    print "%d: STRING %x %s" % (pos, id, repr(string))
154*795d594fSAndroid Build Coastguard Worker    strs[id] = string
155*795d594fSAndroid Build Coastguard Worker  elif tag == 0x02:
156*795d594fSAndroid Build Coastguard Worker    serial = readu4(hprof)
157*795d594fSAndroid Build Coastguard Worker    classobj = readID(hprof)
158*795d594fSAndroid Build Coastguard Worker    stack = readu4(hprof)
159*795d594fSAndroid Build Coastguard Worker    classname = readID(hprof)
160*795d594fSAndroid Build Coastguard Worker    loaded[serial] = classname
161*795d594fSAndroid Build Coastguard Worker    classobjs[classobj] = classname
162*795d594fSAndroid Build Coastguard Worker    print "LOAD CLASS #%d %s @%x stack=@%x" % (serial, showstr(classname), classobj, stack)
163*795d594fSAndroid Build Coastguard Worker  elif tag == 0x04:
164*795d594fSAndroid Build Coastguard Worker    id = readID(hprof)
165*795d594fSAndroid Build Coastguard Worker    method = readID(hprof)
166*795d594fSAndroid Build Coastguard Worker    sig = readID(hprof)
167*795d594fSAndroid Build Coastguard Worker    file = readID(hprof)
168*795d594fSAndroid Build Coastguard Worker    serial = readu4(hprof)
169*795d594fSAndroid Build Coastguard Worker    line = readu4(hprof);
170*795d594fSAndroid Build Coastguard Worker    print "STACK FRAME %d '%s' '%s' '%s' line=%d classserial=%d" % (id, showstr(method), showstr(sig), showstr(file), line, serial)
171*795d594fSAndroid Build Coastguard Worker  elif tag == 0x05:
172*795d594fSAndroid Build Coastguard Worker    serial = readu4(hprof)
173*795d594fSAndroid Build Coastguard Worker    print "STACK TRACE %d" % serial
174*795d594fSAndroid Build Coastguard Worker    thread = readu4(hprof)
175*795d594fSAndroid Build Coastguard Worker    frames = readu4(hprof)
176*795d594fSAndroid Build Coastguard Worker    hprof.read(idsize * frames)
177*795d594fSAndroid Build Coastguard Worker  elif tag == 0x06:
178*795d594fSAndroid Build Coastguard Worker    print "ALLOC SITES"
179*795d594fSAndroid Build Coastguard Worker    flags = readu2(hprof)
180*795d594fSAndroid Build Coastguard Worker    cutoff_ratio = readu4(hprof)
181*795d594fSAndroid Build Coastguard Worker    live_bytes = readu4(hprof)
182*795d594fSAndroid Build Coastguard Worker    live_insts = readu4(hprof)
183*795d594fSAndroid Build Coastguard Worker    alloc_bytes = readu8(hprof)
184*795d594fSAndroid Build Coastguard Worker    alloc_insts = readu8(hprof)
185*795d594fSAndroid Build Coastguard Worker    numsites = readu4(hprof)
186*795d594fSAndroid Build Coastguard Worker    while numsites > 0:
187*795d594fSAndroid Build Coastguard Worker      indicator = readu1(hprof)
188*795d594fSAndroid Build Coastguard Worker      class_serial = readu4(hprof)
189*795d594fSAndroid Build Coastguard Worker      stack = readu4(hprof)
190*795d594fSAndroid Build Coastguard Worker      live_bytes = readu4(hprof)
191*795d594fSAndroid Build Coastguard Worker      live_insts = readu4(hprof)
192*795d594fSAndroid Build Coastguard Worker      alloc_bytes = readu4(hprof)
193*795d594fSAndroid Build Coastguard Worker      alloc_insts = readu4(hprof)
194*795d594fSAndroid Build Coastguard Worker      numsites -= 1
195*795d594fSAndroid Build Coastguard Worker  elif tag == 0x0A:
196*795d594fSAndroid Build Coastguard Worker    thread = readu4(hprof)
197*795d594fSAndroid Build Coastguard Worker    object = readID(hprof)
198*795d594fSAndroid Build Coastguard Worker    stack = readu4(hprof)
199*795d594fSAndroid Build Coastguard Worker    name = readID(hprof)
200*795d594fSAndroid Build Coastguard Worker    group_name = readID(hprof)
201*795d594fSAndroid Build Coastguard Worker    pgroup_name = readID(hprof)
202*795d594fSAndroid Build Coastguard Worker    print "START THREAD serial=%d" % thread
203*795d594fSAndroid Build Coastguard Worker  elif tag == 0x0B:
204*795d594fSAndroid Build Coastguard Worker    thread = readu4(hprof)
205*795d594fSAndroid Build Coastguard Worker    print "END THREAD"
206*795d594fSAndroid Build Coastguard Worker  elif tag == 0x0C or tag == 0x1C:
207*795d594fSAndroid Build Coastguard Worker    if tag == 0x0C:
208*795d594fSAndroid Build Coastguard Worker      print "HEAP DUMP"
209*795d594fSAndroid Build Coastguard Worker    else:
210*795d594fSAndroid Build Coastguard Worker      print "HEAP DUMP SEGMENT"
211*795d594fSAndroid Build Coastguard Worker
212*795d594fSAndroid Build Coastguard Worker    while (length > 0):
213*795d594fSAndroid Build Coastguard Worker      subtag = readu1(hprof) ; length -= 1
214*795d594fSAndroid Build Coastguard Worker      if subtag == 0xFF:
215*795d594fSAndroid Build Coastguard Worker        print " ROOT UNKNOWN"
216*795d594fSAndroid Build Coastguard Worker        objid = readID(hprof) ; length -= idsize
217*795d594fSAndroid Build Coastguard Worker      elif subtag == 0x01:
218*795d594fSAndroid Build Coastguard Worker        print " ROOT JNI GLOBAL"
219*795d594fSAndroid Build Coastguard Worker        objid = readID(hprof) ; length -= idsize
220*795d594fSAndroid Build Coastguard Worker        ref = readID(hprof) ; length -= idsize
221*795d594fSAndroid Build Coastguard Worker      elif subtag == 0x02:
222*795d594fSAndroid Build Coastguard Worker        print " ROOT JNI LOCAL"
223*795d594fSAndroid Build Coastguard Worker        objid = readID(hprof) ; length -= idsize
224*795d594fSAndroid Build Coastguard Worker        thread = readu4(hprof) ; length -= 4
225*795d594fSAndroid Build Coastguard Worker        frame = readu4(hprof) ; length -= 4
226*795d594fSAndroid Build Coastguard Worker      elif subtag == 0x03:
227*795d594fSAndroid Build Coastguard Worker        print " ROOT JAVA FRAME"
228*795d594fSAndroid Build Coastguard Worker        objid = readID(hprof) ; length -= idsize
229*795d594fSAndroid Build Coastguard Worker        serial = readu4(hprof) ; length -= 4
230*795d594fSAndroid Build Coastguard Worker        frame = readu4(hprof) ; length -= 4
231*795d594fSAndroid Build Coastguard Worker      elif subtag == 0x04:
232*795d594fSAndroid Build Coastguard Worker        objid = readID(hprof) ; length -= idsize
233*795d594fSAndroid Build Coastguard Worker        serial = readu4(hprof) ; length -= 4
234*795d594fSAndroid Build Coastguard Worker        print " ROOT NATIVE STACK serial=%d" % serial
235*795d594fSAndroid Build Coastguard Worker      elif subtag == 0x05:
236*795d594fSAndroid Build Coastguard Worker        print " ROOT STICKY CLASS"
237*795d594fSAndroid Build Coastguard Worker        objid = readID(hprof) ; length -= idsize
238*795d594fSAndroid Build Coastguard Worker      elif subtag == 0x06:
239*795d594fSAndroid Build Coastguard Worker        print " ROOT THREAD BLOCK"
240*795d594fSAndroid Build Coastguard Worker        objid = readID(hprof) ; length -= idsize
241*795d594fSAndroid Build Coastguard Worker        thread = readu4(hprof) ; length -= 4
242*795d594fSAndroid Build Coastguard Worker      elif subtag == 0x07:
243*795d594fSAndroid Build Coastguard Worker        print " ROOT MONITOR USED"
244*795d594fSAndroid Build Coastguard Worker        objid = readID(hprof) ; length -= idsize
245*795d594fSAndroid Build Coastguard Worker      elif subtag == 0x08:
246*795d594fSAndroid Build Coastguard Worker        threadid = readID(hprof) ; length -= idsize
247*795d594fSAndroid Build Coastguard Worker        serial = readu4(hprof) ; length -= 4
248*795d594fSAndroid Build Coastguard Worker        stack = readu4(hprof) ; length -= 4
249*795d594fSAndroid Build Coastguard Worker        print " ROOT THREAD OBJECT threadid=@%x serial=%d" % (threadid, serial)
250*795d594fSAndroid Build Coastguard Worker      elif subtag == 0x20:
251*795d594fSAndroid Build Coastguard Worker        print " CLASS DUMP"
252*795d594fSAndroid Build Coastguard Worker        print "  class class object ID: %s" % showclassobj(readID(hprof)) ; length -= idsize
253*795d594fSAndroid Build Coastguard Worker        print "  stack trace serial number: #%d" % readu4(hprof) ; length -= 4
254*795d594fSAndroid Build Coastguard Worker        print "  super class object ID: @%x" % readID(hprof) ; length -= idsize
255*795d594fSAndroid Build Coastguard Worker        print "  class loader object ID: @%x" % readID(hprof) ; length -= idsize
256*795d594fSAndroid Build Coastguard Worker        print "  signers object ID: @%x" % readID(hprof) ; length -= idsize
257*795d594fSAndroid Build Coastguard Worker        print "  protection domain object ID: @%x" % readID(hprof) ; length -= idsize
258*795d594fSAndroid Build Coastguard Worker        print "  reserved: @%x" % readID(hprof) ; length -= idsize
259*795d594fSAndroid Build Coastguard Worker        print "  reserved: @%x" % readID(hprof) ; length -= idsize
260*795d594fSAndroid Build Coastguard Worker        print "  instance size (in bytes): %d" % readu4(hprof) ; length -= 4
261*795d594fSAndroid Build Coastguard Worker        print "  constant pool:"
262*795d594fSAndroid Build Coastguard Worker        poolsize = readu2(hprof) ; length -= 2
263*795d594fSAndroid Build Coastguard Worker        while poolsize > 0:
264*795d594fSAndroid Build Coastguard Worker          poolsize -= 1
265*795d594fSAndroid Build Coastguard Worker          idx = readu2(hprof) ; length -= 2
266*795d594fSAndroid Build Coastguard Worker          ty = readu1(hprof) ; length -= 1
267*795d594fSAndroid Build Coastguard Worker          val = readval(ty, hprof) ; length -= valsize(ty)
268*795d594fSAndroid Build Coastguard Worker          print "   %d %s 0x%x" % (idx, showty(ty), val)
269*795d594fSAndroid Build Coastguard Worker        numstatic = readu2(hprof) ; length -= 2
270*795d594fSAndroid Build Coastguard Worker        print "  static fields:"
271*795d594fSAndroid Build Coastguard Worker        while numstatic > 0:
272*795d594fSAndroid Build Coastguard Worker          numstatic -= 1
273*795d594fSAndroid Build Coastguard Worker          nameid = readID(hprof) ; length -= idsize
274*795d594fSAndroid Build Coastguard Worker          ty = readu1(hprof) ; length -= 1
275*795d594fSAndroid Build Coastguard Worker          val = readval(ty, hprof) ; length -= valsize(ty)
276*795d594fSAndroid Build Coastguard Worker          print "   %s %s 0x%x" % (showstr(nameid), showty(ty), val)
277*795d594fSAndroid Build Coastguard Worker        numinst = readu2(hprof) ; length -= 2
278*795d594fSAndroid Build Coastguard Worker        print "  instance fields:"
279*795d594fSAndroid Build Coastguard Worker        while numinst > 0:
280*795d594fSAndroid Build Coastguard Worker          numinst -= 1
281*795d594fSAndroid Build Coastguard Worker          nameid = readID(hprof) ; length -= idsize
282*795d594fSAndroid Build Coastguard Worker          ty = readu1(hprof) ; length -= 1
283*795d594fSAndroid Build Coastguard Worker          print "   %s %s" % (showstr(nameid), showty(ty))
284*795d594fSAndroid Build Coastguard Worker      elif subtag == 0x21:
285*795d594fSAndroid Build Coastguard Worker        print " INSTANCE DUMP:"
286*795d594fSAndroid Build Coastguard Worker        print "  object ID: @%x" % readID(hprof) ; length -= idsize
287*795d594fSAndroid Build Coastguard Worker        stack = readu4(hprof) ; length -= 4
288*795d594fSAndroid Build Coastguard Worker        print "  stack: %s" % stack
289*795d594fSAndroid Build Coastguard Worker        print "  class object ID: %s" % showclassobj(readID(hprof)) ; length -= idsize
290*795d594fSAndroid Build Coastguard Worker        datalen = readu4(hprof) ; length -= 4
291*795d594fSAndroid Build Coastguard Worker        print "  %d bytes of instance data" % datalen
292*795d594fSAndroid Build Coastguard Worker        data = hprof.read(datalen) ; length -= datalen
293*795d594fSAndroid Build Coastguard Worker      elif subtag == 0x22:
294*795d594fSAndroid Build Coastguard Worker        print " OBJECT ARRAY DUMP:"
295*795d594fSAndroid Build Coastguard Worker        print "  array object ID: @%x" % readID(hprof) ; length -= idsize
296*795d594fSAndroid Build Coastguard Worker        stack = readu4(hprof) ; length -= 4
297*795d594fSAndroid Build Coastguard Worker        print "  stack: %s" % stack
298*795d594fSAndroid Build Coastguard Worker        count = readu4(hprof) ; length -= 4
299*795d594fSAndroid Build Coastguard Worker        print "  array class object ID: %s" % showclassobj(readID(hprof)) ; length -= idsize
300*795d594fSAndroid Build Coastguard Worker        hprof.read(idsize * count) ; length -= (idsize * count)
301*795d594fSAndroid Build Coastguard Worker      elif subtag == 0x23:
302*795d594fSAndroid Build Coastguard Worker        print " PRIMITIVE ARRAY DUMP:"
303*795d594fSAndroid Build Coastguard Worker        print "  array object ID: @%x" % readID(hprof) ; length -= idsize
304*795d594fSAndroid Build Coastguard Worker        stack = readu4(hprof) ; length -= 4
305*795d594fSAndroid Build Coastguard Worker        count = readu4(hprof) ; length -= 4
306*795d594fSAndroid Build Coastguard Worker        ty = readu1(hprof) ; length -= 1
307*795d594fSAndroid Build Coastguard Worker        hprof.read(valsize(ty)*count) ; length -= (valsize(ty)*count)
308*795d594fSAndroid Build Coastguard Worker      elif subtag == 0x89:
309*795d594fSAndroid Build Coastguard Worker        print " HPROF_ROOT_INTERNED_STRING"
310*795d594fSAndroid Build Coastguard Worker        objid = readID(hprof) ; length -= idsize
311*795d594fSAndroid Build Coastguard Worker      elif subtag == 0x8b:
312*795d594fSAndroid Build Coastguard Worker        objid = readID(hprof) ; length -= idsize
313*795d594fSAndroid Build Coastguard Worker        print " HPROF ROOT DEBUGGER @%x (at offset %d)" % (objid, hprof.tell() - (idsize + 1))
314*795d594fSAndroid Build Coastguard Worker      elif subtag == 0x8d:
315*795d594fSAndroid Build Coastguard Worker        objid = readID(hprof) ; length -= idsize
316*795d594fSAndroid Build Coastguard Worker        print " HPROF ROOT VM INTERNAL @%x" % objid
317*795d594fSAndroid Build Coastguard Worker      elif subtag == 0xfe:
318*795d594fSAndroid Build Coastguard Worker        hty = readu4(hprof) ; length -= 4
319*795d594fSAndroid Build Coastguard Worker        hnameid = readID(hprof) ; length -= idsize
320*795d594fSAndroid Build Coastguard Worker        print " HPROF_HEAP_DUMP_INFO %s" % showstr(hnameid)
321*795d594fSAndroid Build Coastguard Worker      else:
322*795d594fSAndroid Build Coastguard Worker        raise Exception("TODO: subtag %x" % subtag)
323*795d594fSAndroid Build Coastguard Worker  elif tag == 0x0E:
324*795d594fSAndroid Build Coastguard Worker    flags = readu4(hprof)
325*795d594fSAndroid Build Coastguard Worker    depth = readu2(hprof)
326*795d594fSAndroid Build Coastguard Worker    print "CONTROL SETTINGS %x %d" % (flags, depth)
327*795d594fSAndroid Build Coastguard Worker  elif tag == 0x2C:
328*795d594fSAndroid Build Coastguard Worker    print "HEAP DUMP END"
329*795d594fSAndroid Build Coastguard Worker  else:
330*795d594fSAndroid Build Coastguard Worker    raise Exception("TODO: TAG %x" % tag)
331*795d594fSAndroid Build Coastguard Worker
332