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.
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),
}
}
+// 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
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]
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.
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.
}
}
}
+
+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)
+ }
+}