...
1
2
3
4
5 package goobj
6
7 import (
8 "bytes"
9 "github.com/twitchyliquid64/golang-asm/objabi"
10 "encoding/binary"
11 )
12
13
14
15 type CUFileIndex uint32
16
17
18
19
20
21 type FuncInfo struct {
22 Args uint32
23 Locals uint32
24 FuncID objabi.FuncID
25
26 Pcsp uint32
27 Pcfile uint32
28 Pcline uint32
29 Pcinline uint32
30 Pcdata []uint32
31 PcdataEnd uint32
32 Funcdataoff []uint32
33 File []CUFileIndex
34
35 InlTree []InlTreeNode
36 }
37
38 func (a *FuncInfo) Write(w *bytes.Buffer) {
39 var b [4]byte
40 writeUint32 := func(x uint32) {
41 binary.LittleEndian.PutUint32(b[:], x)
42 w.Write(b[:])
43 }
44
45 writeUint32(a.Args)
46 writeUint32(a.Locals)
47 writeUint32(uint32(a.FuncID))
48
49 writeUint32(a.Pcsp)
50 writeUint32(a.Pcfile)
51 writeUint32(a.Pcline)
52 writeUint32(a.Pcinline)
53 writeUint32(uint32(len(a.Pcdata)))
54 for _, x := range a.Pcdata {
55 writeUint32(x)
56 }
57 writeUint32(a.PcdataEnd)
58 writeUint32(uint32(len(a.Funcdataoff)))
59 for _, x := range a.Funcdataoff {
60 writeUint32(x)
61 }
62 writeUint32(uint32(len(a.File)))
63 for _, f := range a.File {
64 writeUint32(uint32(f))
65 }
66 writeUint32(uint32(len(a.InlTree)))
67 for i := range a.InlTree {
68 a.InlTree[i].Write(w)
69 }
70 }
71
72 func (a *FuncInfo) Read(b []byte) {
73 readUint32 := func() uint32 {
74 x := binary.LittleEndian.Uint32(b)
75 b = b[4:]
76 return x
77 }
78
79 a.Args = readUint32()
80 a.Locals = readUint32()
81 a.FuncID = objabi.FuncID(readUint32())
82
83 a.Pcsp = readUint32()
84 a.Pcfile = readUint32()
85 a.Pcline = readUint32()
86 a.Pcinline = readUint32()
87 pcdatalen := readUint32()
88 a.Pcdata = make([]uint32, pcdatalen)
89 for i := range a.Pcdata {
90 a.Pcdata[i] = readUint32()
91 }
92 a.PcdataEnd = readUint32()
93 funcdataofflen := readUint32()
94 a.Funcdataoff = make([]uint32, funcdataofflen)
95 for i := range a.Funcdataoff {
96 a.Funcdataoff[i] = readUint32()
97 }
98 filelen := readUint32()
99 a.File = make([]CUFileIndex, filelen)
100 for i := range a.File {
101 a.File[i] = CUFileIndex(readUint32())
102 }
103 inltreelen := readUint32()
104 a.InlTree = make([]InlTreeNode, inltreelen)
105 for i := range a.InlTree {
106 b = a.InlTree[i].Read(b)
107 }
108 }
109
110
111
112
113
114
115 type FuncInfoLengths struct {
116 NumPcdata uint32
117 PcdataOff uint32
118 NumFuncdataoff uint32
119 FuncdataoffOff uint32
120 NumFile uint32
121 FileOff uint32
122 NumInlTree uint32
123 InlTreeOff uint32
124 Initialized bool
125 }
126
127 func (*FuncInfo) ReadFuncInfoLengths(b []byte) FuncInfoLengths {
128 var result FuncInfoLengths
129
130 const numpcdataOff = 28
131 result.NumPcdata = binary.LittleEndian.Uint32(b[numpcdataOff:])
132 result.PcdataOff = numpcdataOff + 4
133
134 numfuncdataoffOff := result.PcdataOff + 4*(result.NumPcdata+1)
135 result.NumFuncdataoff = binary.LittleEndian.Uint32(b[numfuncdataoffOff:])
136 result.FuncdataoffOff = numfuncdataoffOff + 4
137
138 numfileOff := result.FuncdataoffOff + 4*result.NumFuncdataoff
139 result.NumFile = binary.LittleEndian.Uint32(b[numfileOff:])
140 result.FileOff = numfileOff + 4
141
142 numinltreeOff := result.FileOff + 4*result.NumFile
143 result.NumInlTree = binary.LittleEndian.Uint32(b[numinltreeOff:])
144 result.InlTreeOff = numinltreeOff + 4
145
146 result.Initialized = true
147
148 return result
149 }
150
151 func (*FuncInfo) ReadArgs(b []byte) uint32 { return binary.LittleEndian.Uint32(b) }
152
153 func (*FuncInfo) ReadLocals(b []byte) uint32 { return binary.LittleEndian.Uint32(b[4:]) }
154
155 func (*FuncInfo) ReadFuncID(b []byte) uint32 { return binary.LittleEndian.Uint32(b[8:]) }
156
157
158 func (*FuncInfo) ReadPcsp(b []byte) (uint32, uint32) {
159 return binary.LittleEndian.Uint32(b[12:]), binary.LittleEndian.Uint32(b[16:])
160 }
161
162
163 func (*FuncInfo) ReadPcfile(b []byte) (uint32, uint32) {
164 return binary.LittleEndian.Uint32(b[16:]), binary.LittleEndian.Uint32(b[20:])
165 }
166
167
168 func (*FuncInfo) ReadPcline(b []byte) (uint32, uint32) {
169 return binary.LittleEndian.Uint32(b[20:]), binary.LittleEndian.Uint32(b[24:])
170 }
171
172
173 func (*FuncInfo) ReadPcinline(b []byte, pcdataoffset uint32) (uint32, uint32) {
174 return binary.LittleEndian.Uint32(b[24:]), binary.LittleEndian.Uint32(b[pcdataoffset:])
175 }
176
177
178 func (*FuncInfo) ReadPcdata(b []byte, pcdataoffset uint32, k uint32) (uint32, uint32) {
179 return binary.LittleEndian.Uint32(b[pcdataoffset+4*k:]), binary.LittleEndian.Uint32(b[pcdataoffset+4+4*k:])
180 }
181
182 func (*FuncInfo) ReadFuncdataoff(b []byte, funcdataofffoff uint32, k uint32) int64 {
183 return int64(binary.LittleEndian.Uint32(b[funcdataofffoff+4*k:]))
184 }
185
186 func (*FuncInfo) ReadFile(b []byte, filesoff uint32, k uint32) CUFileIndex {
187 return CUFileIndex(binary.LittleEndian.Uint32(b[filesoff+4*k:]))
188 }
189
190 func (*FuncInfo) ReadInlTree(b []byte, inltreeoff uint32, k uint32) InlTreeNode {
191 const inlTreeNodeSize = 4 * 6
192 var result InlTreeNode
193 result.Read(b[inltreeoff+k*inlTreeNodeSize:])
194 return result
195 }
196
197
198 type InlTreeNode struct {
199 Parent int32
200 File CUFileIndex
201 Line int32
202 Func SymRef
203 ParentPC int32
204 }
205
206 func (inl *InlTreeNode) Write(w *bytes.Buffer) {
207 var b [4]byte
208 writeUint32 := func(x uint32) {
209 binary.LittleEndian.PutUint32(b[:], x)
210 w.Write(b[:])
211 }
212 writeUint32(uint32(inl.Parent))
213 writeUint32(uint32(inl.File))
214 writeUint32(uint32(inl.Line))
215 writeUint32(inl.Func.PkgIdx)
216 writeUint32(inl.Func.SymIdx)
217 writeUint32(uint32(inl.ParentPC))
218 }
219
220
221 func (inl *InlTreeNode) Read(b []byte) []byte {
222 readUint32 := func() uint32 {
223 x := binary.LittleEndian.Uint32(b)
224 b = b[4:]
225 return x
226 }
227 inl.Parent = int32(readUint32())
228 inl.File = CUFileIndex(readUint32())
229 inl.Line = int32(readUint32())
230 inl.Func = SymRef{readUint32(), readUint32()}
231 inl.ParentPC = int32(readUint32())
232 return b
233 }
234
View as plain text