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