gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

funcinfo.go (6386B)


      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 
      5 package goobj
      6 
      7 import (
      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.
     15 type 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?
     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 // 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.
    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 // return start and end offsets.
    158 func (*FuncInfo) ReadPcsp(b []byte) (uint32, uint32) {
    159 	return binary.LittleEndian.Uint32(b[12:]), binary.LittleEndian.Uint32(b[16:])
    160 }
    161 
    162 // return start and end offsets.
    163 func (*FuncInfo) ReadPcfile(b []byte) (uint32, uint32) {
    164 	return binary.LittleEndian.Uint32(b[16:]), binary.LittleEndian.Uint32(b[20:])
    165 }
    166 
    167 // return start and end offsets.
    168 func (*FuncInfo) ReadPcline(b []byte) (uint32, uint32) {
    169 	return binary.LittleEndian.Uint32(b[20:]), binary.LittleEndian.Uint32(b[24:])
    170 }
    171 
    172 // return start and end offsets.
    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 // return start and end offsets.
    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 // InlTreeNode is the serialized form of FileInfo.InlTree.
    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 // Read an InlTreeNode from b, return the remaining bytes.
    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 }