github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/internal/goobj2/funcinfo.go (about)

     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 goobj2
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/binary"
    10  )
    11  
    12  // FuncInfo is serialized as a symbol (aux symbol). The symbol data is
    13  // the binary encoding of the struct below.
    14  //
    15  // TODO: make each pcdata a separate symbol?
    16  type FuncInfo struct {
    17  	NoSplit uint8
    18  
    19  	Args   uint32
    20  	Locals uint32
    21  
    22  	Pcsp        uint32
    23  	Pcfile      uint32
    24  	Pcline      uint32
    25  	Pcinline    uint32
    26  	Pcdata      []uint32
    27  	PcdataEnd   uint32
    28  	Funcdataoff []uint32
    29  	File        []SymRef // TODO: just use string?
    30  
    31  	InlTree []InlTreeNode
    32  }
    33  
    34  func (a *FuncInfo) Write(w *bytes.Buffer) {
    35  	w.WriteByte(a.NoSplit)
    36  
    37  	var b [4]byte
    38  	writeUint32 := func(x uint32) {
    39  		binary.LittleEndian.PutUint32(b[:], x)
    40  		w.Write(b[:])
    41  	}
    42  
    43  	writeUint32(a.Args)
    44  	writeUint32(a.Locals)
    45  
    46  	writeUint32(a.Pcsp)
    47  	writeUint32(a.Pcfile)
    48  	writeUint32(a.Pcline)
    49  	writeUint32(a.Pcinline)
    50  	writeUint32(uint32(len(a.Pcdata)))
    51  	for _, x := range a.Pcdata {
    52  		writeUint32(x)
    53  	}
    54  	writeUint32(a.PcdataEnd)
    55  	writeUint32(uint32(len(a.Funcdataoff)))
    56  	for _, x := range a.Funcdataoff {
    57  		writeUint32(x)
    58  	}
    59  	writeUint32(uint32(len(a.File)))
    60  	for _, f := range a.File {
    61  		writeUint32(f.PkgIdx)
    62  		writeUint32(f.SymIdx)
    63  	}
    64  	writeUint32(uint32(len(a.InlTree)))
    65  	for i := range a.InlTree {
    66  		a.InlTree[i].Write(w)
    67  	}
    68  }
    69  
    70  func (a *FuncInfo) Read(b []byte) {
    71  	a.NoSplit = b[0]
    72  	b = b[1:]
    73  
    74  	readUint32 := func() uint32 {
    75  		x := binary.LittleEndian.Uint32(b)
    76  		b = b[4:]
    77  		return x
    78  	}
    79  
    80  	a.Args = readUint32()
    81  	a.Locals = 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([]SymRef, filelen)
   100  	for i := range a.File {
   101  		a.File[i] = SymRef{readUint32(), 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  // InlTreeNode is the serialized form of FileInfo.InlTree.
   111  type InlTreeNode struct {
   112  	Parent   int32
   113  	File     SymRef
   114  	Line     int32
   115  	Func     SymRef
   116  	ParentPC int32
   117  }
   118  
   119  func (inl *InlTreeNode) Write(w *bytes.Buffer) {
   120  	var b [4]byte
   121  	writeUint32 := func(x uint32) {
   122  		binary.LittleEndian.PutUint32(b[:], x)
   123  		w.Write(b[:])
   124  	}
   125  	writeUint32(uint32(inl.Parent))
   126  	writeUint32(inl.File.PkgIdx)
   127  	writeUint32(inl.File.SymIdx)
   128  	writeUint32(uint32(inl.Line))
   129  	writeUint32(inl.Func.PkgIdx)
   130  	writeUint32(inl.Func.SymIdx)
   131  	writeUint32(uint32(inl.ParentPC))
   132  }
   133  
   134  // Read an InlTreeNode from b, return the remaining bytes.
   135  func (inl *InlTreeNode) Read(b []byte) []byte {
   136  	readUint32 := func() uint32 {
   137  		x := binary.LittleEndian.Uint32(b)
   138  		b = b[4:]
   139  		return x
   140  	}
   141  	inl.Parent = int32(readUint32())
   142  	inl.File = SymRef{readUint32(), readUint32()}
   143  	inl.Line = int32(readUint32())
   144  	inl.Func = SymRef{readUint32(), readUint32()}
   145  	inl.ParentPC = int32(readUint32())
   146  	return b
   147  }