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

View as plain text