]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.link] cmd/link: support marking outer/sub for external loader.Sym
authorThan McIntosh <thanm@google.com>
Wed, 11 Dec 2019 19:17:14 +0000 (14:17 -0500)
committerThan McIntosh <thanm@google.com>
Wed, 18 Dec 2019 14:24:57 +0000 (14:24 +0000)
Add a loader mechanism for recording outer/sub relationships between
symbols without falling back on sym.Symbol. Also includes a new
"PrependSub" method that provides a way to chain a sub-symbol only the
list of an outer symbol (a common operation when manipulating
outer/sub relationships in the linker).

Change-Id: I70c72356945ceec2bacdcdc25bcc352bfb6765a1
Reviewed-on: https://go-review.googlesource.com/c/go/+/210777
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
src/cmd/link/internal/loader/loader.go
src/cmd/link/internal/loader/loader_test.go

index f238df7f5a17dd11244508e5e648deedb7d5a4e0..64ab6207982ca46e0662cc88fbc733147ea5fb19 100644 (file)
@@ -185,6 +185,14 @@ type Loader struct {
        attrCgoExportDynamic map[Sym]struct{} // "cgo_export_dynamic" symbols
        attrCgoExportStatic  map[Sym]struct{} // "cgo_export_static" symbols
 
+       // Outer and Sub relations for symbols.
+       // TODO: figure out whether it's more efficient to just have these
+       // as fields on extSymPayload (note that this won't be a viable
+       // strategy if somewhere in the linker we set sub/outer for a
+       // non-external sym).
+       outer map[Sym]Sym
+       sub   map[Sym]Sym
+
        // Used to implement field tracking; created during deadcode if
        // field tracking is enabled. Reachparent[K] contains the index of
        // the symbol that triggered the marking of symbol K as live.
@@ -220,6 +228,8 @@ func NewLoader(flags uint32) *Loader {
                objs:          []objIdx{{nil, 0, 0}},
                symsByName:    [2]map[string]Sym{make(map[string]Sym), make(map[string]Sym)},
                objByPkg:      make(map[string]*oReader),
+               outer:         make(map[Sym]Sym),
+               sub:           make(map[Sym]Sym),
                overwrite:     make(map[Sym]Sym),
                itablink:      make(map[Sym]struct{}),
                extStaticSyms: make(map[nameVer]Sym),
@@ -816,6 +826,34 @@ func (l *Loader) SetAttrCgoExportStatic(i Sym, v bool) {
        }
 }
 
+// AttrSubSymbol returns true for symbols that are listed as a
+// sub-symbol of some other outer symbol. The sub/outer mechanism is
+// used when loading host objects (sections from the host object
+// become regular linker symbols and symbols go on the Sub list of
+// their section) and for constructing the global offset table when
+// internally linking a dynamic executable.
+func (l *Loader) AttrSubSymbol(i Sym) bool {
+       // we don't explicitly store this attribute any more -- return
+       // a value based on the sub-symbol setting.
+       return l.OuterSym(i) != 0
+}
+
+// AttrContainer returns true for symbols that are listed as a
+// sub-symbol of some other outer symbol. The sub/outer mechanism is
+// used when loading host objects (sections from the host object
+// become regular linker symbols and symbols go on the Sub list of
+// their section) and for constructing the global offset table when
+// internally linking a dynamic executable.
+func (l *Loader) AttrContainer(i Sym) bool {
+       // we don't explicitly store this attribute any more -- return
+       // a value based on the sub-symbol setting.
+       return l.SubSym(i) != 0
+}
+
+// Note that we don't have SetAttrSubSymbol' or 'SetAttrContainer' methods
+// in the loader; clients should just use methods like PrependSub
+// to establish these relationships
+
 // Returns whether the i-th symbol has ReflectMethod attribute set.
 func (l *Loader) IsReflectMethod(i Sym) bool {
        return l.SymAttr(i)&goobj2.SymFlagReflectMethod != 0
@@ -916,6 +954,30 @@ func (l *Loader) ReadAuxSyms(symIdx Sym, dst []Sym) []Sym {
        return dst
 }
 
+// PrependSub prepends 'sub' onto the sub list for outer symbol 'outer'.
+// Will panic if 'sub' already has an outer sym or sub sym.
+// FIXME: should this be instead a method on SymbolBuilder?
+func (l *Loader) PrependSub(outer Sym, sub Sym) {
+       if l.Syms[outer] != nil {
+               panic("not implemented for sym.Symbol based syms")
+       }
+       // NB: this presupposes that an outer sym can't be a sub symbol of
+       // some other outer-outer sym (I'm assuming this is true, but I
+       // haven't tested exhaustively).
+       if l.OuterSym(outer) != 0 {
+               panic("outer has outer itself")
+       }
+       if l.SubSym(sub) != 0 {
+               panic("sub set for subsym")
+       }
+       if l.OuterSym(sub) != 0 {
+               panic("outer already set for subsym")
+       }
+       l.sub[sub] = l.sub[outer]
+       l.sub[outer] = sub
+       l.outer[sub] = outer
+}
+
 // OuterSym gets the outer symbol for host object loaded symbols.
 func (l *Loader) OuterSym(i Sym) Sym {
        sym := l.Syms[i]
@@ -923,7 +985,8 @@ func (l *Loader) OuterSym(i Sym) Sym {
                outer := sym.Outer
                return l.Lookup(outer.Name, int(outer.Version))
        }
-       return 0
+       // FIXME: add check for isExternal?
+       return l.outer[i]
 }
 
 // SubSym gets the subsymbol for host object loaded symbols.
@@ -933,7 +996,9 @@ func (l *Loader) SubSym(i Sym) Sym {
                sub := sym.Sub
                return l.Lookup(sub.Name, int(sub.Version))
        }
-       return 0
+       // NB: note -- no check for l.isExternal(), since I am pretty sure
+       // that later phases in the linker set subsym for "type." syms
+       return l.sub[i]
 }
 
 // Initialize Reachable bitmap and its siblings for running deadcode pass.
index ec3090bd5a31d6d7acfa7308037ed41d5c6cfc6a..0bfcfb59bc4518f69d2d06b62a43655fca8949b3 100644 (file)
@@ -110,3 +110,56 @@ func TestAddMaterializedSymbol(t *testing.T) {
                }
        }
 }
