...

Source file src/github.com/twitchyliquid64/golang-asm/goobj/funcinfo.go

Documentation: github.com/twitchyliquid64/golang-asm/goobj

     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  }
   234  

View as plain text