]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.link] cmd/link: convert symtab pass to new style
authorCherry Zhang <cherryyz@google.com>
Mon, 20 Apr 2020 22:42:35 +0000 (18:42 -0400)
committerCherry Zhang <cherryyz@google.com>
Tue, 21 Apr 2020 14:29:02 +0000 (14:29 +0000)
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 <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/lib.go
src/cmd/link/internal/ld/main.go
src/cmd/link/internal/ld/pcln.go
src/cmd/link/internal/ld/symtab.go
src/cmd/link/internal/loader/loader.go
src/cmd/link/internal/loader/symbolbuilder.go

index dd49526ddd5c167cc6c58c9860ce4c63f051ea1c..204c237794300e5083249b89002f6097ca1bd2e9 100644 (file)
@@ -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)
-       }
-       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)
+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.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)
 }
 
index b71bef22f481e7961aaf89f013666351a4f5bd3d..9c87ab15a1cf1c4fdfe0eef483544265fb582a3b 100644 (file)
@@ -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)
                }
index 4735b91b352cb4b3c858b384e3b2eee623c7e8a4..32a2eff2b5fa6c5860663f7a7293d35e3effb3a5 100644 (file)
@@ -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")
index 75fb828bef565451235c37b615b229cb94d8055c..00c29c63e071bd125b722959ab5c9850fe7f6df8 100644 (file)
@@ -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))
 
index cd1fa8e6f15f1cc45ea0dbd6cac121f301f9e8bc..9aca0ded3bb0cacc4a8cd0fbba49ff96a660ef29 100644 (file)
@@ -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.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.gcdata", 0)
+       s.SetType(sym.SRODATA)
+       s.SetSize(0)
+       s.SetReachable(true)
+       ctxt.xdefine2("runtime.egcdata", 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.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("type.*", 0)
+                       s.SetType(sym.STYPE)
+                       s.SetSize(0)
+                       s.SetReachable(true)
+                       symtype = s.Sym()
+
+                       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))
-
-       if ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal {
-               // Add R_REF relocation to prevent ld's garbage collection of
+       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.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)
-
-       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)
+       moduledatatype := ldr.Lookup("type.runtime.moduledata", 0)
+       moduledata.SetSize(decodetypeSize(ctxt.Arch, ldr.Data(moduledatatype)))
+       moduledata.Grow(moduledata.Size())
+
+       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())
        }
 }
 
index b09832b5c3d34d63cb662e540d471b82e1400f4e..75477fd819a0ab33b3e74ba79db462f4c1110baa 100644 (file)
@@ -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)
        }
 }
 
index dfbf6b8cc18f837aa15bb9e3a86d12ead75feb98..f5db69856be58ef05eaf0cf379d1a11bfbc9be4f 100644 (file)
@@ -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 {