]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj: simplify filename handling
authorMatthew Dempsky <mdempsky@google.com>
Mon, 28 Aug 2023 12:13:03 +0000 (05:13 -0700)
committerGopher Robot <gobot@golang.org>
Fri, 1 Sep 2023 15:52:41 +0000 (15:52 +0000)
The old Go object file format used linker symbols like "gofile..foo"
to record references to the filename "foo". But the current object
file format has a dedicated section for file names, so we don't need
these useless prefixes anymore.

Also, change DWARF generation to pass around the src.Pos directly,
rather than the old file symbols, which it just turned back into a
file index before writing out anyway.

Finally, directly record the FileIndex into src.PosBase, so that we
can skip the map lookups.

Change-Id: Ia4a5ebfa95da271f2522e45befdb9f137c16d373
Reviewed-on: https://go-review.googlesource.com/c/go/+/523378
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Matthew Dempsky <mdempsky@google.com>

src/cmd/compile/internal/dwarfgen/dwinl.go
src/cmd/internal/dwarf/dwarf.go
src/cmd/internal/obj/dwarf.go
src/cmd/internal/obj/line.go
src/cmd/internal/obj/line_test.go
src/cmd/internal/obj/plist.go
src/cmd/internal/obj/sym.go
src/cmd/internal/src/pos.go
src/cmd/internal/src/xpos.go
src/cmd/internal/src/xpos_test.go
src/cmd/link/internal/ld/dwarf.go

