]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.link] use per package filenames to build pclntab
authorJeremy Faller <jeremy@golang.org>
Wed, 29 Jul 2020 15:06:02 +0000 (11:06 -0400)
committerJeremy Faller <jeremy@golang.org>
Mon, 10 Aug 2020 16:55:06 +0000 (16:55 +0000)
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>
16 files changed:
src/cmd/internal/goobj/read.go
src/cmd/internal/goobj/readnew.go
src/cmd/internal/goobj2/funcinfo.go
src/cmd/internal/goobj2/objfile.go
src/cmd/internal/obj/dwarf.go
src/cmd/internal/obj/line.go
src/cmd/internal/obj/link.go
src/cmd/internal/obj/objfile2.go
src/cmd/internal/obj/pcln.go
src/cmd/internal/obj/sym.go
src/cmd/internal/objfile/goobj.go
src/cmd/internal/src/xpos.go
src/cmd/link/internal/ld/dwarf.go
src/cmd/link/internal/ld/pcln.go
src/cmd/link/internal/loader/loader.go
src/cmd/link/internal/sym/compilation_unit.go

index 2bbc35d3451be4fa861153d7413bb5a2422dd45d..cb388a84cdb2d23782a5ec6449c3766f1c5a4ff7 100644 (file)
@@ -94,20 +94,20 @@ type Var struct {
 
 // Func contains additional per-symbol information specific to functions.
 type Func struct {
-       Args     int64      // size in bytes of argument frame: inputs and outputs
-       Frame    int64      // size in bytes of local variable frame
-       Align    uint32     // alignment requirement in bytes for the address of the function
-       Leaf     bool       // function omits save of link register (ARM)
-       NoSplit  bool       // function omits stack split prologue
-       TopFrame bool       // function is the top of the call stack
-       Var      []Var      // detail about local variables
-       PCSP     Data       // PC → SP offset map
-       PCFile   Data       // PC → file number map (index into File)
-       PCLine   Data       // PC → line number map
-       PCInline Data       // PC → inline tree index map
-       PCData   []Data     // PC → runtime support data map
-       FuncData []FuncData // non-PC-specific runtime support data
-       File     []string   // paths indexed by PCFile
+       Args     int64                           // size in bytes of argument frame: inputs and outputs
+       Frame    int64                           // size in bytes of local variable frame
+       Align    uint32                          // alignment requirement in bytes for the address of the function
+       Leaf     bool                            // function omits save of link register (ARM)
+       NoSplit  bool                            // function omits stack split prologue
+       TopFrame bool                            // function is the top of the call stack
+       Var      []Var                           // detail about local variables
+       PCSP     Data                            // PC → SP offset map
+       PCFile   Data                            // PC → file number map (index into File)
+       PCLine   Data                            // PC → line number map
+       PCInline Data                            // PC → inline tree index map
+       PCData   []Data                          // PC → runtime support data map
+       FuncData []FuncData                      // non-PC-specific runtime support data
+       File     map[goobj2.CUFileIndex]struct{} // set of files used in this function
        InlTree  []InlinedCall
 }
 
@@ -123,7 +123,7 @@ type FuncData struct {
 // See cmd/internal/obj.InlTree for details.
 type InlinedCall struct {
        Parent   int64
-       File     string
+       File     goobj2.CUFileIndex
        Line     int64
        Func     SymID
        ParentPC int64
@@ -131,14 +131,14 @@ type InlinedCall struct {
 
 // A Package is a parsed Go object file or archive defining a Go package.
 type Package struct {
-       ImportPath    string          // import path denoting this package
-       Imports       []string        // packages imported by this package
-       SymRefs       []SymID         // list of symbol names and versions referred to by this pack
-       Syms          []*Sym          // symbols defined by this package
-       MaxVersion    int64           // maximum Version in any SymID in Syms
-       Arch          string          // architecture
-       Native        []*NativeReader // native object data (e.g. ELF)
-       DWARFFileList []string        // List of files for the DWARF .debug_lines section
+       ImportPath string          // import path denoting this package
+       Imports    []string        // packages imported by this package
+       SymRefs    []SymID         // list of symbol names and versions referred to by this pack
+       Syms       []*Sym          // symbols defined by this package
+       MaxVersion int64           // maximum Version in any SymID in Syms
+       Arch       string          // architecture
+       Native     []*NativeReader // native object data (e.g. ELF)
+       FileList   []string        // List of files for this package.
 }
 
 type NativeReader struct {
index ebac2b5ed1205f5a862f774878e1820bac794084..11847942e8b16ba4e1c59038ec07b99297bfa5d2 100644 (file)
@@ -75,6 +75,12 @@ func (r *objReader) readNew() {
 
        // 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
        pcdataBase := start + rr.PcdataBase()
        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)},
                        PCData:   make([]Data, len(info.Pcdata)-1), // -1 as we appended one above
                        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)),
                }
                sym.Func = f
@@ -177,15 +183,14 @@ func (r *objReader) readNew() {
                        symID := resolveSymRef(funcdata[k])
                        f.FuncData[k] = FuncData{symID, int64(info.Funcdataoff[k])}
                }
-               for k := range f.File {
-                       symID := resolveSymRef(info.File[k])
-                       f.File[k] = symID.Name
+               for _, k := range info.File {
+                       f.File[k] = struct{}{}
                }
                for k := range f.InlTree {
                        inl := &info.InlTree[k]
                        f.InlTree[k] = InlinedCall{
                                Parent:   int64(inl.Parent),
-                               File:     resolveSymRef(inl.File).Name,
+                               File:     inl.File,
                                Line:     int64(inl.Line),
                                Func:     resolveSymRef(inl.Func),
                                ParentPC: int64(inl.ParentPC),
index b525c88b1381c45576a68cb9c1297f76733100eb..9d2522d3c2528b39f8604647a88d76037086e06c 100644 (file)
@@ -10,6 +10,10 @@ import (
        "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
 // the binary encoding of the struct below.
 //
@@ -26,7 +30,7 @@ type FuncInfo struct {
        Pcdata      []uint32
        PcdataEnd   uint32
        Funcdataoff []uint32
-       File        []SymRef // TODO: just use string?
+       File        []CUFileIndex
 
        InlTree []InlTreeNode
 }
@@ -57,8 +61,7 @@ func (a *FuncInfo) Write(w *bytes.Buffer) {
        }
        writeUint32(uint32(len(a.File)))
        for _, f := range a.File {
-               writeUint32(f.PkgIdx)
-               writeUint32(f.SymIdx)
+               writeUint32(uint32(f))
        }
        writeUint32(uint32(len(a.InlTree)))
        for i := range a.InlTree {
@@ -93,9 +96,9 @@ func (a *FuncInfo) Read(b []byte) {
                a.Funcdataoff[i] = readUint32()
        }
        filelen := readUint32()
-       a.File = make([]SymRef, filelen)
+       a.File = make([]CUFileIndex, filelen)
        for i := range a.File {
-               a.File[i] = SymRef{readUint32(), readUint32()}
+               a.File[i] = CUFileIndex(readUint32())
        }
        inltreelen := readUint32()
        a.InlTree = make([]InlTreeNode, inltreelen)
@@ -136,8 +139,7 @@ func (*FuncInfo) ReadFuncInfoLengths(b []byte) FuncInfoLengths {
        result.NumFile = binary.LittleEndian.Uint32(b[numfileOff:])
        result.FileOff = numfileOff + 4
 
-       const symRefSize = 4 + 4
-       numinltreeOff := result.FileOff + symRefSize*result.NumFile
+       numinltreeOff := result.FileOff + 4*result.NumFile
        result.NumInlTree = binary.LittleEndian.Uint32(b[numinltreeOff:])
        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:]))
 }
 
-func (*FuncInfo) ReadFile(b []byte, filesoff uint32, k uint32) SymRef {
-       p := binary.LittleEndian.Uint32(b[filesoff+8*k:])
-       s := binary.LittleEndian.Uint32(b[filesoff+4+8*k:])
-       return SymRef{p, s}
+func (*FuncInfo) ReadFile(b []byte, filesoff uint32, k uint32) CUFileIndex {
+       return CUFileIndex(binary.LittleEndian.Uint32(b[filesoff+4*k:]))
 }
 
 func (*FuncInfo) ReadInlTree(b []byte, inltreeoff uint32, k uint32) InlTreeNode {
-       const inlTreeNodeSize = 4 * 7
+       const inlTreeNodeSize = 4 * 6
        var result InlTreeNode
        result.Read(b[inltreeoff+k*inlTreeNodeSize:])
        return result
@@ -197,7 +197,7 @@ func (*FuncInfo) ReadInlTree(b []byte, inltreeoff uint32, k uint32) InlTreeNode
 // InlTreeNode is the serialized form of FileInfo.InlTree.
 type InlTreeNode struct {
        Parent   int32
-       File     SymRef
+       File     CUFileIndex
        Line     int32
        Func     SymRef
        ParentPC int32
@@ -210,8 +210,7 @@ func (inl *InlTreeNode) Write(w *bytes.Buffer) {
                w.Write(b[:])
        }
        writeUint32(uint32(inl.Parent))
-       writeUint32(inl.File.PkgIdx)
-       writeUint32(inl.File.SymIdx)
+       writeUint32(uint32(inl.File))
        writeUint32(uint32(inl.Line))
        writeUint32(inl.Func.PkgIdx)
        writeUint32(inl.Func.SymIdx)
@@ -226,7 +225,7 @@ func (inl *InlTreeNode) Read(b []byte) []byte {
                return x
        }
        inl.Parent = int32(readUint32())
-       inl.File = SymRef{readUint32(), readUint32()}
+       inl.File = CUFileIndex(readUint32())
        inl.Line = int32(readUint32())
        inl.Func = SymRef{readUint32(), readUint32()}
        inl.ParentPC = int32(readUint32())
index 6f0df86b066ca19a9cfe3edf6dd9b54e9baf2e5f..49f45a7736da018136f69ea5f3c55e93c6dae8fe 100644 (file)
@@ -38,7 +38,7 @@ import (
 //
 //    PkgIndex [...]string // referenced packages by index
 //
-//    DwarfFiles [...]string
+//    Files [...]string
 //
 //    SymbolDefs [...]struct {
 //       Name  string
@@ -177,7 +177,7 @@ const (
 const (
        BlkAutolib = iota
        BlkPkgIdx
-       BlkDwarfFile
+       BlkFile
        BlkSymdef
        BlkHashed64def
        BlkHasheddef
@@ -686,12 +686,12 @@ func (r *Reader) Pkg(i int) string {
        return r.StringRef(off)
 }
 
-func (r *Reader) NDwarfFile() int {
-       return int(r.h.Offsets[BlkDwarfFile+1]-r.h.Offsets[BlkDwarfFile]) / stringRefSize
+func (r *Reader) NFile() int {
+       return int(r.h.Offsets[BlkFile+1]-r.h.Offsets[BlkFile]) / stringRefSize
 }
 
-func (r *Reader) DwarfFile(i int) string {
-       off := r.h.Offsets[BlkDwarfFile] + uint32(i)*stringRefSize
+func (r *Reader) File(i int) string {
+       off := r.h.Offsets[BlkFile] + uint32(i)*stringRefSize
        return r.StringRef(off)
 }
 
index 3fc93081fa62a79898f2cff83a2d366447f588d5..724aea2f8f53f16ffd7a79e22f90f7629cfa17fd 100644 (file)
@@ -32,18 +32,6 @@ const (
 func (ctxt *Link) generateDebugLinesSymbol(s, lines *LSym) {
        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
        // starting text address of this function.
        dctxt.AddUint8(lines, 0)
index 79ecb0068f0a04ef580d81f3f76627bea9f89adf..54b9c4748c27d886c9227d3d562aa5449a275ab3 100644 (file)
@@ -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?
        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
+}
index 8d189b71f94da7238e09ea53c46b5195337e7e36..62943a7cb350e618b8d2600c566f6be26cbd78e1 100644 (file)
@@ -631,10 +631,8 @@ type Pcln struct {
        Pcdata      []Pcdata
        Funcdata    []*LSym
        Funcdataoff []int64
-       File        []string
-       Lastfile    string
-       Lastindex   int
-       InlTree     InlTree // per-function inlining tree extracted from the global tree
+       UsedFiles   map[goobj2.CUFileIndex]struct{} // file indices used while generating pcfile
+       InlTree     InlTree                         // per-function inlining tree extracted from the global tree
 }
 
 type Reloc struct {
index 17021d92943325efa1682e78985b5db4ddf54614..ae1a3646b10934c33a7069837d8c8928353ffc06 100644 (file)
@@ -16,6 +16,7 @@ import (
        "fmt"
        "io"
        "path/filepath"
+       "sort"
        "strings"
 )
 
@@ -69,9 +70,9 @@ func WriteObjFile(ctxt *Link, b *bio.Writer) {
                w.StringRef(pkg)
        }
 
-       // DWARF file table
-       h.Offsets[goobj2.BlkDwarfFile] = w.Offset()
-       for _, f := range ctxt.PosTable.DebugLinesFileTable() {
+       // File table (for DWARF and pcln generation).
+       h.Offsets[goobj2.BlkFile] = w.Offset()
+       for _, f := range ctxt.PosTable.FileTable() {
                w.StringRef(filepath.ToSlash(f))
        }
 
@@ -248,20 +249,9 @@ func (w *writer) StringTable() {
                }
                w.AddString(s.Name)
        })
-       w.ctxt.traverseSyms(traverseDefs, func(s *LSym) {
-               if s.Type != objabi.STEXT {
-                       return
-               }
-               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() {
+
+       // All filenames are in the postable.
+       for _, f := range w.ctxt.PosTable.FileTable() {
                w.AddString(filepath.ToSlash(f))
        }
 }
@@ -594,18 +584,19 @@ func genFuncInfoSyms(ctxt *Link) {
                for i, x := range pc.Funcdataoff {
                        o.Funcdataoff[i] = uint32(x)
                }
-               o.File = make([]goobj2.SymRef, len(pc.File))
-               for i, f := range pc.File {
-                       fsym := ctxt.Lookup(f)
-                       o.File[i] = makeSymRef(fsym)
+               i := 0
+               o.File = make([]goobj2.CUFileIndex, len(pc.UsedFiles))
+               for f := range pc.UsedFiles {
+                       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))
                for i, inl := range pc.InlTree.nodes {
-                       f, l := linkgetlineFromPos(ctxt, inl.Pos)
-                       fsym := ctxt.Lookup(f)
+                       f, l := getFileIndexAndLine(ctxt, inl.Pos)
                        o.InlTree[i] = goobj2.InlTreeNode{
                                Parent:   int32(inl.Parent),
-                               File:     makeSymRef(fsym),
+                               File:     goobj2.CUFileIndex(f),
                                Line:     l,
                                Func:     makeSymRef(inl.Func),
                                ParentPC: inl.ParentPC,
index 58552b9299f737033f52fd3631f59ae7a6f41d0f..b9d58e7ca3c5ed23d3833ed2463ce201c020bca0 100644 (file)
@@ -5,6 +5,7 @@
 package obj
 
 import (
+       "cmd/internal/goobj2"
        "encoding/binary"
        "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 {
                return oldval
        }
-       f, l := linkgetlineFromPos(ctxt, p.Pos)
+       f, l := getFileIndexAndLine(ctxt, p.Pos)
        if arg == nil {
                return l
        }
        pcln := arg.(*Pcln)
-
-       if f == pcln.Lastfile {
-               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)
+       pcln.UsedFiles[goobj2.CUFileIndex(f)] = struct{}{}
+       return int32(f)
 }
 
 // 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) {
        pcln := &cursym.Func.Pcln
+       pcln.UsedFiles = make(map[goobj2.CUFileIndex]struct{})
 
        npcdata := 0
        nfuncdata := 0
index 67e4081f74f568206d981994a4f7dde9e9b9f8aa..f62e1f5e58de4757500d0fdd405b5c46fea18fa9 100644 (file)
@@ -367,8 +367,9 @@ func (ctxt *Link) traverseFuncAux(flag traverseFlag, fsym *LSym, fn func(parent
                        fn(fsym, d)
                }
        }
-       for _, f := range pc.File {
-               if filesym := ctxt.Lookup(f); filesym != nil {
+       files := ctxt.PosTable.FileTable()
+       for f := range pc.UsedFiles {
+               if filesym := ctxt.Lookup(files[f]); filesym != nil {
                        fn(fsym, filesym)
                }
        }
index 7c04b6d5ceea563600a3c35b18889f3c0ebd965a..e1c2fd5d5c1a851f42c6dbe7551bca1b5c4bead6 100644 (file)
@@ -135,7 +135,7 @@ func (f *goobjFile) PCToLine(pc uint64) (string, int, *gosym.Func) {
                        return "", 0, nil
                }
                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)
                _, err = f.f.ReadAt(pcline, s.Func.PCLine.Offset)
                if err != nil {
index 23c8346757139a5bdf57726dff91e5c3391329af..867d0ab069c9c209fb5451377d0a5ddcd2cdaf51 100644 (file)
@@ -163,8 +163,8 @@ func (t *PosTable) FileIndex(filename string) int {
        return -1
 }
 
-// DebugLinesFiles returns the file table for the debug_lines DWARF section.
-func (t *PosTable) DebugLinesFileTable() []string {
+// FileTable returns a slice of all files used to build this package.
+func (t *PosTable) FileTable() []string {
        // 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
        // N+1 in the debug_lines table.
index 50eebea47aa0384eab8414b9526572a0f26bd25b..dc237e72789be41e3c757112a7f53067068d386f 100644 (file)
@@ -1224,7 +1224,7 @@ func (d *dwctxt) writelines(unit *sym.CompilationUnit, lineProlog loader.Sym) []
 
        // Copy over the file table.
        fileNums := make(map[string]int)
-       for i, name := range unit.DWARFFileTable {
+       for i, name := range unit.FileTable {
                name := expandFile(name)
                if len(name) == 0 {
                        // Can't have empty filenames, and having a unique
index 606736e2719f4e4b0db38f9ae7e1faf88b4d6214..e5dfa837ba76699999a9cf2a584ee0e048c55193 100644 (file)
@@ -5,6 +5,7 @@
 package ld
 
 import (
+       "cmd/internal/goobj2"
        "cmd/internal/obj"
        "cmd/internal/objabi"
        "cmd/internal/src"
@@ -32,7 +33,7 @@ import (
 type oldPclnState struct {
        ldr            *loader.Loader
        deferReturnSym loader.Sym
-       numberedFiles  map[loader.Sym]int64
+       numberedFiles  map[string]int64
        filepaths      []string
 }
 
@@ -88,7 +89,7 @@ func makeOldPclnState(ctxt *Link) *oldPclnState {
        state := &oldPclnState{
                ldr:            ldr,
                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,
                // so that when we do a map lookup in numberedFiles fails, it will not
                // 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.
-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 {
                return val
        }
-       sn := state.ldr.SymName(file)
-       path := sn[len(src.FileSymPrefix):]
+       path := file
+       if strings.HasPrefix(path, src.FileSymPrefix) {
+               path = file[len(src.FileSymPrefix):]
+       }
        val := int64(len(state.filepaths))
        state.numberedFiles[file] = val
        state.filepaths = append(state.filepaths, expandGoroot(path))
        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 {
                return val
        }
        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.
        nf := fi.NumFile()
        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)
@@ -191,10 +199,10 @@ func (state *oldPclnState) renumberfiles(ctxt *Link, fi loader.FuncInfo, d *sym.
                if oldval == -1 {
                        val = -1
                } else {
-                       if oldval < 0 || oldval >= int32(nf) {
+                       if oldval < 0 || oldval >= int32(len(cu.FileTable)) {
                                log.Fatalf("bad pcdata %d", oldval)
                        }
-                       val = int32(state.fileVal(fi.File(int(oldval))))
+                       val = int32(state.fileVal(cu, oldval))
                }
 
                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
 // 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
        its := ldr.CreateExtSym("", 0)
        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
                // appears in the Pcfile table. In that case, this assigns
                // the outer file a number.
-               val := state.numberfile(call.File)
+               val := state.numberfile(cu, call.File)
                nameoff, ok := newState.funcNameOffset[call.Func]
                if !ok {
                        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)
                off = int32(ftab.SetUint32(ctxt.Arch, int64(off), deferreturn))
 
+               cu := ldr.SymUnit(s)
                if fi.Valid() {
                        pcsp = sym.Pcdata{P: fi.Pcsp()}
                        pcfile = sym.Pcdata{P: fi.Pcfile()}
                        pcline = sym.Pcdata{P: fi.Pcline()}
-                       oldState.renumberfiles(ctxt, fi, &pcfile)
+                       oldState.renumberfiles(ctxt, cu, fi, &pcfile)
                        if false {
                                // Sanity check the new numbering
                                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 {
-                       its := oldState.genInlTreeSym(fi, ctxt.Arch, state)
+                       its := oldState.genInlTreeSym(cu, fi, ctxt.Arch, state)
                        funcdata[objabi.FUNCDATA_InlTree] = its
                        pcdata[objabi.PCDATA_InlTreeIndex] = sym.Pcdata{P: fi.Pcinline()}
                }
index d56c748f9cadb9f021ea086520c84fd682a18d7f..882799e123ccdab4a864d5d0dbd3821c3fac0625 100644 (file)
@@ -1961,17 +1961,16 @@ func (fi *FuncInfo) NumFile() uint32 {
        return fi.lengths.NumFile
 }
 
-func (fi *FuncInfo) File(k int) Sym {
+func (fi *FuncInfo) File(k int) goobj2.CUFileIndex {
        if !fi.lengths.Initialized {
                panic("need to call Preload first")
        }
-       sr := (*goobj2.FuncInfo)(nil).ReadFile(fi.data, fi.lengths.FileOff, uint32(k))
-       return fi.l.resolve(fi.r, sr)
+       return (*goobj2.FuncInfo)(nil).ReadFile(fi.data, fi.lengths.FileOff, uint32(k))
 }
 
 type InlTreeNode struct {
        Parent   int32
-       File     Sym
+       File     goobj2.CUFileIndex
        Line     int32
        Func     Sym
        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))
        return InlTreeNode{
                Parent:   node.Parent,
-               File:     fi.l.resolve(fi.r, node.File),
+               File:     node.File,
                Line:     node.Line,
                Func:     fi.l.resolve(fi.r, node.Func),
                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()...)
 
        // DWARF file table
-       nfile := r.NDwarfFile()
-       unit.DWARFFileTable = make([]string, nfile)
-       for i := range unit.DWARFFileTable {
-               unit.DWARFFileTable[i] = r.DwarfFile(i)
+       nfile := r.NFile()
+       unit.FileTable = make([]string, nfile)
+       for i := range unit.FileTable {
+               unit.FileTable[i] = r.File(i)
        }
 
        l.addObj(lib.Pkg, or)
index dc37a36cba92760a605bf72964e6f230fbe06e74..5d7206db66e27b80ffe1c5a9944a9b954aaeeca4 100644 (file)
@@ -20,12 +20,12 @@ type LoaderSym int
 //
 // These are used for both DWARF and pclntab generation.
 type CompilationUnit struct {
-       Pkg            string        // The package name, eg ("fmt", or "runtime")
-       Lib            *Library      // Our library
-       PclnIndex      int           // Index of this CU in pclntab
-       PCs            []dwarf.Range // PC ranges, relative to Textp[0]
-       DWInfo         *dwarf.DWDie  // CU root DIE
-       DWARFFileTable []string      // The file table used to generate the .debug_lines
+       Pkg       string        // The package name, eg ("fmt", or "runtime")
+       Lib       *Library      // Our library
+       PclnIndex int           // Index of this CU in pclntab
+       PCs       []dwarf.Range // PC ranges, relative to Textp[0]
+       DWInfo    *dwarf.DWDie  // CU root DIE
+       FileTable []string      // The file table used in this compilation unit.
 
        Consts    LoaderSym   // Package constants DIEs
        FuncDIEs  []LoaderSym // Function DIE subtrees