[dev.link] add compilation unit index to func

Not used yet, but add the compilation unit for a function to func.

Change-Id: I7c43fa9f1da044ca63bab030062519771b9f4418
Reviewed-on: https://go-review.googlesource.com/c/go/+/244547
Run-TryBot: Jeremy Faller <jeremy@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Jeremy Faller 2020-07-23 15:15:26 -04:00
parent 89cf569a45
commit e4e1c6a7af
3 changed files with 42 additions and 14 deletions

View file

@ -14,6 +14,7 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"log" "log"
"math"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -96,8 +97,9 @@ func makeOldPclnState(ctxt *Link) *oldPclnState {
return state return state
} }
// makePclntab makes a pclntab object. // makePclntab makes a pclntab object, and assembles all the compilation units
func makePclntab(ctxt *Link, container loader.Bitmap) *pclntab { // we'll need to write pclntab.
func makePclntab(ctxt *Link, container loader.Bitmap) (*pclntab, []*sym.CompilationUnit) {
ldr := ctxt.loader ldr := ctxt.loader
state := &pclntab{ state := &pclntab{
@ -105,7 +107,10 @@ func makePclntab(ctxt *Link, container loader.Bitmap) *pclntab {
} }
// Gather some basic stats and info. // Gather some basic stats and info.
seenCUs := make(map[*sym.CompilationUnit]struct{})
prevSect := ldr.SymSect(ctxt.Textp[0]) prevSect := ldr.SymSect(ctxt.Textp[0])
compUnits := []*sym.CompilationUnit{}
for _, s := range ctxt.Textp { for _, s := range ctxt.Textp {
if !emitPcln(ctxt, s, container) { if !emitPcln(ctxt, s, container) {
continue continue
@ -125,8 +130,17 @@ func makePclntab(ctxt *Link, container loader.Bitmap) *pclntab {
state.nfunc++ state.nfunc++
prevSect = ss prevSect = ss
} }
// We need to keep track of all compilation units we see. Some symbols
// (eg, go.buildid, _cgoexp_, etc) won't have a compilation unit.
cu := ldr.SymUnit(s)
if _, ok := seenCUs[cu]; cu != nil && !ok {
seenCUs[cu] = struct{}{}
cu.PclnIndex = len(compUnits)
compUnits = append(compUnits, cu)
} }
return state }
return state, compUnits
} }
func ftabaddstring(ftab *loader.SymbolBuilder, s string) int32 { func ftabaddstring(ftab *loader.SymbolBuilder, s string) int32 {
@ -425,7 +439,7 @@ func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab {
// filetable // filetable
oldState := makeOldPclnState(ctxt) oldState := makeOldPclnState(ctxt)
state := makePclntab(ctxt, container) state, _ := makePclntab(ctxt, container)
ldr := ctxt.loader ldr := ctxt.loader
state.carrier = ldr.LookupOrCreateSym("runtime.pclntab", 0) state.carrier = ldr.LookupOrCreateSym("runtime.pclntab", 0)
@ -434,7 +448,7 @@ func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab {
// runtime.pclntab_old is just a placeholder,and will eventually be deleted. // runtime.pclntab_old is just a placeholder,and will eventually be deleted.
// It contains the pieces of runtime.pclntab that haven't moved to a more // It contains the pieces of runtime.pclntab that haven't moved to a more
// ration form. // rational form.
state.pclntab = ldr.LookupOrCreateSym("runtime.pclntab_old", 0) state.pclntab = ldr.LookupOrCreateSym("runtime.pclntab_old", 0)
state.generatePCHeader(ctxt) state.generatePCHeader(ctxt)
state.generateFuncnametab(ctxt, container) state.generateFuncnametab(ctxt, container)
@ -616,6 +630,16 @@ func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab {
off = writepctab(off, pcline.P) off = writepctab(off, pcline.P)
off = int32(ftab.SetUint32(ctxt.Arch, int64(off), uint32(len(pcdata)))) off = int32(ftab.SetUint32(ctxt.Arch, int64(off), uint32(len(pcdata))))
// Store the compilation unit index.
cuIdx := ^uint16(0)
if cu := ldr.SymUnit(s); cu != nil {
if cu.PclnIndex > math.MaxUint16 {
panic("cu limit reached.")
}
cuIdx = uint16(cu.PclnIndex)
}
off = int32(ftab.SetUint16(ctxt.Arch, int64(off), cuIdx))
// funcID uint8 // funcID uint8
var funcID objabi.FuncID var funcID objabi.FuncID
if fi.Valid() { if fi.Valid() {
@ -623,9 +647,6 @@ func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab {
} }
off = int32(ftab.SetUint8(ctxt.Arch, int64(off), uint8(funcID))) off = int32(ftab.SetUint8(ctxt.Arch, int64(off), uint8(funcID)))
// unused
off += 2
// nfuncdata must be the final entry. // nfuncdata must be the final entry.
off = int32(ftab.SetUint8(ctxt.Arch, int64(off), uint8(len(funcdata)))) off = int32(ftab.SetUint8(ctxt.Arch, int64(off), uint8(len(funcdata))))
for i := range pcdata { for i := range pcdata {

View file

@ -10,12 +10,19 @@ import "cmd/internal/dwarf"
// type from the sym package since loader imports sym. // type from the sym package since loader imports sym.
type LoaderSym int type LoaderSym int
// CompilationUnit is an abstraction used by DWARF to represent a chunk of // A CompilationUnit represents a set of source files that are compiled
// debug-related data. We create a CompilationUnit per Object file in a // together. Since all Go sources in a Go package are compiled together,
// library (so, one for all the Go code, one for each assembly file, etc.). // there's one CompilationUnit per package that represents all Go sources in
// that package, plus one for each assembly file.
//
// Equivalently, there's one CompilationUnit per object file in each Library
// loaded by the linker.
//
// These are used for both DWARF and pclntab generation.
type CompilationUnit struct { type CompilationUnit struct {
Pkg string // The package name, eg ("fmt", or "runtime") Pkg string // The package name, eg ("fmt", or "runtime")
Lib *Library // Our library Lib *Library // Our library
PclnIndex int // Index of this CU in pclntab
PCs []dwarf.Range // PC ranges, relative to Textp[0] PCs []dwarf.Range // PC ranges, relative to Textp[0]
DWInfo *dwarf.DWDie // CU root DIE DWInfo *dwarf.DWDie // CU root DIE
DWARFFileTable []string // The file table used to generate the .debug_lines DWARFFileTable []string // The file table used to generate the .debug_lines

View file

@ -804,8 +804,8 @@ type _func struct {
pcfile int32 pcfile int32
pcln int32 pcln int32
npcdata int32 npcdata int32
cuIndex uint16 // TODO(jfaller): 16 bits is never enough, make this larger.
funcID funcID // set for certain special runtime functions funcID funcID // set for certain special runtime functions
_ [2]int8 // unused
nfuncdata uint8 // must be last nfuncdata uint8 // must be last
} }