From 47cac82e36d08198afac646c3f46d24255cf9d61 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Mon, 20 Apr 2020 18:42:35 -0400 Subject: [PATCH] [dev.link] cmd/link: convert symtab pass to new style This is more or less a direct translation, to get things going. There are more things we can do to make it better, especially on the handling of container symbols. Change-Id: I11a0087e402be8d42b9d06869385ead531755272 Reviewed-on: https://go-review.googlesource.com/c/go/+/229125 Run-TryBot: Cherry Zhang TryBot-Result: Gobot Gobot Reviewed-by: Than McIntosh Reviewed-by: Jeremy Faller --- src/cmd/link/internal/ld/data.go | 32 +- src/cmd/link/internal/ld/lib.go | 32 +- src/cmd/link/internal/ld/main.go | 4 +- src/cmd/link/internal/ld/pcln.go | 12 +- src/cmd/link/internal/ld/symtab.go | 413 +++++++++--------- src/cmd/link/internal/loader/loader.go | 42 +- src/cmd/link/internal/loader/symbolbuilder.go | 5 + 7 files changed, 292 insertions(+), 248 deletions(-) diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index dd49526ddd5..204c2377943 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -1145,26 +1145,26 @@ func Addstring(s *sym.Symbol, str string) int64 { // addgostring adds str, as a Go string value, to s. symname is the name of the // symbol used to define the string data and must be unique per linked object. -func addgostring(ctxt *Link, s *sym.Symbol, symname, str string) { - sdata := ctxt.Syms.Lookup(symname, 0) - if sdata.Type != sym.Sxxx { - Errorf(s, "duplicate symname in addgostring: %s", symname) +func addgostring(ctxt *Link, ldr *loader.Loader, s *loader.SymbolBuilder, symname, str string) { + sdata := ldr.CreateSymForUpdate(symname, 0) + if sdata.Type() != sym.Sxxx { + ctxt.Errorf(s.Sym(), "duplicate symname in addgostring: %s", symname) } - sdata.Attr |= sym.AttrReachable - sdata.Attr |= sym.AttrLocal - sdata.Type = sym.SRODATA - sdata.Size = int64(len(str)) - sdata.P = []byte(str) - s.AddAddr(ctxt.Arch, sdata) + sdata.SetReachable(true) + sdata.SetLocal(true) + sdata.SetType(sym.SRODATA) + sdata.SetSize(int64(len(str))) + sdata.SetData([]byte(str)) + s.AddAddr(ctxt.Arch, sdata.Sym()) s.AddUint(ctxt.Arch, uint64(len(str))) } -func addinitarrdata(ctxt *Link, s *sym.Symbol) { - p := s.Name + ".ptr" - sp := ctxt.Syms.Lookup(p, 0) - sp.Type = sym.SINITARR - sp.Size = 0 - sp.Attr |= sym.AttrDuplicateOK +func addinitarrdata(ctxt *Link, ldr *loader.Loader, s loader.Sym) { + p := ldr.SymName(s) + ".ptr" + sp := ldr.CreateSymForUpdate(p, 0) + sp.SetType(sym.SINITARR) + sp.SetSize(0) + sp.SetDuplicateOK(true) sp.AddAddr(ctxt.Arch, s) } diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index b71bef22f48..9c87ab15a1c 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -2627,6 +2627,16 @@ func (ctxt *Link) xdefine(p string, t sym.SymKind, v int64) { s.Attr |= sym.AttrLocal } +func (ctxt *Link) xdefine2(p string, t sym.SymKind, v int64) { + ldr := ctxt.loader + s := ldr.CreateSymForUpdate(p, 0) + s.SetType(t) + s.SetValue(v) + s.SetReachable(true) + s.SetSpecial(true) + s.SetLocal(true) +} + func datoff(s *sym.Symbol, addr int64) int64 { if uint64(addr) >= Segdata.Vaddr { return int64(uint64(addr) - Segdata.Vaddr + Segdata.Fileoff) @@ -2816,10 +2826,6 @@ func (ctxt *Link) loadlibfull() { // Set special global symbols. ctxt.setArchSyms(AfterLoadlibFull) - // Convert special symbols created by pcln. - pclntabFirstFunc = ctxt.loader.Syms[pclntabFirstFunc2] - pclntabLastFunc = ctxt.loader.Syms[pclntabLastFunc2] - // Populate dwarfp from dwarfp2. If we see a symbol index // whose loader.Syms entry is nil, something went wrong. for _, si := range dwarfp2 { @@ -2834,11 +2840,27 @@ func (ctxt *Link) loadlibfull() { } dwarfp = append(dwarfp, dwarfSecInfo2{syms: syms}) } + + // For now, overwrite symbol type with its "group" type, as dodata + // expected. Once we converted dodata, this will probably not be + // needed. + for i, t := range symGroupType { + if t != sym.Sxxx { + ctxt.loader.Syms[i].Type = t + } + } + symGroupType = nil + + if ctxt.Debugvlog > 1 { + // loadlibfull is likely a good place to dump. + // Only dump under -v=2 and above. + ctxt.dumpsyms() + } } func (ctxt *Link) dumpsyms() { for _, s := range ctxt.Syms.Allsym { - fmt.Printf("%s %s %p %v %v\n", s, s.Type, s, s.Attr.Reachable(), s.Attr.OnList()) + fmt.Printf("%s %s reachable=%v onlist=%v outer=%v sub=%v\n", s, s.Type, s.Attr.Reachable(), s.Attr.OnList(), s.Outer, s.Sub) for i := range s.R { fmt.Println("\t", s.R[i].Type, s.R[i].Sym) } diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index 4735b91b352..32a2eff2b5f 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -300,10 +300,10 @@ func Main(arch *sys.Arch, theArch Arch) { ctxt.findfunctab(container) bench.Start("dwarfGenerateDebugSyms") dwarfGenerateDebugSyms(ctxt) - bench.Start("loadlibfull") - ctxt.loadlibfull() // XXX do it here for now bench.Start("symtab") ctxt.symtab() + bench.Start("loadlibfull") + ctxt.loadlibfull() // XXX do it here for now bench.Start("dodata") ctxt.dodata() bench.Start("address") diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 75fb828bef5..00c29c63e07 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -234,10 +234,8 @@ func (state *pclnState) genInlTreeSym(fi loader.FuncInfo, arch *sys.Arch) loader var pclntabNfunc int32 var pclntabFiletabOffset int32 var pclntabPclntabOffset int32 -var pclntabFirstFunc *sym.Symbol -var pclntabLastFunc *sym.Symbol -var pclntabFirstFunc2 loader.Sym -var pclntabLastFunc2 loader.Sym +var pclntabFirstFunc loader.Sym +var pclntabLastFunc loader.Sym // pclntab generates the pcln table for the link output. Return value // is a bitmap indexed by global symbol that marks 'container' text @@ -276,8 +274,8 @@ func (ctxt *Link) pclntab() loader.Bitmap { continue } nfunc++ - if pclntabFirstFunc2 == 0 { - pclntabFirstFunc2 = s + if pclntabFirstFunc == 0 { + pclntabFirstFunc = s } ss := ldr.SymSect(s) if ss != prevSect { @@ -527,7 +525,7 @@ func (ctxt *Link) pclntab() loader.Bitmap { } last := ctxt.Textp2[len(ctxt.Textp2)-1] - pclntabLastFunc2 = last + pclntabLastFunc = last // Final entry of table is just end pc. setAddr(ftab, ctxt.Arch, 8+int64(ctxt.Arch.PtrSize)+int64(nfunc)*2*int64(ctxt.Arch.PtrSize), last, ldr.SymSize(last)) diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index cd1fa8e6f15..9aca0ded3bb 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -33,6 +33,7 @@ package ld import ( "cmd/internal/objabi" "cmd/internal/sys" + "cmd/link/internal/loader" "cmd/link/internal/sym" "fmt" "path/filepath" @@ -271,12 +272,12 @@ func (libs byPkg) Swap(a, b int) { } // Create a table with information on the text sections. - -func textsectionmap(ctxt *Link) uint32 { - - t := ctxt.Syms.Lookup("runtime.textsectionmap", 0) - t.Type = sym.SRODATA - t.Attr |= sym.AttrReachable +// Return the symbol of the table, and number of sections. +func textsectionmap(ctxt *Link) (loader.Sym, uint32) { + ldr := ctxt.loader + t := ldr.CreateSymForUpdate("runtime.textsectionmap", 0) + t.SetType(sym.SRODATA) + t.SetReachable(true) nsections := int64(0) for _, sect := range Segtext.Sections { @@ -308,107 +309,106 @@ func textsectionmap(ctxt *Link) uint32 { off = t.SetUint(ctxt.Arch, off, sect.Vaddr-textbase) off = t.SetUint(ctxt.Arch, off, sect.Length) if n == 0 { - s := ctxt.Syms.ROLookup("runtime.text", 0) - if s == nil { - Errorf(nil, "Unable to find symbol runtime.text\n") + s := ldr.Lookup("runtime.text", 0) + if s == 0 { + ctxt.Errorf(s, "Unable to find symbol runtime.text\n") } off = t.SetAddr(ctxt.Arch, off, s) } else { - s := ctxt.Syms.Lookup(fmt.Sprintf("runtime.text.%d", n), 0) - if s == nil { - Errorf(nil, "Unable to find symbol runtime.text.%d\n", n) + s := ldr.Lookup(fmt.Sprintf("runtime.text.%d", n), 0) + if s == 0 { + ctxt.Errorf(s, "Unable to find symbol runtime.text.%d\n", n) } off = t.SetAddr(ctxt.Arch, off, s) } n++ } - return uint32(n) + return t.Sym(), uint32(n) } +var symGroupType []sym.SymKind // temporarily assign a symbol's "group" type + func (ctxt *Link) symtab() { - if ctxt.HeadType != objabi.Haix { + ldr := ctxt.loader + + if !ctxt.IsAIX() { switch ctxt.BuildMode { case BuildModeCArchive, BuildModeCShared: - s := ctxt.Syms.ROLookup(*flagEntrySymbol, sym.SymVerABI0) - if s != nil { - addinitarrdata(ctxt, s) + s := ldr.Lookup(*flagEntrySymbol, sym.SymVerABI0) + if s != 0 { + addinitarrdata(ctxt, ldr, s) } } } // Define these so that they'll get put into the symbol table. // data.c:/^address will provide the actual values. - ctxt.xdefine("runtime.text", sym.STEXT, 0) - - ctxt.xdefine("runtime.etext", sym.STEXT, 0) - ctxt.xdefine("runtime.itablink", sym.SRODATA, 0) - ctxt.xdefine("runtime.eitablink", sym.SRODATA, 0) - ctxt.xdefine("runtime.rodata", sym.SRODATA, 0) - ctxt.xdefine("runtime.erodata", sym.SRODATA, 0) - ctxt.xdefine("runtime.types", sym.SRODATA, 0) - ctxt.xdefine("runtime.etypes", sym.SRODATA, 0) - ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, 0) - ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATA, 0) - ctxt.xdefine("runtime.data", sym.SDATA, 0) - ctxt.xdefine("runtime.edata", sym.SDATA, 0) - ctxt.xdefine("runtime.bss", sym.SBSS, 0) - ctxt.xdefine("runtime.ebss", sym.SBSS, 0) - ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, 0) - ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, 0) - ctxt.xdefine("runtime.end", sym.SBSS, 0) - ctxt.xdefine("runtime.epclntab", sym.SRODATA, 0) - ctxt.xdefine("runtime.esymtab", sym.SRODATA, 0) + ctxt.xdefine2("runtime.text", sym.STEXT, 0) + ctxt.xdefine2("runtime.etext", sym.STEXT, 0) + ctxt.xdefine2("runtime.itablink", sym.SRODATA, 0) + ctxt.xdefine2("runtime.eitablink", sym.SRODATA, 0) + ctxt.xdefine2("runtime.rodata", sym.SRODATA, 0) + ctxt.xdefine2("runtime.erodata", sym.SRODATA, 0) + ctxt.xdefine2("runtime.types", sym.SRODATA, 0) + ctxt.xdefine2("runtime.etypes", sym.SRODATA, 0) + ctxt.xdefine2("runtime.noptrdata", sym.SNOPTRDATA, 0) + ctxt.xdefine2("runtime.enoptrdata", sym.SNOPTRDATA, 0) + ctxt.xdefine2("runtime.data", sym.SDATA, 0) + ctxt.xdefine2("runtime.edata", sym.SDATA, 0) + ctxt.xdefine2("runtime.bss", sym.SBSS, 0) + ctxt.xdefine2("runtime.ebss", sym.SBSS, 0) + ctxt.xdefine2("runtime.noptrbss", sym.SNOPTRBSS, 0) + ctxt.xdefine2("runtime.enoptrbss", sym.SNOPTRBSS, 0) + ctxt.xdefine2("runtime.end", sym.SBSS, 0) + ctxt.xdefine2("runtime.epclntab", sym.SRODATA, 0) + ctxt.xdefine2("runtime.esymtab", sym.SRODATA, 0) // garbage collection symbols - s := ctxt.Syms.Lookup("runtime.gcdata", 0) + s := ldr.CreateSymForUpdate("runtime.gcdata", 0) + s.SetType(sym.SRODATA) + s.SetSize(0) + s.SetReachable(true) + ctxt.xdefine2("runtime.egcdata", sym.SRODATA, 0) - s.Type = sym.SRODATA - s.Size = 0 - s.Attr |= sym.AttrReachable - ctxt.xdefine("runtime.egcdata", sym.SRODATA, 0) - - s = ctxt.Syms.Lookup("runtime.gcbss", 0) - s.Type = sym.SRODATA - s.Size = 0 - s.Attr |= sym.AttrReachable - ctxt.xdefine("runtime.egcbss", sym.SRODATA, 0) + s = ldr.CreateSymForUpdate("runtime.gcbss", 0) + s.SetType(sym.SRODATA) + s.SetSize(0) + s.SetReachable(true) + ctxt.xdefine2("runtime.egcbss", sym.SRODATA, 0) // pseudo-symbols to mark locations of type, string, and go string data. - var symtype *sym.Symbol - var symtyperel *sym.Symbol + var symtype, symtyperel loader.Sym if !ctxt.DynlinkingGo() { if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) { - s = ctxt.Syms.Lookup("type.*", 0) + s = ldr.CreateSymForUpdate("type.*", 0) + s.SetType(sym.STYPE) + s.SetSize(0) + s.SetReachable(true) + symtype = s.Sym() - s.Type = sym.STYPE - s.Size = 0 - s.Attr |= sym.AttrReachable - symtype = s - - s = ctxt.Syms.Lookup("typerel.*", 0) - - s.Type = sym.STYPERELRO - s.Size = 0 - s.Attr |= sym.AttrReachable - symtyperel = s + s = ldr.CreateSymForUpdate("typerel.*", 0) + s.SetType(sym.STYPERELRO) + s.SetSize(0) + s.SetReachable(true) + symtyperel = s.Sym() } else { - s = ctxt.Syms.Lookup("type.*", 0) - - s.Type = sym.STYPE - s.Size = 0 - s.Attr |= sym.AttrReachable - symtype = s - symtyperel = s + s = ldr.CreateSymForUpdate("type.*", 0) + s.SetType(sym.STYPE) + s.SetSize(0) + s.SetReachable(true) + symtype = s.Sym() + symtyperel = s.Sym() } } - groupSym := func(name string, t sym.SymKind) *sym.Symbol { - s := ctxt.Syms.Lookup(name, 0) - s.Type = t - s.Size = 0 - s.Attr |= sym.AttrLocal | sym.AttrReachable - return s + groupSym := func(name string, t sym.SymKind) loader.Sym { + s := ldr.CreateSymForUpdate(name, 0) + s.SetType(t) + s.SetSize(0) + s.SetLocal(true) + s.SetReachable(true) + return s.Sym() } var ( symgostring = groupSym("go.string.*", sym.SGOSTRING) @@ -416,7 +416,7 @@ func (ctxt *Link) symtab() { symgcbits = groupSym("runtime.gcbits.*", sym.SGCBITS) ) - var symgofuncrel *sym.Symbol + var symgofuncrel loader.Sym if !ctxt.DynlinkingGo() { if ctxt.UseRelro() { symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO) @@ -425,14 +425,14 @@ func (ctxt *Link) symtab() { } } - symitablink := ctxt.Syms.Lookup("runtime.itablink", 0) - symitablink.Type = sym.SITABLINK + symitablink := ldr.CreateSymForUpdate("runtime.itablink", 0) + symitablink.SetType(sym.SITABLINK) - symt := ctxt.Syms.Lookup("runtime.symtab", 0) - symt.Attr |= sym.AttrLocal - symt.Type = sym.SSYMTAB - symt.Size = 0 - symt.Attr |= sym.AttrReachable + symt := ldr.CreateSymForUpdate("runtime.symtab", 0) + symt.SetType(sym.SSYMTAB) + symt.SetSize(0) + symt.SetReachable(true) + symt.SetLocal(true) nitablinks := 0 @@ -440,147 +440,150 @@ func (ctxt *Link) symtab() { // within a type they sort by size, so the .* symbols // just defined above will be first. // hide the specific symbols. - for _, s := range ctxt.Syms.Allsym { - if ctxt.LinkMode != LinkExternal && isStaticTemp(s.Name) { - s.Attr |= sym.AttrNotInSymbolTable + nsym := loader.Sym(ldr.NSym()) + symGroupType = make([]sym.SymKind, nsym) + for s := loader.Sym(1); s < nsym; s++ { + name := ldr.SymName(s) + if !ctxt.IsExternal() && isStaticTemp(name) { + ldr.SetAttrNotInSymbolTable(s, true) } - if !s.Attr.Reachable() || s.Attr.Special() || - (s.Type != sym.SRODATA && s.Type != sym.SGOFUNC) { + if !ldr.AttrReachable(s) || ldr.AttrSpecial(s) || (ldr.SymType(s) != sym.SRODATA && ldr.SymType(s) != sym.SGOFUNC) { continue } switch { - case strings.HasPrefix(s.Name, "type."): + case strings.HasPrefix(name, "type."): if !ctxt.DynlinkingGo() { - s.Attr |= sym.AttrNotInSymbolTable + ldr.SetAttrNotInSymbolTable(s, true) } if ctxt.UseRelro() { - s.Type = sym.STYPERELRO - s.Outer = symtyperel + symGroupType[s] = sym.STYPERELRO + ldr.SetOuterSym(s, symtyperel) } else { - s.Type = sym.STYPE - s.Outer = symtype + symGroupType[s] = sym.STYPE + ldr.SetOuterSym(s, symtype) } - case strings.HasPrefix(s.Name, "go.importpath.") && ctxt.UseRelro(): + case strings.HasPrefix(name, "go.importpath.") && ctxt.UseRelro(): // Keep go.importpath symbols in the same section as types and // names, as they can be referred to by a section offset. - s.Type = sym.STYPERELRO + symGroupType[s] = sym.STYPERELRO - case strings.HasPrefix(s.Name, "go.itablink."): + case strings.HasPrefix(name, "go.itablink."): nitablinks++ - s.Type = sym.SITABLINK - s.Attr |= sym.AttrNotInSymbolTable - s.Outer = symitablink + symGroupType[s] = sym.SITABLINK + ldr.SetAttrNotInSymbolTable(s, true) + ldr.SetOuterSym(s, symitablink.Sym()) - case strings.HasPrefix(s.Name, "go.string."): - s.Type = sym.SGOSTRING - s.Attr |= sym.AttrNotInSymbolTable - s.Outer = symgostring + case strings.HasPrefix(name, "go.string."): + symGroupType[s] = sym.SGOSTRING + ldr.SetAttrNotInSymbolTable(s, true) + ldr.SetOuterSym(s, symgostring) - case strings.HasPrefix(s.Name, "runtime.gcbits."): - s.Type = sym.SGCBITS - s.Attr |= sym.AttrNotInSymbolTable - s.Outer = symgcbits + case strings.HasPrefix(name, "runtime.gcbits."): + symGroupType[s] = sym.SGCBITS + ldr.SetAttrNotInSymbolTable(s, true) + ldr.SetOuterSym(s, symgcbits) - case strings.HasSuffix(s.Name, "·f"): + case strings.HasSuffix(name, "·f"): if !ctxt.DynlinkingGo() { - s.Attr |= sym.AttrNotInSymbolTable + ldr.SetAttrNotInSymbolTable(s, true) } if ctxt.UseRelro() { - s.Type = sym.SGOFUNCRELRO - s.Outer = symgofuncrel + symGroupType[s] = sym.SGOFUNCRELRO + ldr.SetOuterSym(s, symgofuncrel) } else { - s.Type = sym.SGOFUNC - s.Outer = symgofunc + symGroupType[s] = sym.SGOFUNC + ldr.SetOuterSym(s, symgofunc) } - case strings.HasPrefix(s.Name, "gcargs."), - strings.HasPrefix(s.Name, "gclocals."), - strings.HasPrefix(s.Name, "gclocals·"), - s.Type == sym.SGOFUNC && s != symgofunc, - strings.HasSuffix(s.Name, ".opendefer"): - s.Type = sym.SGOFUNC - s.Attr |= sym.AttrNotInSymbolTable - s.Outer = symgofunc - s.Align = 4 - liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1) + case strings.HasPrefix(name, "gcargs."), + strings.HasPrefix(name, "gclocals."), + strings.HasPrefix(name, "gclocals·"), + ldr.SymType(s) == sym.SGOFUNC && s != symgofunc, + strings.HasSuffix(name, ".opendefer"): + symGroupType[s] = sym.SGOFUNC + ldr.SetAttrNotInSymbolTable(s, true) + ldr.SetOuterSym(s, symgofunc) + const align = 4 + ldr.SetSymAlign(s, align) + liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1) } } if ctxt.BuildMode == BuildModeShared { - abihashgostr := ctxt.Syms.Lookup("go.link.abihash."+filepath.Base(*flagOutfile), 0) - abihashgostr.Attr |= sym.AttrReachable - abihashgostr.Type = sym.SRODATA - hashsym := ctxt.Syms.Lookup("go.link.abihashbytes", 0) + abihashgostr := ldr.CreateSymForUpdate("go.link.abihash."+filepath.Base(*flagOutfile), 0) + abihashgostr.SetReachable(true) + abihashgostr.SetType(sym.SRODATA) + hashsym := ldr.LookupOrCreateSym("go.link.abihashbytes", 0) abihashgostr.AddAddr(ctxt.Arch, hashsym) - abihashgostr.AddUint(ctxt.Arch, uint64(hashsym.Size)) + abihashgostr.AddUint(ctxt.Arch, uint64(ldr.SymSize(hashsym))) } if ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() { for _, l := range ctxt.Library { - s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0) - s.Attr |= sym.AttrReachable - s.Type = sym.SRODATA - s.Size = int64(len(l.Hash)) - s.P = []byte(l.Hash) - str := ctxt.Syms.Lookup("go.link.pkghash."+l.Pkg, 0) - str.Attr |= sym.AttrReachable - str.Type = sym.SRODATA - str.AddAddr(ctxt.Arch, s) + s := ldr.CreateSymForUpdate("go.link.pkghashbytes."+l.Pkg, 0) + s.SetReachable(true) + s.SetType(sym.SRODATA) + s.SetSize(int64(len(l.Hash))) + s.SetData([]byte(l.Hash)) + str := ldr.CreateSymForUpdate("go.link.pkghash."+l.Pkg, 0) + str.SetReachable(true) + str.SetType(sym.SRODATA) + str.AddAddr(ctxt.Arch, s.Sym()) str.AddUint(ctxt.Arch, uint64(len(l.Hash))) } } - nsections := textsectionmap(ctxt) + textsectionmapSym, nsections := textsectionmap(ctxt) // Information about the layout of the executable image for the // runtime to use. Any changes here must be matched by changes to // the definition of moduledata in runtime/symtab.go. // This code uses several global variables that are set by pcln.go:pclntab. - moduledata := ctxt.Moduledata + moduledata := ldr.MakeSymbolUpdater(ctxt.Moduledata2) + pclntab := ldr.Lookup("runtime.pclntab", 0) // The pclntab slice - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0)) - moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size)) - moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size)) + moduledata.AddAddr(ctxt.Arch, pclntab) + moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pclntab))) + moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pclntab))) // The ftab slice - moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabPclntabOffset)) + moduledata.AddAddrPlus(ctxt.Arch, pclntab, int64(pclntabPclntabOffset)) moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1)) moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1)) // The filetab slice - moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabFiletabOffset)) + moduledata.AddAddrPlus(ctxt.Arch, pclntab, int64(pclntabFiletabOffset)) moduledata.AddUint(ctxt.Arch, uint64(ctxt.NumFilesyms)+1) moduledata.AddUint(ctxt.Arch, uint64(ctxt.NumFilesyms)+1) // findfunctab - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.findfunctab", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.findfunctab", 0)) // minpc, maxpc moduledata.AddAddr(ctxt.Arch, pclntabFirstFunc) - moduledata.AddAddrPlus(ctxt.Arch, pclntabLastFunc, pclntabLastFunc.Size) + moduledata.AddAddrPlus(ctxt.Arch, pclntabLastFunc, ldr.SymSize(pclntabLastFunc)) // pointers to specific parts of the module - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.text", 0)) - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etext", 0)) - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrdata", 0)) - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrdata", 0)) - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.data", 0)) - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.edata", 0)) - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.bss", 0)) - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.ebss", 0)) - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrbss", 0)) - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrbss", 0)) - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.end", 0)) - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcdata", 0)) - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcbss", 0)) - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.types", 0)) - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etypes", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.text", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etext", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.noptrdata", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.enoptrdata", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.data", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.edata", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.bss", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.ebss", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.noptrbss", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.enoptrbss", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.end", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcdata", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcbss", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.types", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etypes", 0)) - if ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal { - // Add R_REF relocation to prevent ld's garbage collection of + if ctxt.IsAIX() && ctxt.IsExternal() { + // Add R_XCOFFREF relocation to prevent ld's garbage collection of // runtime.rodata, runtime.erodata and runtime.epclntab. addRef := func(name string) { - r := moduledata.AddRel() - r.Sym = ctxt.Syms.Lookup(name, 0) - r.Type = objabi.R_XCOFFREF - r.Siz = uint8(ctxt.Arch.PtrSize) + r, _ := moduledata.AddRel(objabi.R_XCOFFREF) + r.SetSym(ldr.Lookup(name, 0)) + r.SetSiz(uint8(ctxt.Arch.PtrSize)) } addRef("runtime.rodata") addRef("runtime.erodata") @@ -588,26 +591,27 @@ func (ctxt *Link) symtab() { } // text section information - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.textsectionmap", 0)) + moduledata.AddAddr(ctxt.Arch, textsectionmapSym) moduledata.AddUint(ctxt.Arch, uint64(nsections)) moduledata.AddUint(ctxt.Arch, uint64(nsections)) // The typelinks slice - typelinkSym := ctxt.Syms.Lookup("runtime.typelink", 0) - ntypelinks := uint64(typelinkSym.Size) / 4 + typelinkSym := ldr.Lookup("runtime.typelink", 0) + ntypelinks := uint64(ldr.SymSize(typelinkSym)) / 4 moduledata.AddAddr(ctxt.Arch, typelinkSym) moduledata.AddUint(ctxt.Arch, ntypelinks) moduledata.AddUint(ctxt.Arch, ntypelinks) // The itablinks slice - moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.itablink", 0)) + moduledata.AddAddr(ctxt.Arch, symitablink.Sym()) moduledata.AddUint(ctxt.Arch, uint64(nitablinks)) moduledata.AddUint(ctxt.Arch, uint64(nitablinks)) // The ptab slice - if ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0); ptab != nil && ptab.Attr.Reachable() { - ptab.Attr |= sym.AttrLocal - ptab.Type = sym.SRODATA - - nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff) + if ptab := ldr.Lookup("go.plugin.tabs", 0); ptab != 0 && ldr.AttrReachable(ptab) { + ldr.SetAttrLocal(ptab, true) + if ldr.SymType(ptab) != sym.SRODATA { + panic(fmt.Sprintf("go.plugin.tabs is %v, not SRODATA", ldr.SymType(ptab))) + } + nentries := uint64(len(ldr.Data(ptab)) / 8) // sizeof(nameOff) + sizeof(typeOff) moduledata.AddAddr(ctxt.Arch, ptab) moduledata.AddUint(ctxt.Arch, nentries) moduledata.AddUint(ctxt.Arch, nentries) @@ -617,23 +621,23 @@ func (ctxt *Link) symtab() { moduledata.AddUint(ctxt.Arch, 0) } if ctxt.BuildMode == BuildModePlugin { - addgostring(ctxt, moduledata, "go.link.thispluginpath", objabi.PathToPrefix(*flagPluginPath)) + addgostring(ctxt, ldr, moduledata, "go.link.thispluginpath", objabi.PathToPrefix(*flagPluginPath)) - pkghashes := ctxt.Syms.Lookup("go.link.pkghashes", 0) - pkghashes.Attr |= sym.AttrReachable - pkghashes.Attr |= sym.AttrLocal - pkghashes.Type = sym.SRODATA + pkghashes := ldr.CreateSymForUpdate("go.link.pkghashes", 0) + pkghashes.SetReachable(true) + pkghashes.SetLocal(true) + pkghashes.SetType(sym.SRODATA) for i, l := range ctxt.Library { // pkghashes[i].name - addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg) + addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg) // pkghashes[i].linktimehash - addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), l.Hash) + addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), l.Hash) // pkghashes[i].runtimehash - hash := ctxt.Syms.ROLookup("go.link.pkghash."+l.Pkg, 0) + hash := ldr.Lookup("go.link.pkghash."+l.Pkg, 0) pkghashes.AddAddr(ctxt.Arch, hash) } - moduledata.AddAddr(ctxt.Arch, pkghashes) + moduledata.AddAddr(ctxt.Arch, pkghashes.Sym()) moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library))) moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library))) } else { @@ -651,28 +655,28 @@ func (ctxt *Link) symtab() { // it something slightly more comprehensible. thismodulename = "the executable" } - addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename) + addgostring(ctxt, ldr, moduledata, "go.link.thismodulename", thismodulename) - modulehashes := ctxt.Syms.Lookup("go.link.abihashes", 0) - modulehashes.Attr |= sym.AttrReachable - modulehashes.Attr |= sym.AttrLocal - modulehashes.Type = sym.SRODATA + modulehashes := ldr.CreateSymForUpdate("go.link.abihashes", 0) + modulehashes.SetReachable(true) + modulehashes.SetLocal(true) + modulehashes.SetType(sym.SRODATA) for i, shlib := range ctxt.Shlibs { // modulehashes[i].modulename modulename := filepath.Base(shlib.Path) - addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename) + addgostring(ctxt, ldr, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename) // modulehashes[i].linktimehash - addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash)) + addgostring(ctxt, ldr, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash)) // modulehashes[i].runtimehash - abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0) - abihash.Attr |= sym.AttrReachable + abihash := ldr.LookupOrCreateSym("go.link.abihash."+modulename, 0) + ldr.SetAttrReachable(abihash, true) modulehashes.AddAddr(ctxt.Arch, abihash) } - moduledata.AddAddr(ctxt.Arch, modulehashes) + moduledata.AddAddr(ctxt.Arch, modulehashes.Sym()) moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs))) moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs))) } else { @@ -694,15 +698,16 @@ func (ctxt *Link) symtab() { // When linking an object that does not contain the runtime we are // creating the moduledata from scratch and it does not have a // compiler-provided size, so read it from the type data. - moduledatatype := ctxt.Syms.ROLookup("type.runtime.moduledata", 0) - moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype.P) - moduledata.Grow(moduledata.Size) + moduledatatype := ldr.Lookup("type.runtime.moduledata", 0) + moduledata.SetSize(decodetypeSize(ctxt.Arch, ldr.Data(moduledatatype))) + moduledata.Grow(moduledata.Size()) - lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0) - if lastmoduledatap.Type != sym.SDYNIMPORT { - lastmoduledatap.Type = sym.SNOPTRDATA - lastmoduledatap.Size = 0 // overwrite existing value - lastmoduledatap.AddAddr(ctxt.Arch, moduledata) + lastmoduledatap := ldr.CreateSymForUpdate("runtime.lastmoduledatap", 0) + if lastmoduledatap.Type() != sym.SDYNIMPORT { + lastmoduledatap.SetType(sym.SNOPTRDATA) + lastmoduledatap.SetSize(0) // overwrite existing value + lastmoduledatap.SetData(nil) + lastmoduledatap.AddAddr(ctxt.Arch, moduledata.Sym()) } } diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index b09832b5c3d..75477fd819a 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -1398,6 +1398,16 @@ func (l *Loader) SubSym(i Sym) Sym { return l.sub[i] } +// SetOuterSym sets the outer symbol of i to o (without setting +// sub symbols). +func (l *Loader) SetOuterSym(i Sym, o Sym) { + if o != 0 { + l.outer[i] = o + } else { + delete(l.outer, i) + } +} + // Initialize Reachable bitmap and its siblings for running deadcode pass. func (l *Loader) InitReachable() { l.growAttrBitmaps(l.NSym() + 1) @@ -2225,8 +2235,7 @@ func loadObjSyms(l *Loader, syms *sym.Symbols, r *oReader) int { continue } - s := l.addNewSym(gi, name, ver, r.unit, t) - l.migrateAttributes(gi, s) + l.addNewSym(gi, name, ver, r.unit, t) nr += r.NReloc(i) } return nr @@ -2378,10 +2387,19 @@ func (l *Loader) migrateAttributes(src Sym, dst *sym.Symbol) { dst.Sub = l.Syms[sub] } - // Set sub-symbol attribute. FIXME: would be better to do away - // with this and just use l.OuterSymbol() != 0 elsewhere within - // the linker. - dst.Attr.Set(sym.AttrSubSymbol, dst.Outer != nil) + // Set sub-symbol attribute. + // + // In sym.Symbols world, it uses Outer to record container symbols. + // Currently there are two kinds + // - Outer symbol covers the address ranges of its sub-symbols. + // Outer.Sub is set in this case. + // - Outer symbol doesn't conver the address ranges. It is zero-sized + // and doesn't have sub-symbols. In the case, the inner symbol is + // not actually a "SubSymbol". (Tricky!) + // + // FIXME: would be better to do away with this and have a better way + // to represent container symbols. + dst.Attr.Set(sym.AttrSubSymbol, l.outer[src] != 0 && l.sub[l.outer[src]] != 0) // Copy over dynimplib, dynimpvers, extname. if name, ok := l.extname[src]; ok { @@ -2448,10 +2466,11 @@ func loadObjFull(l *Loader, r *oReader) { continue } + l.migrateAttributes(gi, s) + // Be careful not to overwrite attributes set by the linker. + // Don't use the attributes from the object file. + osym := r.Sym(i) - dupok := osym.Dupok() - local := osym.Local() - makeTypelink := osym.Typelink() size := osym.Siz() // Symbol data @@ -2485,14 +2504,9 @@ func loadObjFull(l *Loader, r *oReader) { } s.File = r.pkgprefix[:len(r.pkgprefix)-1] - if dupok { - s.Attr |= sym.AttrDuplicateOK - } if s.Size < int64(size) { s.Size = int64(size) } - s.Attr.Set(sym.AttrLocal, local) - s.Attr.Set(sym.AttrMakeTypelink, makeTypelink) } } diff --git a/src/cmd/link/internal/loader/symbolbuilder.go b/src/cmd/link/internal/loader/symbolbuilder.go index dfbf6b8cc18..f5db69856be 100644 --- a/src/cmd/link/internal/loader/symbolbuilder.go +++ b/src/cmd/link/internal/loader/symbolbuilder.go @@ -107,6 +107,7 @@ func (sb *SymbolBuilder) SetDynimpvers(value string) { sb.l.SetSymDynimpvers(sb. func (sb *SymbolBuilder) SetPlt(value int32) { sb.l.SetPlt(sb.symIdx, value) } func (sb *SymbolBuilder) SetGot(value int32) { sb.l.SetGot(sb.symIdx, value) } func (sb *SymbolBuilder) SetSpecial(value bool) { sb.l.SetAttrSpecial(sb.symIdx, value) } +func (sb *SymbolBuilder) SetLocal(value bool) { sb.l.SetAttrLocal(sb.symIdx, value) } func (sb *SymbolBuilder) SetVisibilityHidden(value bool) { sb.l.SetAttrVisibilityHidden(sb.symIdx, value) } @@ -334,6 +335,10 @@ func (sb *SymbolBuilder) SetAddrPlus(arch *sys.Arch, off int64, tgt Sym, add int return off + int64(r.Size) } +func (sb *SymbolBuilder) SetAddr(arch *sys.Arch, off int64, tgt Sym) int64 { + return sb.SetAddrPlus(arch, off, tgt, 0) +} + func (sb *SymbolBuilder) Addstring(str string) int64 { sb.setReachable() if sb.kind == 0 {