+
+func TestOuterSub(t *testing.T) {
+       ldr := NewLoader(0)
+       dummyOreader := oReader{version: -1}
+       or := &dummyOreader
+
+       // Populate loader with some symbols.
+       addDummyObjSym(t, ldr, or, "type.uint8")
+       es1 := ldr.AddExtSym("outer", 0)
+       es2 := ldr.AddExtSym("sub1", 0)
+       es3 := ldr.AddExtSym("sub2", 0)
+
+       // Should not have an outer sym initially
+       if ldr.OuterSym(es1) != 0 {
+               t.Errorf("es1 outer sym set ")
+       }
+       if ldr.SubSym(es2) != 0 {
+               t.Errorf("es2 outer sym set ")
+       }
+
+       // Establish first outer/sub relationship
+       ldr.PrependSub(es1, es2)
+       if ldr.OuterSym(es1) != 0 {
+               t.Errorf("ldr.OuterSym(es1) got %d wanted %d", ldr.OuterSym(es1), 0)
+       }
+       if ldr.OuterSym(es2) != es1 {
+               t.Errorf("ldr.OuterSym(es2) got %d wanted %d", ldr.OuterSym(es2), es1)
+       }
+       if ldr.SubSym(es1) != es2 {
+               t.Errorf("ldr.SubSym(es1) got %d wanted %d", ldr.SubSym(es1), es2)
+       }
+       if ldr.SubSym(es2) != 0 {
+               t.Errorf("ldr.SubSym(es2) got %d wanted %d", ldr.SubSym(es2), 0)
+       }
+
+       // Establish second outer/sub relationship
+       ldr.PrependSub(es1, es3)
+       if ldr.OuterSym(es1) != 0 {
+               t.Errorf("ldr.OuterSym(es1) got %d wanted %d", ldr.OuterSym(es1), 0)
+       }
+       if ldr.OuterSym(es2) != es1 {
+               t.Errorf("ldr.OuterSym(es2) got %d wanted %d", ldr.OuterSym(es2), es1)
+       }
+       if ldr.OuterSym(es3) != es1 {
+               t.Errorf("ldr.OuterSym(es3) got %d wanted %d", ldr.OuterSym(es3), es1)
+       }
+       if ldr.SubSym(es1) != es3 {
+               t.Errorf("ldr.SubSym(es1) got %d wanted %d", ldr.SubSym(es1), es3)
+       }
+       if ldr.SubSym(es3) != es2 {
+               t.Errorf("ldr.SubSym(es3) got %d wanted %d", ldr.SubSym(es3), es2)
+       }
+}