Source file src/cmd/internal/goobj/funcinfo.go

     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  	"encoding/binary"
    10  	"internal/abi"
    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  type FuncInfo struct {
    20  	Args      uint32
    21  	Locals    uint32
    22  	FuncID    abi.FuncID
    23  	FuncFlag  abi.FuncFlag
    24  	StartLine int32
    25  	File      []CUFileIndex
    26  	InlTree   []InlTreeNode
    27  }
    28  
    29  func (a *FuncInfo) Write(w *bytes.Buffer) {
    30  	writeUint8 := func(x uint8) {
    31  		w.WriteByte(x)
    32  	}
    33  	var b [4]byte
    34  	writeUint32 := func(x uint32) {
    35  		binary.LittleEndian.PutUint32(b[:], x)
    36  		w.Write(b[:])
    37  	}
    38  
    39  	writeUint32(a.Args)
    40  	writeUint32(a.Locals)
    41  	writeUint8(uint8(a.FuncID))
    42  	writeUint8(uint8(a.FuncFlag))
    43  	writeUint8(0) // pad to uint32 boundary
    44  	writeUint8(0)
    45  	writeUint32(uint32(a.StartLine))
    46  
    47  	writeUint32(uint32(len(a.File)))
    48  	for _, f := range a.File {
    49  		writeUint32(uint32(f))
    50  	}
    51  	writeUint32(uint32(len(a.InlTree)))
    52  	for i := range a.InlTree {
    53  		a.InlTree[i].Write(w)
    54  	}
    55  }
    56  
    57  // FuncInfoLengths is a cache containing a roadmap of offsets and
    58  // lengths for things within a serialized FuncInfo. Each length field
    59  // stores the number of items (e.g. files, inltree nodes, etc), and the
    60  // corresponding "off" field stores the byte offset of the start of
    61  // the items in question.
    62  type FuncInfoLengths struct {
    63  	NumFile     uint32
    64  	FileOff     uint32
    65  	NumInlTree  uint32
    66  	InlTreeOff  uint32
    67  	Initialized bool
    68  }
    69  
    70  func (*FuncInfo) ReadFuncInfoLengths(b []byte) FuncInfoLengths {
    71  	var result FuncInfoLengths
    72  
    73  	// Offset to the number of the file table. This value is determined by counting
    74  	// the number of bytes until we write funcdataoff to the file.
    75  	const numfileOff = 16
    76  	result.NumFile = binary.LittleEndian.Uint32(b[numfileOff:])
    77  	result.FileOff = numfileOff + 4
    78  
    79  	numinltreeOff := result.FileOff + 4*result.NumFile
    80  	result.NumInlTree = binary.LittleEndian.Uint32(b[numinltreeOff:])
    81  	result.InlTreeOff = numinltreeOff + 4
    82  
    83  	result.Initialized = true
    84  
    85  	return result
    86  }
    87  
    88  func (*FuncInfo) ReadArgs(b []byte) uint32 { return binary.LittleEndian.Uint32(b) }
    89  
    90  func (*FuncInfo) ReadLocals(b []byte) uint32 { return binary.LittleEndian.Uint32(b[4:]) }
    91  
    92  func (*FuncInfo) ReadFuncID(b []byte) abi.FuncID { return abi.FuncID(b[8]) }
    93  
    94  func (*FuncInfo) ReadFuncFlag(b []byte) abi.FuncFlag { return abi.FuncFlag(b[9]) }
    95  
    96  func (*FuncInfo) ReadStartLine(b []byte) int32 { return int32(binary.LittleEndian.Uint32(b[12:])) }
    97  
    98  func (*FuncInfo) ReadFile(b []byte, filesoff uint32, k uint32) CUFileIndex {
    99  	return CUFileIndex(binary.LittleEndian.Uint32(b[filesoff+4*k:]))
   100  }
   101  
   102  func (*FuncInfo) ReadInlTree(b []byte, inltreeoff uint32, k uint32) InlTreeNode {
   103  	const inlTreeNodeSize = 4 * 6
   104  	var result InlTreeNode
   105  	result.Read(b[inltreeoff+k*inlTreeNodeSize:])
   106  	return result
   107  }
   108  
   109  // InlTreeNode is the serialized form of FileInfo.InlTree.
   110  type InlTreeNode struct {
   111  	Parent   int32
   112  	File     CUFileIndex
   113  	Line     int32
   114  	Func     SymRef
   115  	ParentPC int32
   116  }
   117  
   118  func (inl *InlTreeNode) Write(w *bytes.Buffer) {
   119  	var b [4]byte
   120  	writeUint32 := func(x uint32) {
   121  		binary.LittleEndian.PutUint32(b[:], x)
   122  		w.Write(b[:])
   123  	}
   124  	writeUint32(uint32(inl.Parent))
   125  	writeUint32(uint32(inl.File))
   126  	writeUint32(uint32(inl.Line))
   127  	writeUint32(inl.Func.PkgIdx)
   128  	writeUint32(inl.Func.SymIdx)
   129  	writeUint32(uint32(inl.ParentPC))
   130  }
   131  
   132  // Read an InlTreeNode from b, return the remaining bytes.
   133  func (inl *InlTreeNode) Read(b []byte) []byte {
   134  	readUint32 := func() uint32 {
   135  		x := binary.LittleEndian.Uint32(b)
   136  		b = b[4:]
   137  		return x
   138  	}
   139  	inl.Parent = int32(readUint32())
   140  	inl.File = CUFileIndex(readUint32())
   141  	inl.Line = int32(readUint32())
   142  	inl.Func = SymRef{readUint32(), readUint32()}
   143  	inl.ParentPC = int32(readUint32())
   144  	return b
   145  }
   146  

View as plain text