We're going to use the linker's symbol versions to track ABIs.
Currently, version 0 is used for global symbols and version > 0 is
used for file-local symbols. This CL reserves versions 0 to 9 for
global symbols with ABIs and uses version 10 and up for file-local
symbols. To make this clean, it also introduces a method on Symbol for
querying whether it's file-local.
For #27539.
Change-Id: Id3bc7369268f35128b14318a62e86335181a80e5
Reviewed-on: https://go-review.googlesource.com/c/146859
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Heschi Kreinick <heschi@google.com>
// (https://sourceware.org/bugzilla/show_bug.cgi?id=18270). So
// we convert the adrp; ld64 + R_ARM64_GOTPCREL into adrp;
// add + R_ADDRARM64.
- if !(r.Sym.Version != 0 || r.Sym.Attr.VisibilityHidden() || r.Sym.Attr.Local()) && r.Sym.Type == sym.STEXT && ctxt.DynlinkingGo() {
+ if !(r.Sym.IsFileLocal() || r.Sym.Attr.VisibilityHidden() || r.Sym.Attr.Local()) && r.Sym.Type == sym.STEXT && ctxt.DynlinkingGo() {
if o2&0xffc00000 != 0xf9400000 {
ld.Errorf(s, "R_ARM64_GOTPCREL against unexpected instruction %x", o2)
}
// If the symbol does not exist, it creates it if create is true,
// or returns nil otherwise.
func dwarfFuncSym(ctxt *Link, s *sym.Symbol, meta string, create bool) *sym.Symbol {
+ // All function ABIs use symbol version 0 for the DWARF data.
+ //
+ // TODO(austin): It may be useful to have DWARF info for ABI
+ // wrappers, in which case we may want these versions to
+ // align. Better yet, replace these name lookups with a
+ // general way to attach metadata to a symbol.
+ ver := 0
+ if s.IsFileLocal() {
+ ver = int(s.Version)
+ }
if create {
- return ctxt.Syms.Lookup(meta+s.Name, int(s.Version))
+ return ctxt.Syms.Lookup(meta+s.Name, ver)
}
- return ctxt.Syms.ROLookup(meta+s.Name, int(s.Version))
+ return ctxt.Syms.ROLookup(meta+s.Name, ver)
}
func dotypedef(ctxt *Link, parent *dwarf.DWDie, name string, def *dwarf.DWDie) *dwarf.DWDie {
}
dv := newdie(ctxt, ctxt.compUnitByPackage[lib].dwinfo, dwarf.DW_ABRV_VARIABLE, str, int(s.Version))
newabslocexprattr(dv, v, s)
- if s.Version == 0 {
+ if !s.IsFileLocal() {
newattr(dv, dwarf.DW_AT_external, dwarf.DW_CLS_FLAG, 1, 0)
}
dt := defgotype(ctxt, gotype)
if s.Attr.NotInSymbolTable() {
continue
}
- if (s.Name == "" || s.Name[0] == '.') && s.Version == 0 && s.Name != ".rathole" && s.Name != ".TOC." {
+ if (s.Name == "" || s.Name[0] == '.') && !s.IsFileLocal() && s.Name != ".rathole" && s.Name != ".TOC." {
continue
}
switch s.Type {
}
}
class := IMAGE_SYM_CLASS_EXTERNAL
- if s.Version != 0 || s.Attr.VisibilityHidden() || s.Attr.Local() {
+ if s.IsFileLocal() || s.Attr.VisibilityHidden() || s.Attr.Local() {
class = IMAGE_SYM_CLASS_STATIC
}
f.writeSymbol(ctxt.Out, s, value, sect, typ, uint8(class))
// maybe one day STB_WEAK.
bind := STB_GLOBAL
- if x.Version != 0 || x.Attr.VisibilityHidden() || x.Attr.Local() {
+ if x.IsFileLocal() || x.Attr.VisibilityHidden() || x.Attr.Local() {
bind = STB_LOCAL
}
t := int(typ)
switch typ {
case TextSym, DataSym, BSSSym:
- if x.Version != 0 {
+ if x.IsFileLocal() {
t += 'a' - 'A'
}
fallthrough
elftype elf.SymType
}
+const (
+ SymVerStatic = 10 // Minimum version used by static (file-local) syms
+)
+
func (s *Symbol) String() string {
if s.Version == 0 {
return s.Name
return fmt.Sprintf("%s<%d>", s.Name, s.Version)
}
+func (s *Symbol) IsFileLocal() bool {
+ return s.Version >= SymVerStatic
+}
+
func (s *Symbol) ElfsymForReloc() int32 {
// If putelfsym created a local version of this symbol, use that in all
// relocations.
}
func NewSymbols() *Symbols {
+ hash := make([]map[string]*Symbol, SymVerStatic)
+ // Preallocate about 2mb for hash of non static symbols
+ hash[0] = make(map[string]*Symbol, 100000)
return &Symbols{
- hash: []map[string]*Symbol{
- // preallocate about 2mb for hash of
- // non static symbols
- make(map[string]*Symbol, 100000),
- },
+ hash: hash,
Allsym: make([]*Symbol, 0, 100000),
}
}