mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.link] use per package filenames to build pclntab
In order to prevent renumbering of filenames in pclntab generation, use the per-package file list (previously only used for DWARF generation) as file-indices. This is the largest step to eliminate renumbering of filenames in pclntab. Note, this is probably not the final state of the file table within the object file. In this form, the linker loads all filenames for all objects. I'll move to storing the filenames as regular string symbols,and defaulting all string symbols to using the larger hash value to make generation of pcln simplest, and most memory friendly. Change-Id: I23daafa3f4b4535076e23100200ae0e7163aafe0 Reviewed-on: https://go-review.googlesource.com/c/go/+/245485 Run-TryBot: Jeremy Faller <jeremy@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
This commit is contained in:
parent
8370cbe64d
commit
9bdaf99966
16 changed files with 126 additions and 143 deletions
|
|
@ -107,7 +107,7 @@ type Func struct {
|
||||||
PCInline Data // PC → inline tree index map
|
PCInline Data // PC → inline tree index map
|
||||||
PCData []Data // PC → runtime support data map
|
PCData []Data // PC → runtime support data map
|
||||||
FuncData []FuncData // non-PC-specific runtime support data
|
FuncData []FuncData // non-PC-specific runtime support data
|
||||||
File []string // paths indexed by PCFile
|
File map[goobj2.CUFileIndex]struct{} // set of files used in this function
|
||||||
InlTree []InlinedCall
|
InlTree []InlinedCall
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,7 +123,7 @@ type FuncData struct {
|
||||||
// See cmd/internal/obj.InlTree for details.
|
// See cmd/internal/obj.InlTree for details.
|
||||||
type InlinedCall struct {
|
type InlinedCall struct {
|
||||||
Parent int64
|
Parent int64
|
||||||
File string
|
File goobj2.CUFileIndex
|
||||||
Line int64
|
Line int64
|
||||||
Func SymID
|
Func SymID
|
||||||
ParentPC int64
|
ParentPC int64
|
||||||
|
|
@ -138,7 +138,7 @@ type Package struct {
|
||||||
MaxVersion int64 // maximum Version in any SymID in Syms
|
MaxVersion int64 // maximum Version in any SymID in Syms
|
||||||
Arch string // architecture
|
Arch string // architecture
|
||||||
Native []*NativeReader // native object data (e.g. ELF)
|
Native []*NativeReader // native object data (e.g. ELF)
|
||||||
DWARFFileList []string // List of files for the DWARF .debug_lines section
|
FileList []string // List of files for this package.
|
||||||
}
|
}
|
||||||
|
|
||||||
type NativeReader struct {
|
type NativeReader struct {
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,12 @@ func (r *objReader) readNew() {
|
||||||
|
|
||||||
// Read things for the current goobj API for now.
|
// Read things for the current goobj API for now.
|
||||||
|
|
||||||
|
// File names
|
||||||
|
r.p.FileList = make([]string, rr.NFile())
|
||||||
|
for i := range r.p.FileList {
|
||||||
|
r.p.FileList[i] = rr.File(i)
|
||||||
|
}
|
||||||
|
|
||||||
// Symbols
|
// Symbols
|
||||||
pcdataBase := start + rr.PcdataBase()
|
pcdataBase := start + rr.PcdataBase()
|
||||||
ndef := uint32(rr.NSym() + rr.NHashed64def() + rr.NHasheddef() + rr.NNonpkgdef())
|
ndef := uint32(rr.NSym() + rr.NHashed64def() + rr.NHasheddef() + rr.NNonpkgdef())
|
||||||
|
|
@ -166,7 +172,7 @@ func (r *objReader) readNew() {
|
||||||
PCInline: Data{int64(pcdataBase + info.Pcinline), int64(info.Pcdata[0] - info.Pcinline)},
|
PCInline: Data{int64(pcdataBase + info.Pcinline), int64(info.Pcdata[0] - info.Pcinline)},
|
||||||
PCData: make([]Data, len(info.Pcdata)-1), // -1 as we appended one above
|
PCData: make([]Data, len(info.Pcdata)-1), // -1 as we appended one above
|
||||||
FuncData: make([]FuncData, len(info.Funcdataoff)),
|
FuncData: make([]FuncData, len(info.Funcdataoff)),
|
||||||
File: make([]string, len(info.File)),
|
File: make(map[goobj2.CUFileIndex]struct{}, len(info.File)),
|
||||||
InlTree: make([]InlinedCall, len(info.InlTree)),
|
InlTree: make([]InlinedCall, len(info.InlTree)),
|
||||||
}
|
}
|
||||||
sym.Func = f
|
sym.Func = f
|
||||||
|
|
@ -177,15 +183,14 @@ func (r *objReader) readNew() {
|
||||||
symID := resolveSymRef(funcdata[k])
|
symID := resolveSymRef(funcdata[k])
|
||||||
f.FuncData[k] = FuncData{symID, int64(info.Funcdataoff[k])}
|
f.FuncData[k] = FuncData{symID, int64(info.Funcdataoff[k])}
|
||||||
}
|
}
|
||||||
for k := range f.File {
|
for _, k := range info.File {
|
||||||
symID := resolveSymRef(info.File[k])
|
f.File[k] = struct{}{}
|
||||||
f.File[k] = symID.Name
|
|
||||||
}
|
}
|
||||||
for k := range f.InlTree {
|
for k := range f.InlTree {
|
||||||
inl := &info.InlTree[k]
|
inl := &info.InlTree[k]
|
||||||
f.InlTree[k] = InlinedCall{
|
f.InlTree[k] = InlinedCall{
|
||||||
Parent: int64(inl.Parent),
|
Parent: int64(inl.Parent),
|
||||||
File: resolveSymRef(inl.File).Name,
|
File: inl.File,
|
||||||
Line: int64(inl.Line),
|
Line: int64(inl.Line),
|
||||||
Func: resolveSymRef(inl.Func),
|
Func: resolveSymRef(inl.Func),
|
||||||
ParentPC: int64(inl.ParentPC),
|
ParentPC: int64(inl.ParentPC),
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,10 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CUFileIndex is used to index the filenames that are stored in the
|
||||||
|
// per-package/per-CU FileList.
|
||||||
|
type CUFileIndex uint32
|
||||||
|
|
||||||
// FuncInfo is serialized as a symbol (aux symbol). The symbol data is
|
// FuncInfo is serialized as a symbol (aux symbol). The symbol data is
|
||||||
// the binary encoding of the struct below.
|
// the binary encoding of the struct below.
|
||||||
//
|
//
|
||||||
|
|
@ -26,7 +30,7 @@ type FuncInfo struct {
|
||||||
Pcdata []uint32
|
Pcdata []uint32
|
||||||
PcdataEnd uint32
|
PcdataEnd uint32
|
||||||
Funcdataoff []uint32
|
Funcdataoff []uint32
|
||||||
File []SymRef // TODO: just use string?
|
File []CUFileIndex
|
||||||
|
|
||||||
InlTree []InlTreeNode
|
InlTree []InlTreeNode
|
||||||
}
|
}
|
||||||
|
|
@ -57,8 +61,7 @@ func (a *FuncInfo) Write(w *bytes.Buffer) {
|
||||||
}
|
}
|
||||||
writeUint32(uint32(len(a.File)))
|
writeUint32(uint32(len(a.File)))
|
||||||
for _, f := range a.File {
|
for _, f := range a.File {
|
||||||
writeUint32(f.PkgIdx)
|
writeUint32(uint32(f))
|
||||||
writeUint32(f.SymIdx)
|
|
||||||
}
|
}
|
||||||
writeUint32(uint32(len(a.InlTree)))
|
writeUint32(uint32(len(a.InlTree)))
|
||||||
for i := range a.InlTree {
|
for i := range a.InlTree {
|
||||||
|
|
@ -93,9 +96,9 @@ func (a *FuncInfo) Read(b []byte) {
|
||||||
a.Funcdataoff[i] = readUint32()
|
a.Funcdataoff[i] = readUint32()
|
||||||
}
|
}
|
||||||
filelen := readUint32()
|
filelen := readUint32()
|
||||||
a.File = make([]SymRef, filelen)
|
a.File = make([]CUFileIndex, filelen)
|
||||||
for i := range a.File {
|
for i := range a.File {
|
||||||
a.File[i] = SymRef{readUint32(), readUint32()}
|
a.File[i] = CUFileIndex(readUint32())
|
||||||
}
|
}
|
||||||
inltreelen := readUint32()
|
inltreelen := readUint32()
|
||||||
a.InlTree = make([]InlTreeNode, inltreelen)
|
a.InlTree = make([]InlTreeNode, inltreelen)
|
||||||
|
|
@ -136,8 +139,7 @@ func (*FuncInfo) ReadFuncInfoLengths(b []byte) FuncInfoLengths {
|
||||||
result.NumFile = binary.LittleEndian.Uint32(b[numfileOff:])
|
result.NumFile = binary.LittleEndian.Uint32(b[numfileOff:])
|
||||||
result.FileOff = numfileOff + 4
|
result.FileOff = numfileOff + 4
|
||||||
|
|
||||||
const symRefSize = 4 + 4
|
numinltreeOff := result.FileOff + 4*result.NumFile
|
||||||
numinltreeOff := result.FileOff + symRefSize*result.NumFile
|
|
||||||
result.NumInlTree = binary.LittleEndian.Uint32(b[numinltreeOff:])
|
result.NumInlTree = binary.LittleEndian.Uint32(b[numinltreeOff:])
|
||||||
result.InlTreeOff = numinltreeOff + 4
|
result.InlTreeOff = numinltreeOff + 4
|
||||||
|
|
||||||
|
|
@ -181,14 +183,12 @@ func (*FuncInfo) ReadFuncdataoff(b []byte, funcdataofffoff uint32, k uint32) int
|
||||||
return int64(binary.LittleEndian.Uint32(b[funcdataofffoff+4*k:]))
|
return int64(binary.LittleEndian.Uint32(b[funcdataofffoff+4*k:]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*FuncInfo) ReadFile(b []byte, filesoff uint32, k uint32) SymRef {
|
func (*FuncInfo) ReadFile(b []byte, filesoff uint32, k uint32) CUFileIndex {
|
||||||
p := binary.LittleEndian.Uint32(b[filesoff+8*k:])
|
return CUFileIndex(binary.LittleEndian.Uint32(b[filesoff+4*k:]))
|
||||||
s := binary.LittleEndian.Uint32(b[filesoff+4+8*k:])
|
|
||||||
return SymRef{p, s}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*FuncInfo) ReadInlTree(b []byte, inltreeoff uint32, k uint32) InlTreeNode {
|
func (*FuncInfo) ReadInlTree(b []byte, inltreeoff uint32, k uint32) InlTreeNode {
|
||||||
const inlTreeNodeSize = 4 * 7
|
const inlTreeNodeSize = 4 * 6
|
||||||
var result InlTreeNode
|
var result InlTreeNode
|
||||||
result.Read(b[inltreeoff+k*inlTreeNodeSize:])
|
result.Read(b[inltreeoff+k*inlTreeNodeSize:])
|
||||||
return result
|
return result
|
||||||
|
|
@ -197,7 +197,7 @@ func (*FuncInfo) ReadInlTree(b []byte, inltreeoff uint32, k uint32) InlTreeNode
|
||||||
// InlTreeNode is the serialized form of FileInfo.InlTree.
|
// InlTreeNode is the serialized form of FileInfo.InlTree.
|
||||||
type InlTreeNode struct {
|
type InlTreeNode struct {
|
||||||
Parent int32
|
Parent int32
|
||||||
File SymRef
|
File CUFileIndex
|
||||||
Line int32
|
Line int32
|
||||||
Func SymRef
|
Func SymRef
|
||||||
ParentPC int32
|
ParentPC int32
|
||||||
|
|
@ -210,8 +210,7 @@ func (inl *InlTreeNode) Write(w *bytes.Buffer) {
|
||||||
w.Write(b[:])
|
w.Write(b[:])
|
||||||
}
|
}
|
||||||
writeUint32(uint32(inl.Parent))
|
writeUint32(uint32(inl.Parent))
|
||||||
writeUint32(inl.File.PkgIdx)
|
writeUint32(uint32(inl.File))
|
||||||
writeUint32(inl.File.SymIdx)
|
|
||||||
writeUint32(uint32(inl.Line))
|
writeUint32(uint32(inl.Line))
|
||||||
writeUint32(inl.Func.PkgIdx)
|
writeUint32(inl.Func.PkgIdx)
|
||||||
writeUint32(inl.Func.SymIdx)
|
writeUint32(inl.Func.SymIdx)
|
||||||
|
|
@ -226,7 +225,7 @@ func (inl *InlTreeNode) Read(b []byte) []byte {
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
inl.Parent = int32(readUint32())
|
inl.Parent = int32(readUint32())
|
||||||
inl.File = SymRef{readUint32(), readUint32()}
|
inl.File = CUFileIndex(readUint32())
|
||||||
inl.Line = int32(readUint32())
|
inl.Line = int32(readUint32())
|
||||||
inl.Func = SymRef{readUint32(), readUint32()}
|
inl.Func = SymRef{readUint32(), readUint32()}
|
||||||
inl.ParentPC = int32(readUint32())
|
inl.ParentPC = int32(readUint32())
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ import (
|
||||||
//
|
//
|
||||||
// PkgIndex [...]string // referenced packages by index
|
// PkgIndex [...]string // referenced packages by index
|
||||||
//
|
//
|
||||||
// DwarfFiles [...]string
|
// Files [...]string
|
||||||
//
|
//
|
||||||
// SymbolDefs [...]struct {
|
// SymbolDefs [...]struct {
|
||||||
// Name string
|
// Name string
|
||||||
|
|
@ -177,7 +177,7 @@ const (
|
||||||
const (
|
const (
|
||||||
BlkAutolib = iota
|
BlkAutolib = iota
|
||||||
BlkPkgIdx
|
BlkPkgIdx
|
||||||
BlkDwarfFile
|
BlkFile
|
||||||
BlkSymdef
|
BlkSymdef
|
||||||
BlkHashed64def
|
BlkHashed64def
|
||||||
BlkHasheddef
|
BlkHasheddef
|
||||||
|
|
@ -686,12 +686,12 @@ func (r *Reader) Pkg(i int) string {
|
||||||
return r.StringRef(off)
|
return r.StringRef(off)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reader) NDwarfFile() int {
|
func (r *Reader) NFile() int {
|
||||||
return int(r.h.Offsets[BlkDwarfFile+1]-r.h.Offsets[BlkDwarfFile]) / stringRefSize
|
return int(r.h.Offsets[BlkFile+1]-r.h.Offsets[BlkFile]) / stringRefSize
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reader) DwarfFile(i int) string {
|
func (r *Reader) File(i int) string {
|
||||||
off := r.h.Offsets[BlkDwarfFile] + uint32(i)*stringRefSize
|
off := r.h.Offsets[BlkFile] + uint32(i)*stringRefSize
|
||||||
return r.StringRef(off)
|
return r.StringRef(off)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,18 +32,6 @@ const (
|
||||||
func (ctxt *Link) generateDebugLinesSymbol(s, lines *LSym) {
|
func (ctxt *Link) generateDebugLinesSymbol(s, lines *LSym) {
|
||||||
dctxt := dwCtxt{ctxt}
|
dctxt := dwCtxt{ctxt}
|
||||||
|
|
||||||
// The Pcfile table is used to generate the debug_lines section, and the file
|
|
||||||
// indices for that data could differ from the files we write out for the
|
|
||||||
// debug_lines section. Here we generate a LUT between those two indices.
|
|
||||||
fileNums := make(map[int32]int64)
|
|
||||||
for i, filename := range s.Func.Pcln.File {
|
|
||||||
if symbolIndex := ctxt.PosTable.FileIndex(filename); symbolIndex >= 0 {
|
|
||||||
fileNums[int32(i)] = int64(symbolIndex) + 1
|
|
||||||
} else {
|
|
||||||
panic(fmt.Sprintf("First time we've seen filename: %q", filename))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit a LNE_set_address extended opcode, so as to establish the
|
// Emit a LNE_set_address extended opcode, so as to establish the
|
||||||
// starting text address of this function.
|
// starting text address of this function.
|
||||||
dctxt.AddUint8(lines, 0)
|
dctxt.AddUint8(lines, 0)
|
||||||
|
|
|
||||||
|
|
@ -22,3 +22,9 @@ func linkgetlineFromPos(ctxt *Link, xpos src.XPos) (f string, l int32) {
|
||||||
// TODO(gri) Should this use relative or absolute line number?
|
// TODO(gri) Should this use relative or absolute line number?
|
||||||
return pos.SymFilename(), int32(pos.RelLine())
|
return pos.SymFilename(), int32(pos.RelLine())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getFileIndexAndLine returns the file index (local to the CU), and the line number for a position.
|
||||||
|
func getFileIndexAndLine(ctxt *Link, xpos src.XPos) (int, int32) {
|
||||||
|
f, l := linkgetlineFromPos(ctxt, xpos)
|
||||||
|
return ctxt.PosTable.FileIndex(f), l
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -631,9 +631,7 @@ type Pcln struct {
|
||||||
Pcdata []Pcdata
|
Pcdata []Pcdata
|
||||||
Funcdata []*LSym
|
Funcdata []*LSym
|
||||||
Funcdataoff []int64
|
Funcdataoff []int64
|
||||||
File []string
|
UsedFiles map[goobj2.CUFileIndex]struct{} // file indices used while generating pcfile
|
||||||
Lastfile string
|
|
||||||
Lastindex int
|
|
||||||
InlTree InlTree // per-function inlining tree extracted from the global tree
|
InlTree InlTree // per-function inlining tree extracted from the global tree
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -69,9 +70,9 @@ func WriteObjFile(ctxt *Link, b *bio.Writer) {
|
||||||
w.StringRef(pkg)
|
w.StringRef(pkg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DWARF file table
|
// File table (for DWARF and pcln generation).
|
||||||
h.Offsets[goobj2.BlkDwarfFile] = w.Offset()
|
h.Offsets[goobj2.BlkFile] = w.Offset()
|
||||||
for _, f := range ctxt.PosTable.DebugLinesFileTable() {
|
for _, f := range ctxt.PosTable.FileTable() {
|
||||||
w.StringRef(filepath.ToSlash(f))
|
w.StringRef(filepath.ToSlash(f))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -248,20 +249,9 @@ func (w *writer) StringTable() {
|
||||||
}
|
}
|
||||||
w.AddString(s.Name)
|
w.AddString(s.Name)
|
||||||
})
|
})
|
||||||
w.ctxt.traverseSyms(traverseDefs, func(s *LSym) {
|
|
||||||
if s.Type != objabi.STEXT {
|
// All filenames are in the postable.
|
||||||
return
|
for _, f := range w.ctxt.PosTable.FileTable() {
|
||||||
}
|
|
||||||
pc := &s.Func.Pcln
|
|
||||||
for _, f := range pc.File {
|
|
||||||
w.AddString(filepath.ToSlash(f))
|
|
||||||
}
|
|
||||||
for _, call := range pc.InlTree.nodes {
|
|
||||||
f, _ := linkgetlineFromPos(w.ctxt, call.Pos)
|
|
||||||
w.AddString(filepath.ToSlash(f))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
for _, f := range w.ctxt.PosTable.DebugLinesFileTable() {
|
|
||||||
w.AddString(filepath.ToSlash(f))
|
w.AddString(filepath.ToSlash(f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -594,18 +584,19 @@ func genFuncInfoSyms(ctxt *Link) {
|
||||||
for i, x := range pc.Funcdataoff {
|
for i, x := range pc.Funcdataoff {
|
||||||
o.Funcdataoff[i] = uint32(x)
|
o.Funcdataoff[i] = uint32(x)
|
||||||
}
|
}
|
||||||
o.File = make([]goobj2.SymRef, len(pc.File))
|
i := 0
|
||||||
for i, f := range pc.File {
|
o.File = make([]goobj2.CUFileIndex, len(pc.UsedFiles))
|
||||||
fsym := ctxt.Lookup(f)
|
for f := range pc.UsedFiles {
|
||||||
o.File[i] = makeSymRef(fsym)
|
o.File[i] = f
|
||||||
|
i++
|
||||||
}
|
}
|
||||||
|
sort.Slice(o.File, func(i, j int) bool { return o.File[i] < o.File[j] })
|
||||||
o.InlTree = make([]goobj2.InlTreeNode, len(pc.InlTree.nodes))
|
o.InlTree = make([]goobj2.InlTreeNode, len(pc.InlTree.nodes))
|
||||||
for i, inl := range pc.InlTree.nodes {
|
for i, inl := range pc.InlTree.nodes {
|
||||||
f, l := linkgetlineFromPos(ctxt, inl.Pos)
|
f, l := getFileIndexAndLine(ctxt, inl.Pos)
|
||||||
fsym := ctxt.Lookup(f)
|
|
||||||
o.InlTree[i] = goobj2.InlTreeNode{
|
o.InlTree[i] = goobj2.InlTreeNode{
|
||||||
Parent: int32(inl.Parent),
|
Parent: int32(inl.Parent),
|
||||||
File: makeSymRef(fsym),
|
File: goobj2.CUFileIndex(f),
|
||||||
Line: l,
|
Line: l,
|
||||||
Func: makeSymRef(inl.Func),
|
Func: makeSymRef(inl.Func),
|
||||||
ParentPC: inl.ParentPC,
|
ParentPC: inl.ParentPC,
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
package obj
|
package obj
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"cmd/internal/goobj2"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
@ -130,28 +131,13 @@ func pctofileline(ctxt *Link, sym *LSym, oldval int32, p *Prog, phase int32, arg
|
||||||
if p.As == ATEXT || p.As == ANOP || p.Pos.Line() == 0 || phase == 1 {
|
if p.As == ATEXT || p.As == ANOP || p.Pos.Line() == 0 || phase == 1 {
|
||||||
return oldval
|
return oldval
|
||||||
}
|
}
|
||||||
f, l := linkgetlineFromPos(ctxt, p.Pos)
|
f, l := getFileIndexAndLine(ctxt, p.Pos)
|
||||||
if arg == nil {
|
if arg == nil {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
pcln := arg.(*Pcln)
|
pcln := arg.(*Pcln)
|
||||||
|
pcln.UsedFiles[goobj2.CUFileIndex(f)] = struct{}{}
|
||||||
if f == pcln.Lastfile {
|
return int32(f)
|
||||||
return int32(pcln.Lastindex)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, file := range pcln.File {
|
|
||||||
if file == f {
|
|
||||||
pcln.Lastfile = f
|
|
||||||
pcln.Lastindex = i
|
|
||||||
return int32(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i := len(pcln.File)
|
|
||||||
pcln.File = append(pcln.File, f)
|
|
||||||
pcln.Lastfile = f
|
|
||||||
pcln.Lastindex = i
|
|
||||||
return int32(i)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// pcinlineState holds the state used to create a function's inlining
|
// pcinlineState holds the state used to create a function's inlining
|
||||||
|
|
@ -263,6 +249,7 @@ func pctopcdata(ctxt *Link, sym *LSym, oldval int32, p *Prog, phase int32, arg i
|
||||||
|
|
||||||
func linkpcln(ctxt *Link, cursym *LSym) {
|
func linkpcln(ctxt *Link, cursym *LSym) {
|
||||||
pcln := &cursym.Func.Pcln
|
pcln := &cursym.Func.Pcln
|
||||||
|
pcln.UsedFiles = make(map[goobj2.CUFileIndex]struct{})
|
||||||
|
|
||||||
npcdata := 0
|
npcdata := 0
|
||||||
nfuncdata := 0
|
nfuncdata := 0
|
||||||
|
|
|
||||||
|
|
@ -367,8 +367,9 @@ func (ctxt *Link) traverseFuncAux(flag traverseFlag, fsym *LSym, fn func(parent
|
||||||
fn(fsym, d)
|
fn(fsym, d)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, f := range pc.File {
|
files := ctxt.PosTable.FileTable()
|
||||||
if filesym := ctxt.Lookup(f); filesym != nil {
|
for f := range pc.UsedFiles {
|
||||||
|
if filesym := ctxt.Lookup(files[f]); filesym != nil {
|
||||||
fn(fsym, filesym)
|
fn(fsym, filesym)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ func (f *goobjFile) PCToLine(pc uint64) (string, int, *gosym.Func) {
|
||||||
return "", 0, nil
|
return "", 0, nil
|
||||||
}
|
}
|
||||||
fileID := int(pcValue(pcfile, pc-uint64(s.Data.Offset), arch))
|
fileID := int(pcValue(pcfile, pc-uint64(s.Data.Offset), arch))
|
||||||
fileName := s.Func.File[fileID]
|
fileName := f.goobj.FileList[fileID]
|
||||||
pcline := make([]byte, s.Func.PCLine.Size)
|
pcline := make([]byte, s.Func.PCLine.Size)
|
||||||
_, err = f.f.ReadAt(pcline, s.Func.PCLine.Offset)
|
_, err = f.f.ReadAt(pcline, s.Func.PCLine.Offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -163,8 +163,8 @@ func (t *PosTable) FileIndex(filename string) int {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// DebugLinesFiles returns the file table for the debug_lines DWARF section.
|
// FileTable returns a slice of all files used to build this package.
|
||||||
func (t *PosTable) DebugLinesFileTable() []string {
|
func (t *PosTable) FileTable() []string {
|
||||||
// Create a LUT of the global package level file indices. This table is what
|
// Create a LUT of the global package level file indices. This table is what
|
||||||
// is written in the debug_lines header, the file[N] will be referenced as
|
// is written in the debug_lines header, the file[N] will be referenced as
|
||||||
// N+1 in the debug_lines table.
|
// N+1 in the debug_lines table.
|
||||||
|
|
|
||||||
|
|
@ -1224,7 +1224,7 @@ func (d *dwctxt) writelines(unit *sym.CompilationUnit, lineProlog loader.Sym) []
|
||||||
|
|
||||||
// Copy over the file table.
|
// Copy over the file table.
|
||||||
fileNums := make(map[string]int)
|
fileNums := make(map[string]int)
|
||||||
for i, name := range unit.DWARFFileTable {
|
for i, name := range unit.FileTable {
|
||||||
name := expandFile(name)
|
name := expandFile(name)
|
||||||
if len(name) == 0 {
|
if len(name) == 0 {
|
||||||
// Can't have empty filenames, and having a unique
|
// Can't have empty filenames, and having a unique
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
package ld
|
package ld
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"cmd/internal/goobj2"
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"cmd/internal/objabi"
|
"cmd/internal/objabi"
|
||||||
"cmd/internal/src"
|
"cmd/internal/src"
|
||||||
|
|
@ -32,7 +33,7 @@ import (
|
||||||
type oldPclnState struct {
|
type oldPclnState struct {
|
||||||
ldr *loader.Loader
|
ldr *loader.Loader
|
||||||
deferReturnSym loader.Sym
|
deferReturnSym loader.Sym
|
||||||
numberedFiles map[loader.Sym]int64
|
numberedFiles map[string]int64
|
||||||
filepaths []string
|
filepaths []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,7 +89,7 @@ func makeOldPclnState(ctxt *Link) *oldPclnState {
|
||||||
state := &oldPclnState{
|
state := &oldPclnState{
|
||||||
ldr: ldr,
|
ldr: ldr,
|
||||||
deferReturnSym: drs,
|
deferReturnSym: drs,
|
||||||
numberedFiles: make(map[loader.Sym]int64),
|
numberedFiles: make(map[string]int64),
|
||||||
// NB: initial entry in filepaths below is to reserve the zero value,
|
// NB: initial entry in filepaths below is to reserve the zero value,
|
||||||
// so that when we do a map lookup in numberedFiles fails, it will not
|
// so that when we do a map lookup in numberedFiles fails, it will not
|
||||||
// return a value slot in filepaths.
|
// return a value slot in filepaths.
|
||||||
|
|
@ -153,30 +154,37 @@ func ftabaddstring(ftab *loader.SymbolBuilder, s string) int32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// numberfile assigns a file number to the file if it hasn't been assigned already.
|
// numberfile assigns a file number to the file if it hasn't been assigned already.
|
||||||
func (state *oldPclnState) numberfile(file loader.Sym) int64 {
|
// This funciton looks at a CU's file at index [i], and if it's a new filename,
|
||||||
|
// stores that filename in the global file table, and adds it to the map lookup
|
||||||
|
// for renumbering pcfile.
|
||||||
|
func (state *oldPclnState) numberfile(cu *sym.CompilationUnit, i goobj2.CUFileIndex) int64 {
|
||||||
|
file := cu.FileTable[i]
|
||||||
if val, ok := state.numberedFiles[file]; ok {
|
if val, ok := state.numberedFiles[file]; ok {
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
sn := state.ldr.SymName(file)
|
path := file
|
||||||
path := sn[len(src.FileSymPrefix):]
|
if strings.HasPrefix(path, src.FileSymPrefix) {
|
||||||
|
path = file[len(src.FileSymPrefix):]
|
||||||
|
}
|
||||||
val := int64(len(state.filepaths))
|
val := int64(len(state.filepaths))
|
||||||
state.numberedFiles[file] = val
|
state.numberedFiles[file] = val
|
||||||
state.filepaths = append(state.filepaths, expandGoroot(path))
|
state.filepaths = append(state.filepaths, expandGoroot(path))
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
func (state *oldPclnState) fileVal(file loader.Sym) int64 {
|
func (state *oldPclnState) fileVal(cu *sym.CompilationUnit, i int32) int64 {
|
||||||
|
file := cu.FileTable[i]
|
||||||
if val, ok := state.numberedFiles[file]; ok {
|
if val, ok := state.numberedFiles[file]; ok {
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
panic("should have been numbered first")
|
panic("should have been numbered first")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (state *oldPclnState) renumberfiles(ctxt *Link, fi loader.FuncInfo, d *sym.Pcdata) {
|
func (state *oldPclnState) renumberfiles(ctxt *Link, cu *sym.CompilationUnit, fi loader.FuncInfo, d *sym.Pcdata) {
|
||||||
// Give files numbers.
|
// Give files numbers.
|
||||||
nf := fi.NumFile()
|
nf := fi.NumFile()
|
||||||
for i := uint32(0); i < nf; i++ {
|
for i := uint32(0); i < nf; i++ {
|
||||||
state.numberfile(fi.File(int(i)))
|
state.numberfile(cu, fi.File(int(i)))
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := make([]byte, binary.MaxVarintLen32)
|
buf := make([]byte, binary.MaxVarintLen32)
|
||||||
|
|
@ -191,10 +199,10 @@ func (state *oldPclnState) renumberfiles(ctxt *Link, fi loader.FuncInfo, d *sym.
|
||||||
if oldval == -1 {
|
if oldval == -1 {
|
||||||
val = -1
|
val = -1
|
||||||
} else {
|
} else {
|
||||||
if oldval < 0 || oldval >= int32(nf) {
|
if oldval < 0 || oldval >= int32(len(cu.FileTable)) {
|
||||||
log.Fatalf("bad pcdata %d", oldval)
|
log.Fatalf("bad pcdata %d", oldval)
|
||||||
}
|
}
|
||||||
val = int32(state.fileVal(fi.File(int(oldval))))
|
val = int32(state.fileVal(cu, oldval))
|
||||||
}
|
}
|
||||||
|
|
||||||
dv := val - newval
|
dv := val - newval
|
||||||
|
|
@ -287,7 +295,7 @@ func (state *oldPclnState) computeDeferReturn(target *Target, s loader.Sym) uint
|
||||||
|
|
||||||
// genInlTreeSym generates the InlTree sym for a function with the
|
// genInlTreeSym generates the InlTree sym for a function with the
|
||||||
// specified FuncInfo.
|
// specified FuncInfo.
|
||||||
func (state *oldPclnState) genInlTreeSym(fi loader.FuncInfo, arch *sys.Arch, newState *pclntab) loader.Sym {
|
func (state *oldPclnState) genInlTreeSym(cu *sym.CompilationUnit, fi loader.FuncInfo, arch *sys.Arch, newState *pclntab) loader.Sym {
|
||||||
ldr := state.ldr
|
ldr := state.ldr
|
||||||
its := ldr.CreateExtSym("", 0)
|
its := ldr.CreateExtSym("", 0)
|
||||||
inlTreeSym := ldr.MakeSymbolUpdater(its)
|
inlTreeSym := ldr.MakeSymbolUpdater(its)
|
||||||
|
|
@ -305,7 +313,7 @@ func (state *oldPclnState) genInlTreeSym(fi loader.FuncInfo, arch *sys.Arch, new
|
||||||
// might overlap exactly so that only the innermost file
|
// might overlap exactly so that only the innermost file
|
||||||
// appears in the Pcfile table. In that case, this assigns
|
// appears in the Pcfile table. In that case, this assigns
|
||||||
// the outer file a number.
|
// the outer file a number.
|
||||||
val := state.numberfile(call.File)
|
val := state.numberfile(cu, call.File)
|
||||||
nameoff, ok := newState.funcNameOffset[call.Func]
|
nameoff, ok := newState.funcNameOffset[call.Func]
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("couldn't find function name offset")
|
panic("couldn't find function name offset")
|
||||||
|
|
@ -603,11 +611,12 @@ func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab {
|
||||||
deferreturn := oldState.computeDeferReturn(&ctxt.Target, s)
|
deferreturn := oldState.computeDeferReturn(&ctxt.Target, s)
|
||||||
off = int32(ftab.SetUint32(ctxt.Arch, int64(off), deferreturn))
|
off = int32(ftab.SetUint32(ctxt.Arch, int64(off), deferreturn))
|
||||||
|
|
||||||
|
cu := ldr.SymUnit(s)
|
||||||
if fi.Valid() {
|
if fi.Valid() {
|
||||||
pcsp = sym.Pcdata{P: fi.Pcsp()}
|
pcsp = sym.Pcdata{P: fi.Pcsp()}
|
||||||
pcfile = sym.Pcdata{P: fi.Pcfile()}
|
pcfile = sym.Pcdata{P: fi.Pcfile()}
|
||||||
pcline = sym.Pcdata{P: fi.Pcline()}
|
pcline = sym.Pcdata{P: fi.Pcline()}
|
||||||
oldState.renumberfiles(ctxt, fi, &pcfile)
|
oldState.renumberfiles(ctxt, cu, fi, &pcfile)
|
||||||
if false {
|
if false {
|
||||||
// Sanity check the new numbering
|
// Sanity check the new numbering
|
||||||
it := obj.NewPCIter(uint32(ctxt.Arch.MinLC))
|
it := obj.NewPCIter(uint32(ctxt.Arch.MinLC))
|
||||||
|
|
@ -621,7 +630,7 @@ func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab {
|
||||||
}
|
}
|
||||||
|
|
||||||
if fi.Valid() && fi.NumInlTree() > 0 {
|
if fi.Valid() && fi.NumInlTree() > 0 {
|
||||||
its := oldState.genInlTreeSym(fi, ctxt.Arch, state)
|
its := oldState.genInlTreeSym(cu, fi, ctxt.Arch, state)
|
||||||
funcdata[objabi.FUNCDATA_InlTree] = its
|
funcdata[objabi.FUNCDATA_InlTree] = its
|
||||||
pcdata[objabi.PCDATA_InlTreeIndex] = sym.Pcdata{P: fi.Pcinline()}
|
pcdata[objabi.PCDATA_InlTreeIndex] = sym.Pcdata{P: fi.Pcinline()}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1961,17 +1961,16 @@ func (fi *FuncInfo) NumFile() uint32 {
|
||||||
return fi.lengths.NumFile
|
return fi.lengths.NumFile
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fi *FuncInfo) File(k int) Sym {
|
func (fi *FuncInfo) File(k int) goobj2.CUFileIndex {
|
||||||
if !fi.lengths.Initialized {
|
if !fi.lengths.Initialized {
|
||||||
panic("need to call Preload first")
|
panic("need to call Preload first")
|
||||||
}
|
}
|
||||||
sr := (*goobj2.FuncInfo)(nil).ReadFile(fi.data, fi.lengths.FileOff, uint32(k))
|
return (*goobj2.FuncInfo)(nil).ReadFile(fi.data, fi.lengths.FileOff, uint32(k))
|
||||||
return fi.l.resolve(fi.r, sr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type InlTreeNode struct {
|
type InlTreeNode struct {
|
||||||
Parent int32
|
Parent int32
|
||||||
File Sym
|
File goobj2.CUFileIndex
|
||||||
Line int32
|
Line int32
|
||||||
Func Sym
|
Func Sym
|
||||||
ParentPC int32
|
ParentPC int32
|
||||||
|
|
@ -1991,7 +1990,7 @@ func (fi *FuncInfo) InlTree(k int) InlTreeNode {
|
||||||
node := (*goobj2.FuncInfo)(nil).ReadInlTree(fi.data, fi.lengths.InlTreeOff, uint32(k))
|
node := (*goobj2.FuncInfo)(nil).ReadInlTree(fi.data, fi.lengths.InlTreeOff, uint32(k))
|
||||||
return InlTreeNode{
|
return InlTreeNode{
|
||||||
Parent: node.Parent,
|
Parent: node.Parent,
|
||||||
File: fi.l.resolve(fi.r, node.File),
|
File: node.File,
|
||||||
Line: node.Line,
|
Line: node.Line,
|
||||||
Func: fi.l.resolve(fi.r, node.Func),
|
Func: fi.l.resolve(fi.r, node.Func),
|
||||||
ParentPC: node.ParentPC,
|
ParentPC: node.ParentPC,
|
||||||
|
|
@ -2060,10 +2059,10 @@ func (l *Loader) Preload(localSymVersion int, f *bio.Reader, lib *sym.Library, u
|
||||||
lib.Autolib = append(lib.Autolib, r.Autolib()...)
|
lib.Autolib = append(lib.Autolib, r.Autolib()...)
|
||||||
|
|
||||||
// DWARF file table
|
// DWARF file table
|
||||||
nfile := r.NDwarfFile()
|
nfile := r.NFile()
|
||||||
unit.DWARFFileTable = make([]string, nfile)
|
unit.FileTable = make([]string, nfile)
|
||||||
for i := range unit.DWARFFileTable {
|
for i := range unit.FileTable {
|
||||||
unit.DWARFFileTable[i] = r.DwarfFile(i)
|
unit.FileTable[i] = r.File(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
l.addObj(lib.Pkg, or)
|
l.addObj(lib.Pkg, or)
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ type CompilationUnit struct {
|
||||||
PclnIndex int // Index of this CU in pclntab
|
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
|
FileTable []string // The file table used in this compilation unit.
|
||||||
|
|
||||||
Consts LoaderSym // Package constants DIEs
|
Consts LoaderSym // Package constants DIEs
|
||||||
FuncDIEs []LoaderSym // Function DIE subtrees
|
FuncDIEs []LoaderSym // Function DIE subtrees
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue