-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathHeapDumpParse.py
111 lines (93 loc) · 3.4 KB
/
HeapDumpParse.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/usr/bin/python
import socket,struct,sys
from hash import backtrace_element
from Print import printDebug,printError
def printInfo(size,allocations,backtraces):
#Allocations: 3
#Size: 3456000
#TotalSize: 10368000
#BeginStacktrace:
print("Allocations: {0}".format(allocations))
print("Size: {0}".format(size))
print("TotalSize: {0}".format(allocations * size))
print("BeginStacktrace:")
for backtrace in backtraces:
print("{0:08x}".format(backtrace))
print("EndStacktrace:")
print("")
SIZE_FLAG_ZYGOTE_CHILD = 1 << 31
class MemInfoEntry(object):
def __hash__(self):
ret = self.size << 16 | hash(self.backtraces)
return ret
def __eq__(self,other):
#if not isinstance(other,MemInfoEntry):
# return False
if(self.size != other.size):
return False
return self.backtraces == other.backtraces
def __init__(self,size,allocations,backtraces):
self.size = size
self.allocations = allocations
self.backtraces = backtrace_element(backtraces)
class Parser(object):
def __init__(self):
self.outData = []
def genInfo(self,size,allocations,backtraces):
self.outData.append(MemInfoEntry(size,allocations,backtraces))
def printEntry(self,buf,offset,infoSize):
if len(buf) - offset < infoSize:
printDebug("the buffer is too small! exit!")
return len(buf)
endOffset = offset + infoSize
size = struct.unpack_from("<I",buf,offset)[0]
if size & SIZE_FLAG_ZYGOTE_CHILD:
size = size & ~SIZE_FLAG_ZYGOTE_CHILD
offset = offset + 4
allocations = struct.unpack_from("<I",buf,offset)[0]
offset = offset + 4
backtraces = []
while offset < endOffset:
backtrace = struct.unpack_from("<I",buf,offset)[0]
offset = offset + 4
backtraces.append(backtrace)
self.genInfo(size,allocations,backtraces)
return offset
def handleBuf(self,buf):
printDebug("buf length is {0}".format(len(buf)))
offset = 0
overallSize = struct.unpack_from("<i",buf,offset)[0]
offset = offset + 4
infoSize = struct.unpack_from("<i",buf,offset)[0]
offset = offset + 4
totalMemory = struct.unpack_from("<i",buf,offset)[0]
offset = offset + 4
backtraceSize = struct.unpack_from("<i",buf,offset)[0]
offset = offset + 4
printDebug("overallSize = {0};infoSize = {1},totalMemory = {2},backtraceSize = {3}".format(overallSize,infoSize,totalMemory,backtraceSize))
meminfoSize = overallSize + 4 * 4
while offset < meminfoSize:
offset = self.printEntry(buf,offset,infoSize)
def parse(self,fileName = None):
expr = None
if fileName :
f = open(fileName,"rb")
expr = lambda x : f.read(x)
else:
mysocket = socket.create_connection(("127.0.0.1",3244))
expr = lambda x : mysocket.recv(x)
buf = []
while True:
buf2 = expr(4096*1024)
if not len(buf2):
break
buf.append(buf2)
self.handleBuf("".join(buf))
if __name__ == '__main__':
fileName = None
if len(sys.argv) > 1:
fileName = sys.argv[1]
p = Parser()
p.parse(fileName)
for e in p.outData:
printInfo(e.size,e.allocations,e.backtraces._backtraces)