podman
233 строки · 6.2 Кб
1// Copyright 2019 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package goobj
6
7import (
8"bytes"
9"github.com/twitchyliquid64/golang-asm/objabi"
10"encoding/binary"
11)
12
13// CUFileIndex is used to index the filenames that are stored in the
14// per-package/per-CU FileList.
15type CUFileIndex uint32
16
17// FuncInfo is serialized as a symbol (aux symbol). The symbol data is
18// the binary encoding of the struct below.
19//
20// TODO: make each pcdata a separate symbol?
21type FuncInfo struct {
22Args uint32
23Locals uint32
24FuncID objabi.FuncID
25
26Pcsp uint32
27Pcfile uint32
28Pcline uint32
29Pcinline uint32
30Pcdata []uint32
31PcdataEnd uint32
32Funcdataoff []uint32
33File []CUFileIndex
34
35InlTree []InlTreeNode
36}
37
38func (a *FuncInfo) Write(w *bytes.Buffer) {
39var b [4]byte
40writeUint32 := func(x uint32) {
41binary.LittleEndian.PutUint32(b[:], x)
42w.Write(b[:])
43}
44
45writeUint32(a.Args)
46writeUint32(a.Locals)
47writeUint32(uint32(a.FuncID))
48
49writeUint32(a.Pcsp)
50writeUint32(a.Pcfile)
51writeUint32(a.Pcline)
52writeUint32(a.Pcinline)
53writeUint32(uint32(len(a.Pcdata)))
54for _, x := range a.Pcdata {
55writeUint32(x)
56}
57writeUint32(a.PcdataEnd)
58writeUint32(uint32(len(a.Funcdataoff)))
59for _, x := range a.Funcdataoff {
60writeUint32(x)
61}
62writeUint32(uint32(len(a.File)))
63for _, f := range a.File {
64writeUint32(uint32(f))
65}
66writeUint32(uint32(len(a.InlTree)))
67for i := range a.InlTree {
68a.InlTree[i].Write(w)
69}
70}
71
72func (a *FuncInfo) Read(b []byte) {
73readUint32 := func() uint32 {
74x := binary.LittleEndian.Uint32(b)
75b = b[4:]
76return x
77}
78
79a.Args = readUint32()
80a.Locals = readUint32()
81a.FuncID = objabi.FuncID(readUint32())
82
83a.Pcsp = readUint32()
84a.Pcfile = readUint32()
85a.Pcline = readUint32()
86a.Pcinline = readUint32()
87pcdatalen := readUint32()
88a.Pcdata = make([]uint32, pcdatalen)
89for i := range a.Pcdata {
90a.Pcdata[i] = readUint32()
91}
92a.PcdataEnd = readUint32()
93funcdataofflen := readUint32()
94a.Funcdataoff = make([]uint32, funcdataofflen)
95for i := range a.Funcdataoff {
96a.Funcdataoff[i] = readUint32()
97}
98filelen := readUint32()
99a.File = make([]CUFileIndex, filelen)
100for i := range a.File {
101a.File[i] = CUFileIndex(readUint32())
102}
103inltreelen := readUint32()
104a.InlTree = make([]InlTreeNode, inltreelen)
105for i := range a.InlTree {
106b = a.InlTree[i].Read(b)
107}
108}
109
110// FuncInfoLengths is a cache containing a roadmap of offsets and
111// lengths for things within a serialized FuncInfo. Each length field
112// stores the number of items (e.g. files, inltree nodes, etc), and the
113// corresponding "off" field stores the byte offset of the start of
114// the items in question.
115type FuncInfoLengths struct {
116NumPcdata uint32
117PcdataOff uint32
118NumFuncdataoff uint32
119FuncdataoffOff uint32
120NumFile uint32
121FileOff uint32
122NumInlTree uint32
123InlTreeOff uint32
124Initialized bool
125}
126
127func (*FuncInfo) ReadFuncInfoLengths(b []byte) FuncInfoLengths {
128var result FuncInfoLengths
129
130const numpcdataOff = 28
131result.NumPcdata = binary.LittleEndian.Uint32(b[numpcdataOff:])
132result.PcdataOff = numpcdataOff + 4
133
134numfuncdataoffOff := result.PcdataOff + 4*(result.NumPcdata+1)
135result.NumFuncdataoff = binary.LittleEndian.Uint32(b[numfuncdataoffOff:])
136result.FuncdataoffOff = numfuncdataoffOff + 4
137
138numfileOff := result.FuncdataoffOff + 4*result.NumFuncdataoff
139result.NumFile = binary.LittleEndian.Uint32(b[numfileOff:])
140result.FileOff = numfileOff + 4
141
142numinltreeOff := result.FileOff + 4*result.NumFile
143result.NumInlTree = binary.LittleEndian.Uint32(b[numinltreeOff:])
144result.InlTreeOff = numinltreeOff + 4
145
146result.Initialized = true
147
148return result
149}
150
151func (*FuncInfo) ReadArgs(b []byte) uint32 { return binary.LittleEndian.Uint32(b) }
152
153func (*FuncInfo) ReadLocals(b []byte) uint32 { return binary.LittleEndian.Uint32(b[4:]) }
154
155func (*FuncInfo) ReadFuncID(b []byte) uint32 { return binary.LittleEndian.Uint32(b[8:]) }
156
157// return start and end offsets.
158func (*FuncInfo) ReadPcsp(b []byte) (uint32, uint32) {
159return binary.LittleEndian.Uint32(b[12:]), binary.LittleEndian.Uint32(b[16:])
160}
161
162// return start and end offsets.
163func (*FuncInfo) ReadPcfile(b []byte) (uint32, uint32) {
164return binary.LittleEndian.Uint32(b[16:]), binary.LittleEndian.Uint32(b[20:])
165}
166
167// return start and end offsets.
168func (*FuncInfo) ReadPcline(b []byte) (uint32, uint32) {
169return binary.LittleEndian.Uint32(b[20:]), binary.LittleEndian.Uint32(b[24:])
170}
171
172// return start and end offsets.
173func (*FuncInfo) ReadPcinline(b []byte, pcdataoffset uint32) (uint32, uint32) {
174return binary.LittleEndian.Uint32(b[24:]), binary.LittleEndian.Uint32(b[pcdataoffset:])
175}
176
177// return start and end offsets.
178func (*FuncInfo) ReadPcdata(b []byte, pcdataoffset uint32, k uint32) (uint32, uint32) {
179return binary.LittleEndian.Uint32(b[pcdataoffset+4*k:]), binary.LittleEndian.Uint32(b[pcdataoffset+4+4*k:])
180}
181
182func (*FuncInfo) ReadFuncdataoff(b []byte, funcdataofffoff uint32, k uint32) int64 {
183return int64(binary.LittleEndian.Uint32(b[funcdataofffoff+4*k:]))
184}
185
186func (*FuncInfo) ReadFile(b []byte, filesoff uint32, k uint32) CUFileIndex {
187return CUFileIndex(binary.LittleEndian.Uint32(b[filesoff+4*k:]))
188}
189
190func (*FuncInfo) ReadInlTree(b []byte, inltreeoff uint32, k uint32) InlTreeNode {
191const inlTreeNodeSize = 4 * 6
192var result InlTreeNode
193result.Read(b[inltreeoff+k*inlTreeNodeSize:])
194return result
195}
196
197// InlTreeNode is the serialized form of FileInfo.InlTree.
198type InlTreeNode struct {
199Parent int32
200File CUFileIndex
201Line int32
202Func SymRef
203ParentPC int32
204}
205
206func (inl *InlTreeNode) Write(w *bytes.Buffer) {
207var b [4]byte
208writeUint32 := func(x uint32) {
209binary.LittleEndian.PutUint32(b[:], x)
210w.Write(b[:])
211}
212writeUint32(uint32(inl.Parent))
213writeUint32(uint32(inl.File))
214writeUint32(uint32(inl.Line))
215writeUint32(inl.Func.PkgIdx)
216writeUint32(inl.Func.SymIdx)
217writeUint32(uint32(inl.ParentPC))
218}
219
220// Read an InlTreeNode from b, return the remaining bytes.
221func (inl *InlTreeNode) Read(b []byte) []byte {
222readUint32 := func() uint32 {
223x := binary.LittleEndian.Uint32(b)
224b = b[4:]
225return x
226}
227inl.Parent = int32(readUint32())
228inl.File = CUFileIndex(readUint32())
229inl.Line = int32(readUint32())
230inl.Func = SymRef{readUint32(), readUint32()}
231inl.ParentPC = int32(readUint32())
232return b
233}
234