]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.link] cmd/link: implement symbol overwrite logic
authorCherry Zhang <cherryyz@google.com>
Tue, 8 Oct 2019 19:35:36 +0000 (15:35 -0400)
committerCherry Zhang <cherryyz@google.com>
Tue, 15 Oct 2019 18:55:59 +0000 (18:55 +0000)
If two defined symbols have the same name, one contentless and
one with content, the one with content "wins". This is mainly for
go:linkname on data symbols. Support this logic in newobj mode.

Introduce an "overwrite" mechanism, letting one symbol overwrite
another. This machanism could later be used for the linker
overwriting symbol contents (e.g. -X flag).

Change-Id: I32ee7d4b82df275f11b38c3abefc99b878ff12d7
Reviewed-on: https://go-review.googlesource.com/c/go/+/200097
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
src/cmd/link/internal/objfile/objfile2.go

index c48cf960748a6ee3dd82b85e36534306f067d6dc..b37a665f43b00c092b51862758aef31e90afb02e 100644 (file)
@@ -97,6 +97,7 @@ type Loader struct {
        extSyms  []nameVer        // externally defined symbols
 
        symsByName map[nameVer]Sym // map symbol name to index
+       overwrite  map[Sym]Sym     // overwrite[i]=j if symbol j overwrites symbol i
 
        objByPkg map[string]*oReader // map package path to its Go object reader
 
@@ -111,6 +112,7 @@ func NewLoader() *Loader {
                objs:       []objIdx{{nil, 0}},
                symsByName: make(map[nameVer]Sym),
                objByPkg:   make(map[string]*oReader),
+               overwrite:  make(map[Sym]Sym),
        }
 }
 
@@ -137,16 +139,34 @@ func (l *Loader) AddObj(pkg string, r *oReader) Sym {
 }
 
 // Add a symbol with a given index, return if it is added.
-func (l *Loader) AddSym(name string, ver int, i Sym, dupok bool) bool {
+func (l *Loader) AddSym(name string, ver int, i Sym, r *oReader, dupok bool, typ sym.SymKind) bool {
        if l.extStart != 0 {
                panic("AddSym called after AddExtSym is called")
        }
        nv := nameVer{name, ver}
-       if _, ok := l.symsByName[nv]; ok {
-               if dupok || true { // TODO: "true" isn't quite right. need to implement "overwrite" logic.
+       if oldi, ok := l.symsByName[nv]; ok {
+               if dupok {
+                       return false
+               }
+               overwrite := r.DataSize(int(i-l.StartIndex(r))) != 0
+               if overwrite {
+                       // new symbol overwrites old symbol.
+                       oldr, li := l.ToLocal(oldi)
+                       oldsym := goobj2.Sym{}
+                       oldsym.Read(oldr.Reader, oldr.SymOff(li))
+                       oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type)]
+                       if oldsym.Flag&goobj2.SymFlagDupok == 0 && !((oldtyp == sym.SDATA || oldtyp == sym.SNOPTRDATA || oldtyp == sym.SBSS || oldtyp == sym.SNOPTRBSS) && oldr.DataSize(li) == 0) { // only allow overwriting 0-sized data symbol
+                               log.Fatalf("duplicated definition of symbol " + name)
+                       }
+                       l.overwrite[oldi] = i
+               } else {
+                       // old symbol overwrites new symbol.
+                       if typ != sym.SDATA && typ != sym.SNOPTRDATA && typ != sym.SBSS && typ != sym.SNOPTRBSS { // only allow overwriting data symbol
+                               log.Fatalf("duplicated definition of symbol " + name)
+                       }
+                       l.overwrite[i] = oldi
                        return false
                }
-               panic("duplicated definition of symbol " + name)
        }
        l.symsByName[nv] = i
        return true
@@ -171,11 +191,18 @@ func (l *Loader) AddExtSym(name string, ver int) Sym {
 
 // Convert a local index to a global index.
 func (l *Loader) ToGlobal(r *oReader, i int) Sym {
-       return l.StartIndex(r) + Sym(i)
+       g := l.StartIndex(r) + Sym(i)
+       if ov, ok := l.overwrite[g]; ok {
+               return ov
+       }
+       return g
 }
 
 // Convert a global index to a local index.
 func (l *Loader) ToLocal(i Sym) (*oReader, int) {
+       if ov, ok := l.overwrite[i]; ok {
+               i = ov
+       }
        if l.extStart != 0 && i >= l.extStart {
                return nil, int(i - l.extStart)
        }
@@ -389,7 +416,7 @@ func LoadNew(l *Loader, arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, lib *s
                }
                v := abiToVer(osym.ABI, localSymVersion)
                dupok := osym.Flag&goobj2.SymFlagDupok != 0
-               l.AddSym(name, v, istart+Sym(i), dupok)
+               l.AddSym(name, v, istart+Sym(i), or, dupok, sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)])
        }
 
        // The caller expects us consuming all the data