-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathparse.go
132 lines (110 loc) · 2.66 KB
/
parse.go
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package heaputil
import (
"bufio"
"fmt"
"github.com/burntcarrot/heaputil/record"
)
type RecordData struct {
RecordType record.RecordType
Repr string
HasPointers bool
RowID string
Pointers []PointerData
}
type PointerData struct {
Index int
Address string
Incoming string
Outgoing string
}
func ParseDump(rd *bufio.Reader) ([]RecordData, error) {
err := record.ReadHeader(rd)
if err != nil {
return nil, err
}
var dumpParams *record.DumpParamsRecord
records := []RecordData{}
for {
r, err := record.ReadRecord(rd)
if err != nil {
return nil, err
}
_, isEOF := r.(*record.EOFRecord)
if isEOF {
break
}
dp, isDumpParams := r.(*record.DumpParamsRecord)
if isDumpParams {
dumpParams = dp
}
recordInfo := RecordData{
RecordType: record.GetRecordType(r),
Repr: r.Repr(),
}
p, isParent := r.(record.ParentGuard)
if isParent {
incoming, outgoing := record.ParsePointers(p, dumpParams)
for i := 0; i < len(outgoing); i++ {
if outgoing[i] != 0 {
a, hasAddress := r.(record.AddressGuard)
if hasAddress {
address := a.GetAddress() + p.GetFields()[i]
pointerInfo := PointerData{
Index: i,
Address: fmt.Sprintf("%x", address),
Incoming: fmt.Sprintf("%x", incoming[i]),
Outgoing: fmt.Sprintf("%x", outgoing[i]),
}
recordInfo.Pointers = append(recordInfo.Pointers, pointerInfo)
recordInfo.HasPointers = true
}
}
}
}
recordInfo.RowID = fmt.Sprintf("row%d", len(records)+1)
records = append(records, recordInfo)
}
return records, nil
}
// PrintDump prints the heap dump information to stdout.
// CAUTION: can be too verbose!
func PrintDump(rd *bufio.Reader) error {
err := record.ReadHeader(rd)
if err != nil {
return err
}
var dumpParams *record.DumpParamsRecord
for {
r, err := record.ReadRecord(rd)
if err != nil {
return err
}
_, isEOF := r.(*record.EOFRecord)
if isEOF {
break
}
dp, isDumpParams := r.(*record.DumpParamsRecord)
if isDumpParams {
dumpParams = dp
}
// Print pointer information.
p, isParent := r.(record.ParentGuard)
if isParent {
incoming, outgoing := record.ParsePointers(p, dumpParams)
for i := 0; i < len(outgoing); i++ {
// If outgoing (destination) is valid, then print it.
if outgoing[i] != 0 {
a, hasAddress := r.(record.AddressGuard)
if hasAddress {
address := a.GetAddress() + p.GetFields()[i]
format := "\tPointer(#%d) at address 0x%x (incoming = 0x%x, outgoing = 0x%x)\n"
fmt.Printf(format, i, address, incoming[i], outgoing[i])
}
}
}
}
// Display record.
fmt.Println(r.Repr())
}
return nil
}