index 08544fef6f7c60d26f4d99d2026993f5f6bac38c..92f339d3c6f8f0f4cb61e3b3215d6c9e2759bee3 100644 (file)
@@ -273,13 +273,11 @@ func insertInlCall(dwcalls *dwarf.InlCalls, inlIdx int, imap map[int]int) int {
        // Create new entry for this inline
        inlinedFn := base.Ctxt.InlTree.InlinedFunction(inlIdx)
        callXPos := base.Ctxt.InlTree.CallPos(inlIdx)
-       callPos := base.Ctxt.PosTable.Pos(callXPos)
-       callFileSym := base.Ctxt.Lookup(callPos.Base().SymFilename())
+       callPos := base.Ctxt.InnermostPos(callXPos)
        absFnSym := base.Ctxt.DwFixups.AbsFuncDwarfSym(inlinedFn)
        ic := dwarf.InlCall{
                InlIndex:  inlIdx,
-               CallFile:  callFileSym,
-               CallLine:  uint32(callPos.RelLine()),
+               CallPos:   callPos,
                AbsFunSym: absFnSym,
                Root:      parCallIdx == -1,
        }
index 86bc9e68236ab350682b1a06b07c3b5490daf6bf..c48b576fa04b7b7a59edecf9332d4a6aaad6908a 100644 (file)
@@ -9,6 +9,7 @@ package dwarf
 
 import (
        "bytes"
+       "cmd/internal/src"
        "errors"
        "fmt"
        "internal/buildcfg"
@@ -85,13 +86,12 @@ type Range struct {
 type FnState struct {
        Name          string
        Info          Sym
-       Filesym       Sym
        Loc           Sym
        Ranges        Sym
        Absfn         Sym
        StartPC       Sym
+       StartPos      src.Pos
        Size          int64
-       StartLine     int32
        External      bool
        Scopes        []Scope
        InlCalls      InlCalls
@@ -166,11 +166,8 @@ type InlCall struct {
        // index into ctx.InlTree describing the call inlined here
        InlIndex int
 
-       // Symbol of file containing inlined call site (really *obj.LSym).
-       CallFile Sym
-
-       // Line number of inlined call site.
-       CallLine uint32
+       // Position of the inlined call site.
+       CallPos src.Pos
 
        // Dwarf abstract subroutine symbol (really *obj.LSym).
        AbsFunSym Sym
@@ -202,7 +199,6 @@ type Context interface {
        RecordDclReference(from Sym, to Sym, dclIdx int, inlIndex int)
        RecordChildDieOffsets(s Sym, vars []*Var, offsets []int32)
        AddString(s Sym, v string)
-       AddFileRef(s Sym, f interface{})
        Logf(format string, args ...interface{})
 }
 
@@ -1246,7 +1242,8 @@ func PutAbstractFunc(ctxt Context, s *FnState) error {
        // DW_AT_inlined value
        putattr(ctxt, s.Absfn, abbrev, DW_FORM_data1, DW_CLS_CONSTANT, int64(DW_INL_inlined), nil)
 
-       putattr(ctxt, s.Absfn, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(s.StartLine), nil)
+       // TODO(mdempsky): Shouldn't we write out StartPos.FileIndex() too?
+       putattr(ctxt, s.Absfn, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(s.StartPos.RelLine()), nil)
 
        var ev int64
        if s.External {
@@ -1335,9 +1332,9 @@ func putInlinedFunc(ctxt Context, s *FnState, callIdx int) error {
        }
 
        // Emit call file, line attrs.
-       ctxt.AddFileRef(s.Info, ic.CallFile)
+       putattr(ctxt, s.Info, abbrev, DW_FORM_data4, DW_CLS_CONSTANT, int64(1+ic.CallPos.FileIndex()), nil) // 1-based file table
        form := int(expandPseudoForm(DW_FORM_udata_pseudo))
-       putattr(ctxt, s.Info, abbrev, form, DW_CLS_CONSTANT, int64(ic.CallLine), nil)
+       putattr(ctxt, s.Info, abbrev, form, DW_CLS_CONSTANT, int64(ic.CallPos.RelLine()), nil)
 
        // Variables associated with this inlined routine instance.
        vars := ic.InlVars
@@ -1438,8 +1435,8 @@ func PutDefaultFunc(ctxt Context, s *FnState, isWrapper bool) error {
        if isWrapper {
                putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0)
        } else {
-               ctxt.AddFileRef(s.Info, s.Filesym)
-               putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(s.StartLine), nil)
+               putattr(ctxt, s.Info, abbrev, DW_FORM_data4, DW_CLS_CONSTANT, int64(1+s.StartPos.FileIndex()), nil) // 1-based file index
+               putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(s.StartPos.RelLine()), nil)
 
                var ev int64
                if s.External {
index 825f0133f1aa651efb45a06a414b95fceecbd93d..f5caa08f0a2b0c9ab1b3fcdeab72a492ebbb0769 100644 (file)
@@ -48,7 +48,7 @@ func (ctxt *Link) generateDebugLinesSymbol(s, lines *LSym) {
        line := int64(1)
        pc := s.Func().Text.Pc
        var lastpc int64 // last PC written to line table, not last PC in func
-       name := ""
+       fileIndex := 1
        prologue, wrotePrologue := false, false
        // Walk the progs, generating the DWARF table.
        for p := s.Func().Text; p != nil; p = p.Link {
@@ -58,15 +58,15 @@ func (ctxt *Link) generateDebugLinesSymbol(s, lines *LSym) {
                        continue
                }
                newStmt := p.Pos.IsStmt() != src.PosNotStmt
-               newName, newLine := ctxt.getFileSymbolAndLine(p.Pos)
+               newFileIndex, newLine := ctxt.getFileIndexAndLine(p.Pos)
+               newFileIndex++ // 1 indexing for the table
 
                // Output debug info.
                wrote := false
-               if name != newName {
-                       newFile := ctxt.PosTable.FileIndex(newName) + 1 // 1 indexing for the table.
+               if newFileIndex != fileIndex {
                        dctxt.AddUint8(lines, dwarf.DW_LNS_set_file)
-                       dwarf.Uleb128put(dctxt, lines, int64(newFile))
-                       name = newName
+                       dwarf.Uleb128put(dctxt, lines, int64(newFileIndex))
+                       fileIndex = newFileIndex
                        wrote = true
                }
                if prologue && !wrotePrologue {
@@ -258,16 +258,6 @@ func (c dwCtxt) AddDWARFAddrSectionOffset(s dwarf.Sym, t interface{}, ofs int64)
        r.Type = objabi.R_DWARFSECREF
 }
 
-func (c dwCtxt) AddFileRef(s dwarf.Sym, f interface{}) {
-       ls := s.(*LSym)
-       rsym := f.(*LSym)
-       fidx := c.Link.PosTable.FileIndex(rsym.Name)
-       // Note the +1 here -- the value we're writing is going to be an
-       // index into the DWARF line table file section, whose entries
-       // are numbered starting at 1, not 0.
-       ls.WriteInt(c.Link, ls.Size, 4, int64(fidx+1))
-}
-
 func (c dwCtxt) CurrentOffset(s dwarf.Sym) int64 {
        ls := s.(*LSym)
        return ls.Size
@@ -329,17 +319,13 @@ func (s *LSym) Length(dwarfContext interface{}) int64 {
        return s.Size
 }
 
-// fileSymbol returns a symbol corresponding to the source file of the
-// first instruction (prog) of the specified function. This will
-// presumably be the file in which the function is defined.
-func (ctxt *Link) fileSymbol(fn *LSym) *LSym {
-       p := fn.Func().Text
-       if p != nil {
-               f, _ := ctxt.getFileSymbolAndLine(p.Pos)
-               fsym := ctxt.Lookup(f)
-               return fsym
+// textPos returns the source position of the first instruction (prog)
+// of the specified function.
+func textPos(fn *LSym) src.XPos {
+       if p := fn.Func().Text; p != nil {
+               return p.Pos
        }
-       return nil
+       return src.NoXPos
 }
 
 // populateDWARF fills in the DWARF Debugging Information Entries for
@@ -362,17 +348,19 @@ func (ctxt *Link) populateDWARF(curfn Func, s *LSym) {
        }
        var err error
        dwctxt := dwCtxt{ctxt}
-       filesym := ctxt.fileSymbol(s)
+       startPos := ctxt.InnermostPos(textPos(s))
+       if !startPos.IsKnown() || startPos.RelLine() != uint(s.Func().StartLine) {
+               panic("bad startPos")
+       }
        fnstate := &dwarf.FnState{
                Name:          s.Name,
                Info:          info,
-               Filesym:       filesym,
                Loc:           loc,
                Ranges:        ranges,
                Absfn:         absfunc,
                StartPC:       s,
                Size:          s.Size,
-               StartLine:     s.Func().StartLine,
+               StartPos:      startPos,
                External:      !s.Static(),
                Scopes:        scopes,
                InlCalls:      inlcalls,
@@ -434,13 +422,12 @@ func (ctxt *Link) DwarfAbstractFunc(curfn Func, s *LSym) {
                s.NewFuncInfo()
        }
        scopes, _ := ctxt.DebugInfo(s, absfn, curfn)
-       _, startLine := ctxt.getFileSymbolAndLine(curfn.Pos())
        dwctxt := dwCtxt{ctxt}
        fnstate := dwarf.FnState{
                Name:          s.Name,
                Info:          absfn,
                Absfn:         absfn,
-               StartLine:     startLine,
+               StartPos:      ctxt.InnermostPos(curfn.Pos()),
                External:      !s.Static(),
                Scopes:        scopes,
                UseBASEntries: ctxt.UseBASEntries,
index 20f03d985340fe63876932a4c1cc134a3fd16b4d..988640f6a4e8ca7355aa5f641b2967275bb7dc85 100644 (file)
@@ -14,22 +14,14 @@ func (ctxt *Link) AddImport(pkg string, fingerprint goobj.FingerprintType) {
        ctxt.Imports = append(ctxt.Imports, goobj.ImportedPkg{Pkg: pkg, Fingerprint: fingerprint})
 }
 
-// getFileSymbolAndLine returns the relative file symbol and relative line
-// number for a position (i.e., as adjusted by a //line directive). This is the
-// file/line visible in the final binary (pcfile, pcln, etc).
-func (ctxt *Link) getFileSymbolAndLine(xpos src.XPos) (f string, l int32) {
-       pos := ctxt.InnermostPos(xpos)
-       if !pos.IsKnown() {
-               pos = src.Pos{}
-       }
-       return pos.SymFilename(), int32(pos.RelLine())
-}
-
 // getFileIndexAndLine returns the relative file index (local to the CU), and
 // the relative line number for a position (i.e., as adjusted by a //line
 // directive). This is the file/line visible in the final binary (pcfile, pcln,
 // etc).
 func (ctxt *Link) getFileIndexAndLine(xpos src.XPos) (int, int32) {
-       f, l := ctxt.getFileSymbolAndLine(xpos)
-       return ctxt.PosTable.FileIndex(f), l
+       pos := ctxt.InnermostPos(xpos)
+       if !pos.IsKnown() {
+               pos = src.Pos{}
+       }
+       return pos.FileIndex(), int32(pos.RelLine())
 }
index d3bb4e2639ecdb1bd90eaa418ce741a45504b94b..de7ef1a22eb1c97645fe46f49d9866e83a7d09ea 100644 (file)
@@ -31,9 +31,15 @@ func TestGetFileSymbolAndLine(t *testing.T) {
        }
 
        for _, test := range tests {
-               f, l := ctxt.getFileSymbolAndLine(ctxt.PosTable.XPos(test.pos))
-               got := fmt.Sprintf("%s:%d", f, l)
-               if got != src.FileSymPrefix+test.want {
+               fileIndex, line := ctxt.getFileIndexAndLine(ctxt.PosTable.XPos(test.pos))
+
+               file := "??"
+               if fileIndex >= 0 {
+                       file = ctxt.PosTable.FileTable()[fileIndex]
+               }
+               got := fmt.Sprintf("%s:%d", file, line)
+
+               if got != test.want {
                        t.Errorf("ctxt.getFileSymbolAndLine(%v) = %q, want %q", test.pos, got, test.want)
                }
        }
index cd6e2313ad7aa9a1f55c2d8e0ccde27902a063d7..9cf6a20bdb77c54b8b790abb4e695eaf95c4e890 100644 (file)
@@ -198,7 +198,7 @@ func (ctxt *Link) InitTextSym(s *LSym, flag int, start src.XPos) {
        // startLine should be the same line number that would be displayed via
        // pcln, etc for the declaration (i.e., relative line number, as
        // adjusted by //line).
-       _, startLine := ctxt.getFileSymbolAndLine(start)
+       _, startLine := ctxt.getFileIndexAndLine(start)
 
        s.Func().FuncID = objabi.GetFuncID(s.Name, flag&WRAPPER != 0 || flag&ABIWRAPPER != 0)
        s.Func().FuncFlag = ctxt.toFuncFlag(flag)
index 63d7d22e3333b3e1559dfb7ee9e0210f0480beb6..f27d4ef4fcca5b20b11a40ffa47d4a0a7ea1aad1 100644 (file)
@@ -449,10 +449,6 @@ func (ctxt *Link) traverseFuncAux(flag traverseFlag, fsym *LSym, fn func(parent
                if call.Func != nil {
                        fn(fsym, call.Func)
                }
-               f, _ := ctxt.getFileSymbolAndLine(call.Pos)
-               if filesym := ctxt.Lookup(f); filesym != nil {
-                       fn(fsym, filesym)
-               }
        }
 
        auxsyms := []*LSym{fninfo.dwarfRangesSym, fninfo.dwarfLocSym, fninfo.dwarfDebugLinesSym, fninfo.dwarfInfoSym, fninfo.WasmImportSym, fninfo.sehUnwindInfoSym}
index 6f1c7dddbcf6c8128835a02652e76d0467cc3b84..4d71c8190a8f83f8eb398bcb3f57d9bd51bb1f2e 100644 (file)
@@ -116,9 +116,9 @@ func (p Pos) RelCol() uint {
 // AbsFilename() returns the absolute filename recorded with the position's base.
 func (p Pos) AbsFilename() string { return p.base.AbsFilename() }
 
-// SymFilename() returns the absolute filename recorded with the position's base,
-// prefixed by FileSymPrefix to make it appropriate for use as a linker symbol.
-func (p Pos) SymFilename() string { return p.base.SymFilename() }
+// FileIndex returns the file index of the position's base's absolute
+// filename within the PosTable that it was registered.
+func (p Pos) FileIndex() int { return p.base.FileIndex() }
 
 func (p Pos) String() string {
        return p.Format(true, true)
@@ -193,9 +193,9 @@ type PosBase struct {
        pos         Pos    // position at which the relative position is (line, col)
        filename    string // file name used to open source file, for error messages
        absFilename string // absolute file name, for PC-Line tables
-       symFilename string // cached symbol file name, to avoid repeated string concatenation
        line, col   uint   // relative line, column number at pos
        inl         int    // inlining index (see cmd/internal/obj/inl.go)
+       fileIndex   int    // index of absFilename within PosTable.FileTable
 }
 
 // NewFileBase returns a new *PosBase for a file with the given (relative and
@@ -204,10 +204,10 @@ func NewFileBase(filename, absFilename string) *PosBase {
        base := &PosBase{
                filename:    filename,
                absFilename: absFilename,
-               symFilename: FileSymPrefix + absFilename,
                line:        1,
                col:         1,
                inl:         -1,
+               fileIndex:   -1,
        }
        base.pos = MakePos(base, 1, 1)
        return base
@@ -220,24 +220,22 @@ func NewFileBase(filename, absFilename string) *PosBase {
 //
 // at position pos.
 func NewLinePragmaBase(pos Pos, filename, absFilename string, line, col uint) *PosBase {
-       return &PosBase{pos, filename, absFilename, FileSymPrefix + absFilename, line, col, -1}
+       return &PosBase{pos, filename, absFilename, line, col, -1, -1}
 }
 
-// NewInliningBase returns a copy of the old PosBase with the given inlining
-// index. If old == nil, the resulting PosBase has no filename.
-func NewInliningBase(old *PosBase, inlTreeIndex int) *PosBase {
-       if old == nil {
-               base := &PosBase{line: 1, col: 1, inl: inlTreeIndex}
-               base.pos = MakePos(base, 1, 1)
-               return base
+// NewInliningBase returns a copy of the orig PosBase with the given inlining
+// index. If orig == nil, NewInliningBase panics.
+func NewInliningBase(orig *PosBase, inlTreeIndex int) *PosBase {
+       if orig == nil {
+               panic("no old PosBase")
        }
-       copy := *old
-       base := &copy
+       base := *orig
        base.inl = inlTreeIndex
-       if old == old.pos.base {
-               base.pos.base = base
+       base.fileIndex = -1
+       if orig == orig.pos.base {
+               base.pos.base = &base
        }
-       return base
+       return &base
 }
 
 var noPos Pos
@@ -269,16 +267,21 @@ func (b *PosBase) AbsFilename() string {
        return ""
 }
 
+// FileSymPrefix is the linker symbol prefix that used to be used for
+// linker pseudo-symbols representing file names.
 const FileSymPrefix = "gofile.."
 
-// SymFilename returns the absolute filename recorded with the base,
-// prefixed by FileSymPrefix to make it appropriate for use as a linker symbol.
-// If b is nil, SymFilename returns FileSymPrefix + "??".
-func (b *PosBase) SymFilename() string {
+// FileIndex returns the index of the base's absolute filename within
+// its PosTable's FileTable. It panics if it hasn't been registered
+// with a PosTable. If b == nil, the result is -1.
+func (b *PosBase) FileIndex() int {
        if b != nil {
-               return b.symFilename
+               if b.fileIndex < 0 {
+                       panic("PosBase has no file index")
+               }
+               return b.fileIndex
        }
-       return FileSymPrefix + "??"
+       return -1
 }
 
 // Line returns the line number recorded with the base.
index 867d0ab069c9c209fb5451377d0a5ddcd2cdaf51..a74505997d2cfd7a65d8d2af57e13560f7a09f5f 100644 (file)
@@ -124,25 +124,40 @@ type PosTable struct {
 // XPos returns the corresponding XPos for the given pos,
 // adding pos to t if necessary.
 func (t *PosTable) XPos(pos Pos) XPos {
-       m := t.indexMap
-       if m == nil {
-               // Create new list and map and populate with nil
-               // base so that NoPos always gets index 0.
+       return XPos{t.baseIndex(pos.base), pos.lico}
+}
+
+func (t *PosTable) baseIndex(base *PosBase) int32 {
+       if base == nil {
+               return 0
+       }
+
+       if i, ok := t.indexMap[base]; ok {
+               return int32(i)
+       }
+
+       if base.fileIndex >= 0 {
+               panic("PosBase already registered with a PosTable")
+       }
+
+       if t.indexMap == nil {
                t.baseList = append(t.baseList, nil)
-               m = map[*PosBase]int{nil: 0}
-               t.indexMap = m
+               t.indexMap = make(map[*PosBase]int)
                t.nameMap = make(map[string]int)
        }
-       i, ok := m[pos.base]
+
+       i := len(t.baseList)
+       t.indexMap[base] = i
+       t.baseList = append(t.baseList, base)
+
+       fileIndex, ok := t.nameMap[base.absFilename]
        if !ok {
-               i = len(t.baseList)
-               t.baseList = append(t.baseList, pos.base)
-               t.indexMap[pos.base] = i
-               if _, ok := t.nameMap[pos.base.symFilename]; !ok {
-                       t.nameMap[pos.base.symFilename] = len(t.nameMap)
-               }
+               fileIndex = len(t.nameMap)
+               t.nameMap[base.absFilename] = fileIndex
        }
-       return XPos{int32(i), pos.lico}
+       base.fileIndex = fileIndex
+
+       return int32(i)
 }
 
 // Pos returns the corresponding Pos for the given p.
@@ -155,14 +170,6 @@ func (t *PosTable) Pos(p XPos) Pos {
        return Pos{base, p.lico}
 }
 
-// FileIndex returns the index of the given filename(symbol) in the PosTable, or -1 if not found.
-func (t *PosTable) FileIndex(filename string) int {
-       if v, ok := t.nameMap[filename]; ok {
-               return v
-       }
-       return -1
-}
-
 // 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
index a17ba63d2a0afc66e094c3972c4e52331b937a5d..f76de9dbc2378e307f8b804919fa21dc38f2fc02 100644 (file)
@@ -62,8 +62,8 @@ func TestConversion(t *testing.T) {
                }
        }
 
-       if len(tab.baseList) != len(tab.indexMap) {
-               t.Errorf("table length discrepancy: %d != %d", len(tab.baseList), len(tab.indexMap))
+       if len(tab.baseList) != 1+len(tab.indexMap) { // indexMap omits nil
+               t.Errorf("table length discrepancy: %d != 1+%d", len(tab.baseList), len(tab.indexMap))
        }
 
        const wantLen = 4
index 23285de2e1d8d84e996062e193b6752b14ace81f..36e11cc0d282682421eb1570c99626c6dcfe21ca 100644 (file)
@@ -154,10 +154,6 @@ func (c dwctxt) Logf(format string, args ...interface{}) {
 
 // At the moment these interfaces are only used in the compiler.
 
-func (c dwctxt) AddFileRef(s dwarf.Sym, f interface{}) {
-       panic("should be used only in the compiler")
-}
-
 func (c dwctxt) CurrentOffset(s dwarf.Sym) int64 {
        panic("should be used only in the compiler")
 }