]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.link] cmd/link: move xcoff to loader represenatation
authorJeremy Faller <jeremy@golang.org>
Mon, 11 May 2020 18:35:54 +0000 (14:35 -0400)
committerJeremy Faller <jeremy@golang.org>
Thu, 14 May 2020 19:18:37 +0000 (19:18 +0000)
Change-Id: I5b260493ffd7945f665c466e892be18d81e7940a
Reviewed-on: https://go-review.googlesource.com/c/go/+/233340
Run-TryBot: Jeremy Faller <jeremy@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/link/internal/ld/data2.go [deleted file]
src/cmd/link/internal/ld/lib.go
src/cmd/link/internal/ld/main.go
src/cmd/link/internal/ld/xcoff.go
src/cmd/link/internal/ppc64/asm.go

diff --git a/src/cmd/link/internal/ld/data2.go b/src/cmd/link/internal/ld/data2.go
deleted file mode 100644 (file)
index 0b3c6f0..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2020 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ld
-
-import (
-       "cmd/link/internal/sym"
-       "strings"
-)
-
-// Temporary dumping around for sym.Symbol version of helper
-// functions in dodata(), still being used for some archs/oses.
-// FIXME: get rid of this file when dodata() is completely
-// converted.
-
-// symalign returns the required alignment for the given symbol s.
-func symalign(s *sym.Symbol) int32 {
-       min := int32(thearch.Minalign)
-       if s.Align >= min {
-               return s.Align
-       } else if s.Align != 0 {
-               return min
-       }
-       if strings.HasPrefix(s.Name, "go.string.") || strings.HasPrefix(s.Name, "type..namedata.") {
-               // String data is just bytes.
-               // If we align it, we waste a lot of space to padding.
-               return min
-       }
-       align := int32(thearch.Maxalign)
-       for int64(align) > s.Size && align > min {
-               align >>= 1
-       }
-       s.Align = align
-       return align
-}
index e5378225dc5a68b46f1866248c83f5da8f7dadb4..d3382b525244d125a2aa35c70d31f7b1beee3cfb 100644 (file)
@@ -273,7 +273,7 @@ type Arch struct {
        Gentext2    func(*Link, *loader.Loader)
        Machoreloc1 func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtRelocView, int64) bool
        PEreloc1    func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtRelocView, int64) bool
-       Xcoffreloc1 func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, int64) bool
+       Xcoffreloc1 func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtRelocView, int64) bool
 
        // TLSIEtoLE converts a TLS Initial Executable relocation to
        // a TLS Local Executable relocation.
@@ -2870,13 +2870,6 @@ func (ctxt *Link) loadlibfull(symGroupType []sym.SymKind, needReloc, needExtRelo
        }
 }
 
-func symPkg(ctxt *Link, s *sym.Symbol) string {
-       if s == nil {
-               return ""
-       }
-       return ctxt.loader.SymPkg(loader.Sym(s.SymIdx))
-}
-
 func ElfSymForReloc2(ctxt *Link, s loader.Sym) int32 {
        // If putelfsym created a local version of this symbol, use that in all
        // relocations.
index 465a765db83be7c94eed87d938254d90df9ae3a3..bc170f9eb8ea01b3a603e571639116c1ce3eb7d5 100644 (file)
@@ -320,16 +320,6 @@ func Main(arch *sys.Arch, theArch Arch) {
        thearch.Asmb(ctxt, ctxt.loader)
        bench.Start("reloc")
        ctxt.reloc()
-       newasmb2 := ctxt.IsDarwin() || ctxt.IsWindows() || ctxt.IsWasm() || ctxt.IsPlan9() || ctxt.IsElf()
-       if !newasmb2 {
-               bench.Start("loadlibfull")
-               // We don't need relocations at this point.
-               needReloc := false
-               // On AMD64 ELF, we directly use the loader's ExtRelocs, so we don't
-               // need conversion. Otherwise we do.
-               needExtReloc := ctxt.IsExternal() && !(ctxt.IsAMD64() && ctxt.IsELF)
-               ctxt.loadlibfull(symGroupType, needReloc, needExtReloc) // XXX do it here for now
-       }
        bench.Start("Asmb2")
        thearch.Asmb2(ctxt, ctxt.loader)
 
index 96c5a58af5df25714ff22cf3f87f8065154ff471..506dde232f5d373e1208a5d53f54bede00928b48 100644 (file)
@@ -10,6 +10,7 @@ import (
        "cmd/link/internal/loader"
        "cmd/link/internal/sym"
        "encoding/binary"
+       "fmt"
        "io/ioutil"
        "math/bits"
        "path/filepath"
@@ -359,7 +360,6 @@ type XcoffLdRel64 struct {
 
 // xcoffLoaderReloc holds information about a relocation made by the loader.
 type xcoffLoaderReloc struct {
-       sym    *sym.Symbol
        sym2   loader.Sym
        roff   int32
        rtype  uint16
@@ -616,13 +616,13 @@ func (f *xcoffFile) addSymbol(sym xcoffSym) {
 }
 
 // xcoffAlign returns the log base 2 of the symbol's alignment.
-func xcoffAlign(x *sym.Symbol, t SymbolType) uint8 {
-       align := x.Align
+func xcoffAlign(ldr *loader.Loader, x loader.Sym, t SymbolType) uint8 {
+       align := ldr.SymAlign(x)
        if align == 0 {
                if t == TextSym {
                        align = int32(Funcalign)
                } else {
-                       align = symalign(x)
+                       align = symalign2(ldr, x)
                }
        }
        return logBase2(int(align))
@@ -642,6 +642,7 @@ func logBase2(a int) uint8 {
 // Currently, a new file is in fact a new package. It seems to be OK, but it might change
 // in the future.
 func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint64, extnum int16) {
+       ldr := ctxt.loader
        /* C_FILE */
        s := &XcoffSymEnt64{
                Noffset: uint32(f.stringTable.add(".file")),
@@ -670,8 +671,7 @@ func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint6
                        dwsize = getDwsectCUSize(sect.Name, name)
                        // .debug_abbrev is common to all packages and not found with the previous function
                        if sect.Name == ".debug_abbrev" {
-                               s := ctxt.Syms.ROLookup(sect.Name, 0)
-                               dwsize = uint64(s.Size)
+                               dwsize = uint64(ldr.SymSize(loader.Sym(sect.Sym2)))
 
                        }
                } else {
@@ -693,8 +693,7 @@ func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint6
                        // Dwarf relocations need the symbol number of .dw* symbols.
                        // It doesn't need to know it for each package, one is enough.
                        // currSymSrcFile.csectAux == nil means first package.
-                       dws := ctxt.Syms.Lookup(sect.Name, 0)
-                       dws.Dynid = int32(f.symbolCount)
+                       ldr.SetSymDynid(loader.Sym(sect.Sym2), int32(f.symbolCount))
 
                        if sect.Name == ".debug_frame" && ctxt.LinkMode != LinkExternal {
                                // CIE size must be added to the first package.
@@ -774,28 +773,30 @@ func (f *xcoffFile) updatePreviousFile(ctxt *Link, last bool) {
 // Write symbol representing a .text function.
 // The symbol table is split with C_FILE corresponding to each package
 // and not to each source file as it should be.
-func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x *sym.Symbol) []xcoffSym {
+func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x loader.Sym) []xcoffSym {
        // New XCOFF symbols which will be written.
        syms := []xcoffSym{}
 
        // Check if a new file is detected.
-       if strings.Contains(x.Name, "-tramp") || strings.HasPrefix(x.Name, "runtime.text.") {
+       ldr := ctxt.loader
+       name := ldr.SymName(x)
+       if strings.Contains(name, "-tramp") || strings.HasPrefix(name, "runtime.text.") {
                // Trampoline don't have a FILE so there are considered
                // in the current file.
                // Same goes for runtime.text.X symbols.
-       } else if symPkg(ctxt, x) == "" { // Undefined global symbol
+       } else if ldr.SymPkg(x) == "" { // Undefined global symbol
                // If this happens, the algorithm must be redone.
                if currSymSrcFile.name != "" {
                        Exitf("undefined global symbol found inside another file")
                }
        } else {
                // Current file has changed. New C_FILE, C_DWARF, etc must be generated.
-               if currSymSrcFile.name != symPkg(ctxt, x) {
+               if currSymSrcFile.name != ldr.SymPkg(x) {
                        if ctxt.LinkMode == LinkInternal {
                                // update previous file values
                                xfile.updatePreviousFile(ctxt, false)
-                               currSymSrcFile.name = symPkg(ctxt, x)
-                               f.writeSymbolNewFile(ctxt, symPkg(ctxt, x), uint64(x.Value), xfile.getXCOFFscnum(x.Sect))
+                               currSymSrcFile.name = ldr.SymPkg(x)
+                               f.writeSymbolNewFile(ctxt, ldr.SymPkg(x), uint64(ldr.SymValue(x)), xfile.getXCOFFscnum(ldr.SymSect(x)))
                        } else {
                                // With external linking, ld will crash if there is several
                                // .FILE and DWARF debugging enable, somewhere during
@@ -805,8 +806,8 @@ func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x *sym.Symbol) []xcoffSym {
                                // TODO(aix); remove once ld has been fixed or the triggering
                                // relocation has been found and fixed.
                                if currSymSrcFile.name == "" {
-                                       currSymSrcFile.name = symPkg(ctxt, x)
-                                       f.writeSymbolNewFile(ctxt, "go_functions", uint64(x.Value), xfile.getXCOFFscnum(x.Sect))
+                                       currSymSrcFile.name = ldr.SymPkg(x)
+                                       f.writeSymbolNewFile(ctxt, "go_functions", uint64(ldr.SymValue(x)), xfile.getXCOFFscnum(ldr.SymSect(x)))
                                }
                        }
 
@@ -815,26 +816,26 @@ func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x *sym.Symbol) []xcoffSym {
 
        s := &XcoffSymEnt64{
                Nsclass: C_EXT,
-               Noffset: uint32(xfile.stringTable.add(x.Extname())),
-               Nvalue:  uint64(x.Value),
-               Nscnum:  f.getXCOFFscnum(x.Sect),
+               Noffset: uint32(xfile.stringTable.add(ldr.SymExtname(x))),
+               Nvalue:  uint64(ldr.SymValue(x)),
+               Nscnum:  f.getXCOFFscnum(ldr.SymSect(x)),
                Ntype:   SYM_TYPE_FUNC,
                Nnumaux: 2,
        }
 
-       if x.Version != 0 || x.Attr.VisibilityHidden() || x.Attr.Local() {
+       if ldr.SymVersion(x) != 0 || ldr.AttrVisibilityHidden(x) || ldr.AttrLocal(x) {
                s.Nsclass = C_HIDEXT
        }
 
-       x.Dynid = int32(xfile.symbolCount)
+       ldr.SetSymDynid(x, int32(xfile.symbolCount))
        syms = append(syms, s)
 
        // Update current csect size
-       currSymSrcFile.csectSize += x.Size
+       currSymSrcFile.csectSize += ldr.SymSize(x)
 
        // create auxiliary entries
        a2 := &XcoffAuxFcn64{
-               Xfsize:   uint32(x.Size),
+               Xfsize:   uint32(ldr.SymSize(x)),
                Xlnnoptr: 0,                     // TODO
                Xendndx:  xfile.symbolCount + 3, // this symbol + 2 aux entries
                Xauxtype: _AUX_FCN,
@@ -848,44 +849,49 @@ func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x *sym.Symbol) []xcoffSym {
                Xsmtyp:    XTY_LD, // label definition (based on C)
                Xauxtype:  _AUX_CSECT,
        }
-       a4.Xsmtyp |= uint8(xcoffAlign(x, TextSym) << 3)
+       a4.Xsmtyp |= uint8(xcoffAlign(ldr, x, TextSym) << 3)
 
        syms = append(syms, a4)
        return syms
 }
 
 // put function used by genasmsym to write symbol table
-func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64) {
-
+func putaixsym(ctxt *Link, x loader.Sym, t SymbolType) {
        // All XCOFF symbols generated by this GO symbols
        // Can be a symbol entry or a auxiliary entry
        syms := []xcoffSym{}
 
+       ldr := ctxt.loader
+       name := ldr.SymName(x)
+       if t == UndefinedSym {
+               name = ldr.SymExtname(x)
+       }
+
        switch t {
        default:
                return
 
        case TextSym:
-               if symPkg(ctxt, x) != "" || strings.Contains(x.Name, "-tramp") || strings.HasPrefix(x.Name, "runtime.text.") {
+               if ldr.SymPkg(x) != "" || strings.Contains(name, "-tramp") || strings.HasPrefix(name, "runtime.text.") {
                        // Function within a file
                        syms = xfile.writeSymbolFunc(ctxt, x)
                } else {
                        // Only runtime.text and runtime.etext come through this way
-                       if x.Name != "runtime.text" && x.Name != "runtime.etext" && x.Name != "go.buildid" {
-                               Exitf("putaixsym: unknown text symbol %s", x.Name)
+                       if name != "runtime.text" && name != "runtime.etext" && name != "go.buildid" {
+                               Exitf("putaixsym: unknown text symbol %s", name)
                        }
                        s := &XcoffSymEnt64{
                                Nsclass: C_HIDEXT,
-                               Noffset: uint32(xfile.stringTable.add(str)),
-                               Nvalue:  uint64(x.Value),
-                               Nscnum:  xfile.getXCOFFscnum(x.Sect),
+                               Noffset: uint32(xfile.stringTable.add(name)),
+                               Nvalue:  uint64(ldr.SymValue(x)),
+                               Nscnum:  xfile.getXCOFFscnum(ldr.SymSect(x)),
                                Ntype:   SYM_TYPE_FUNC,
                                Nnumaux: 1,
                        }
-                       x.Dynid = int32(xfile.symbolCount)
+                       ldr.SetSymDynid(x, int32(xfile.symbolCount))
                        syms = append(syms, s)
 
-                       size := uint64(x.Size)
+                       size := uint64(ldr.SymSize(x))
                        a4 := &XcoffAuxCSect64{
                                Xauxtype:  _AUX_CSECT,
                                Xscnlenlo: uint32(size & 0xFFFFFFFF),
@@ -893,21 +899,20 @@ func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64)
                                Xsmclas:   XMC_PR,
                                Xsmtyp:    XTY_SD,
                        }
-                       a4.Xsmtyp |= uint8(xcoffAlign(x, TextSym) << 3)
+                       a4.Xsmtyp |= uint8(xcoffAlign(ldr, x, TextSym) << 3)
                        syms = append(syms, a4)
-
                }
 
        case DataSym, BSSSym:
                s := &XcoffSymEnt64{
                        Nsclass: C_EXT,
-                       Noffset: uint32(xfile.stringTable.add(str)),
-                       Nvalue:  uint64(x.Value),
-                       Nscnum:  xfile.getXCOFFscnum(x.Sect),
+                       Noffset: uint32(xfile.stringTable.add(name)),
+                       Nvalue:  uint64(ldr.SymValue(x)),
+                       Nscnum:  xfile.getXCOFFscnum(ldr.SymSect(x)),
                        Nnumaux: 1,
                }
 
-               if x.Version != 0 || x.Attr.VisibilityHidden() || x.Attr.Local() {
+               if ldr.SymVersion(x) != 0 || ldr.AttrVisibilityHidden(x) || ldr.AttrLocal(x) {
                        // There is more symbols in the case of a global data
                        // which are related to the assembly generated
                        // to access such symbols.
@@ -917,7 +922,7 @@ func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64)
                        s.Nsclass = C_HIDEXT
                }
 
-               x.Dynid = int32(xfile.symbolCount)
+               ldr.SetSymDynid(x, int32(xfile.symbolCount))
                syms = append(syms, s)
 
                // Create auxiliary entry
@@ -926,15 +931,15 @@ func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64)
                // the data and bss symbols of one file/package.
                // However, it's easier to just have a csect for each symbol.
                // It might change
-               size := uint64(x.Size)
+               size := uint64(ldr.SymSize(x))
                a4 := &XcoffAuxCSect64{
                        Xauxtype:  _AUX_CSECT,
                        Xscnlenlo: uint32(size & 0xFFFFFFFF),
                        Xscnlenhi: uint32(size >> 32),
                }
 
-               if x.Type >= sym.STYPE && x.Type <= sym.SPCLNTAB {
-                       if ctxt.LinkMode == LinkExternal && strings.HasPrefix(x.Sect.Name, ".data.rel.ro") {
+               if ty := ldr.SymType(x); ty >= sym.STYPE && ty <= sym.SPCLNTAB {
+                       if ctxt.IsExternal() && strings.HasPrefix(ldr.SymSect(x).Name, ".data.rel.ro") {
                                // During external linking, read-only datas with relocation
                                // must be in .data.
                                a4.Xsmclas = XMC_RW
@@ -942,9 +947,9 @@ func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64)
                                // Read only data
                                a4.Xsmclas = XMC_RO
                        }
-               } else if x.Type == sym.SDATA && strings.HasPrefix(x.Name, "TOC.") && ctxt.LinkMode == LinkExternal {
+               } else if /*ty == sym.SDATA &&*/ strings.HasPrefix(ldr.SymName(x), "TOC.") && ctxt.IsExternal() {
                        a4.Xsmclas = XMC_TC
-               } else if x.Name == "TOC" {
+               } else if ldr.SymName(x) == "TOC" {
                        a4.Xsmclas = XMC_TC0
                } else {
                        a4.Xsmclas = XMC_RW
@@ -955,20 +960,20 @@ func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64)
                        a4.Xsmtyp |= XTY_CM
                }
 
-               a4.Xsmtyp |= uint8(xcoffAlign(x, t) << 3)
+               a4.Xsmtyp |= uint8(xcoffAlign(ldr, x, t) << 3)
 
                syms = append(syms, a4)
 
        case UndefinedSym:
-               if x.Type != sym.SDYNIMPORT && x.Type != sym.SHOSTOBJ && x.Type != sym.SUNDEFEXT {
+               if ty := ldr.SymType(x); ty != sym.SDYNIMPORT && ty != sym.SHOSTOBJ && ty != sym.SUNDEFEXT {
                        return
                }
                s := &XcoffSymEnt64{
                        Nsclass: C_EXT,
-                       Noffset: uint32(xfile.stringTable.add(str)),
+                       Noffset: uint32(xfile.stringTable.add(name)),
                        Nnumaux: 1,
                }
-               x.Dynid = int32(xfile.symbolCount)
+               ldr.SetSymDynid(x, int32(xfile.symbolCount))
                syms = append(syms, s)
 
                a4 := &XcoffAuxCSect64{
@@ -977,7 +982,7 @@ func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64)
                        Xsmtyp:   XTY_ER | XTY_IMP,
                }
 
-               if x.Name == "__n_pthreads" {
+               if ldr.SymName(x) == "__n_pthreads" {
                        // Currently, all imported symbols made by cgo_import_dynamic are
                        // syscall functions, except __n_pthreads which is a variable.
                        // TODO(aix): Find a way to detect variables imported by cgo.
@@ -989,16 +994,16 @@ func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64)
        case TLSSym:
                s := &XcoffSymEnt64{
                        Nsclass: C_EXT,
-                       Noffset: uint32(xfile.stringTable.add(str)),
-                       Nscnum:  xfile.getXCOFFscnum(x.Sect),
-                       Nvalue:  uint64(x.Value),
+                       Noffset: uint32(xfile.stringTable.add(name)),
+                       Nscnum:  xfile.getXCOFFscnum(ldr.SymSect(x)),
+                       Nvalue:  uint64(ldr.SymValue(x)),
                        Nnumaux: 1,
                }
 
-               x.Dynid = int32(xfile.symbolCount)
+               ldr.SetSymDynid(x, int32(xfile.symbolCount))
                syms = append(syms, s)
 
-               size := uint64(x.Size)
+               size := uint64(ldr.SymSize(x))
                a4 := &XcoffAuxCSect64{
                        Xauxtype:  _AUX_CSECT,
                        Xsmclas:   XMC_UL,
@@ -1019,18 +1024,114 @@ func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64)
 // It will be written in out file in Asmbxcoff, because it must be
 // at the very end, especially after relocation sections which needs symbols' index.
 func (f *xcoffFile) asmaixsym(ctxt *Link) {
+       ldr := ctxt.loader
        // Get correct size for symbols wrapping others symbols like go.string.*
        // sym.Size can be used directly as the symbols have already been written.
        for name, size := range outerSymSize {
-               sym := ctxt.Syms.ROLookup(name, 0)
-               if sym == nil {
+               sym := ldr.Lookup(name, 0)
+               if sym == 0 {
                        Errorf(nil, "unknown outer symbol with name %s", name)
                } else {
-                       sym.Size = size
+                       s := ldr.MakeSymbolUpdater(sym)
+                       s.SetSize(size)
+               }
+       }
+
+       // These symbols won't show up in the first loop below because we
+       // skip sym.STEXT symbols. Normal sym.STEXT symbols are emitted by walking textp.
+       s := ldr.Lookup("runtime.text", 0)
+       if ldr.SymType(s) == sym.STEXT {
+               // We've already included this symbol in ctxt.Textp on AIX with external linker.
+               // See data.go:/textaddress
+               if !ctxt.IsExternal() {
+                       putaixsym(ctxt, s, TextSym)
+               }
+       }
+
+       n := 1
+       // Generate base addresses for all text sections if there are multiple
+       for _, sect := range Segtext.Sections[1:] {
+               if sect.Name != ".text" || ctxt.IsExternal() {
+                       // On AIX, runtime.text.X are symbols already in the symtab.
+                       break
+               }
+               s = ldr.Lookup(fmt.Sprintf("runtime.text.%d", n), 0)
+               if s == 0 {
+                       break
+               }
+               if ldr.SymType(s) == sym.STEXT {
+                       putaixsym(ctxt, s, TextSym)
                }
+               n++
        }
 
-       genasmsym(ctxt, putaixsym)
+       s = ldr.Lookup("runtime.etext", 0)
+       if ldr.SymType(s) == sym.STEXT {
+               // We've already included this symbol in ctxt.Textp
+               // on AIX with external linker.
+               // See data.go:/textaddress
+               if !ctxt.IsExternal() {
+                       putaixsym(ctxt, s, TextSym)
+               }
+       }
+
+       shouldBeInSymbolTable := func(s loader.Sym, name string) bool {
+               if name == ".go.buildinfo" {
+                       // On AIX, .go.buildinfo must be in the symbol table as
+                       // it has relocations.
+                       return true
+               }
+               if ldr.AttrNotInSymbolTable(s) {
+                       return false
+               }
+               if (name == "" || name[0] == '.') && !ldr.IsFileLocal(s) && name != ".TOC." {
+                       return false
+               }
+               return true
+       }
+
+       for s, nsym := loader.Sym(1), loader.Sym(ldr.NSym()); s < nsym; s++ {
+               if !shouldBeInSymbolTable(s, ldr.SymName(s)) {
+                       continue
+               }
+               st := ldr.SymType(s)
+               switch {
+               case st == sym.STLSBSS:
+                       if ctxt.IsExternal() {
+                               putaixsym(ctxt, s, TLSSym)
+                       }
+
+               case st == sym.SBSS, st == sym.SNOPTRBSS, st == sym.SLIBFUZZER_EXTRA_COUNTER:
+                       if ldr.AttrReachable(s) {
+                               data := ldr.Data(s)
+                               if len(data) > 0 {
+                                       ldr.Errorf(s, "should not be bss (size=%d type=%v special=%v)", len(data), ldr.SymType(s), ldr.AttrSpecial(s))
+                               }
+                               putaixsym(ctxt, s, BSSSym)
+                       }
+
+               case st >= sym.SELFRXSECT && st < sym.SXREF: // data sections handled in dodata
+                       if ldr.AttrReachable(s) {
+                               putaixsym(ctxt, s, DataSym)
+                       }
+
+               case st == sym.SUNDEFEXT:
+                       putaixsym(ctxt, s, UndefinedSym)
+
+               case st == sym.SDYNIMPORT:
+                       if ldr.AttrReachable(s) {
+                               putaixsym(ctxt, s, UndefinedSym)
+                       }
+               }
+       }
+
+       for _, s := range ctxt.Textp2 {
+               putaixsym(ctxt, s, TextSym)
+       }
+
+       if ctxt.Debugvlog != 0 || *flagN {
+               ctxt.Logf("symsize = %d\n", uint32(Symsize))
+       }
        xfile.updatePreviousFile(ctxt, true)
 }
 
@@ -1264,6 +1365,7 @@ func (f *xcoffFile) writeLdrScn(ctxt *Link, globalOff uint64) {
                Lsymoff:  LDHDRSZ_64,
        }
 
+       ldr := ctxt.loader
        /* Symbol table */
        for _, s := range f.loaderSymbols {
                lds := &XcoffLdSym64{
@@ -1271,19 +1373,19 @@ func (f *xcoffFile) writeLdrScn(ctxt *Link, globalOff uint64) {
                        Lsmtype: s.smtype,
                        Lsmclas: s.smclas,
                }
-               sym := ctxt.loader.Syms[s.sym]
+               sym := s.sym
                switch s.smtype {
                default:
-                       Errorf(sym, "unexpected loader symbol type: 0x%x", s.smtype)
+                       ldr.Errorf(sym, "unexpected loader symbol type: 0x%x", s.smtype)
                case XTY_ENT | XTY_SD:
-                       lds.Lvalue = uint64(sym.Value)
-                       lds.Lscnum = f.getXCOFFscnum(sym.Sect)
+                       lds.Lvalue = uint64(ldr.SymValue(sym))
+                       lds.Lscnum = f.getXCOFFscnum(ldr.SymSect(sym))
                case XTY_IMP:
-                       lds.Lifile = int32(f.dynLibraries[sym.Dynimplib()] + 1)
+                       lds.Lifile = int32(f.dynLibraries[ldr.SymDynimplib(sym)] + 1)
                }
                ldstr := &XcoffLdStr64{
-                       size: uint16(len(sym.Name) + 1), // + null terminator
-                       name: sym.Name,
+                       size: uint16(len(ldr.SymName(sym)) + 1), // + null terminator
+                       name: ldr.SymName(sym),
                }
                stlen += uint32(2 + ldstr.size) // 2 = sizeof ldstr.size
                symtab = append(symtab, lds)
@@ -1296,11 +1398,11 @@ func (f *xcoffFile) writeLdrScn(ctxt *Link, globalOff uint64) {
        off := hdr.Lrldoff                                // current offset is the same of reloc offset
 
        /* Reloc */
-       ep := ctxt.Syms.ROLookup(*flagEntrySymbol, 0)
+       ep := ldr.Lookup(*flagEntrySymbol, 0)
        xldr := &XcoffLdRel64{
-               Lvaddr:  uint64(ep.Value),
+               Lvaddr:  uint64(ldr.SymValue(ep)),
                Lrtype:  0x3F00,
-               Lrsecnm: f.getXCOFFscnum(ep.Sect),
+               Lrsecnm: f.getXCOFFscnum(ldr.SymSect(ep)),
                Lsymndx: 0,
        }
        off += 16
@@ -1308,18 +1410,18 @@ func (f *xcoffFile) writeLdrScn(ctxt *Link, globalOff uint64) {
 
        off += uint64(16 * len(f.loaderReloc))
        for _, r := range f.loaderReloc {
-               symp := r.sym
-               if symp == nil {
-                       symp = ctxt.loader.Syms[r.sym2]
+               symp := r.sym2
+               if symp == 0 {
+                       panic("unexpected 0 sym value")
                }
                xldr = &XcoffLdRel64{
-                       Lvaddr:  uint64(symp.Value + int64(r.roff)),
+                       Lvaddr:  uint64(ldr.SymValue(symp) + int64(r.roff)),
                        Lrtype:  r.rtype,
                        Lsymndx: r.symndx,
                }
 
-               if symp.Sect != nil {
-                       xldr.Lrsecnm = f.getXCOFFscnum(symp.Sect)
+               if ldr.SymSect(symp) != nil {
+                       xldr.Lrsecnm = f.getXCOFFscnum(ldr.SymSect(symp))
                }
 
                reloctab = append(reloctab, xldr)
@@ -1416,6 +1518,7 @@ func (f *xcoffFile) writeFileHeader(ctxt *Link) {
        }
 
        if ctxt.BuildMode == BuildModeExe && ctxt.LinkMode == LinkInternal {
+               ldr := ctxt.loader
                f.xfhdr.Fopthdr = AOUTHSZ_EXEC64
                f.xfhdr.Fflags = F_EXEC
 
@@ -1423,12 +1526,12 @@ func (f *xcoffFile) writeFileHeader(ctxt *Link) {
                f.xahdr.Ovstamp = 1 // based on dump -o
                f.xahdr.Omagic = 0x10b
                copy(f.xahdr.Omodtype[:], "1L")
-               entry := ctxt.Syms.ROLookup(*flagEntrySymbol, 0)
-               f.xahdr.Oentry = uint64(entry.Value)
-               f.xahdr.Osnentry = f.getXCOFFscnum(entry.Sect)
-               toc := ctxt.Syms.ROLookup("TOC", 0)
-               f.xahdr.Otoc = uint64(toc.Value)
-               f.xahdr.Osntoc = f.getXCOFFscnum(toc.Sect)
+               entry := ldr.Lookup(*flagEntrySymbol, 0)
+               f.xahdr.Oentry = uint64(ldr.SymValue(entry))
+               f.xahdr.Osnentry = f.getXCOFFscnum(ldr.SymSect(entry))
+               toc := ldr.Lookup("TOC", 0)
+               f.xahdr.Otoc = uint64(ldr.SymValue(toc))
+               f.xahdr.Osntoc = f.getXCOFFscnum(ldr.SymSect(toc))
 
                f.xahdr.Oalgntext = int16(logBase2(int(Funcalign)))
                f.xahdr.Oalgndata = 0x5
@@ -1534,19 +1637,6 @@ func Asmbxcoff(ctxt *Link, fileoff int64) {
        xcoffwrite(ctxt)
 }
 
-// byOffset is used to sort relocations by offset
-type byOffset []sym.Reloc
-
-func (x byOffset) Len() int { return len(x) }
-
-func (x byOffset) Swap(i, j int) {
-       x[i], x[j] = x[j], x[i]
-}
-
-func (x byOffset) Less(i, j int) bool {
-       return x[i].Off < x[j].Off
-}
-
 // emitRelocations emits relocation entries for go.o in external linking.
 func (f *xcoffFile) emitRelocations(ctxt *Link, fileoff int64) {
        ctxt.Out.SeekSet(fileoff)
@@ -1554,9 +1644,10 @@ func (f *xcoffFile) emitRelocations(ctxt *Link, fileoff int64) {
                ctxt.Out.Write8(0)
        }
 
+       ldr := ctxt.loader
        // relocsect relocates symbols from first in section sect, and returns
        // the total number of relocations emitted.
-       relocsect := func(sect *sym.Section, syms []*sym.Symbol, base uint64) uint32 {
+       relocsect := func(sect *sym.Section, syms []loader.Sym, base uint64) uint32 {
                // ctxt.Logf("%s 0x%x\n", sect.Name, sect.Vaddr)
                // If main section has no bits, nothing to relocate.
                if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
@@ -1564,42 +1655,45 @@ func (f *xcoffFile) emitRelocations(ctxt *Link, fileoff int64) {
                }
                sect.Reloff = uint64(ctxt.Out.Offset())
                for i, s := range syms {
-                       if !s.Attr.Reachable() {
+                       if !ldr.AttrReachable(s) {
                                continue
                        }
-                       if uint64(s.Value) >= sect.Vaddr {
+                       if uint64(ldr.SymValue(s)) >= sect.Vaddr {
                                syms = syms[i:]
                                break
                        }
                }
                eaddr := int64(sect.Vaddr + sect.Length)
                for _, s := range syms {
-                       if !s.Attr.Reachable() {
+                       if !ldr.AttrReachable(s) {
                                continue
                        }
-                       if s.Value >= int64(eaddr) {
+                       if ldr.SymValue(s) >= int64(eaddr) {
                                break
                        }
 
-                       // Relocation must be ordered by address, so s.R is ordered by Off.
-                       sort.Sort(byOffset(s.R))
-
-                       for ri := range s.R {
+                       // Relocation must be ordered by address, so create a list of sorted indices.
+                       relocs := ldr.ExtRelocs(s)
+                       sorted := make([]int, relocs.Count())
+                       for i := 0; i < relocs.Count(); i++ {
+                               sorted[i] = i
+                       }
+                       sort.Slice(sorted, func(i, j int) bool {
+                               return relocs.At(sorted[i]).Off() < relocs.At(sorted[j]).Off()
+                       })
 
-                               r := &s.R[ri]
+                       for _, ri := range sorted {
+                               r := relocs.At(ri)
 
-                               if r.Done {
-                                       continue
-                               }
-                               if r.Xsym == nil {
-                                       Errorf(s, "missing xsym in relocation")
+                               if r.Xsym == 0 {
+                                       ldr.Errorf(s, "missing xsym in relocation")
                                        continue
                                }
-                               if r.Xsym.Dynid < 0 {
-                                       Errorf(s, "reloc %s to non-coff symbol %s (outer=%s) %d %d", r.Type.String(), r.Sym.Name, r.Xsym.Name, r.Sym.Type, r.Xsym.Dynid)
+                               if ldr.SymDynid(r.Xsym) < 0 {
+                                       ldr.Errorf(s, "reloc %s to non-coff symbol %s (outer=%s) %d %d", r.Type(), ldr.SymName(r.Sym()), ldr.SymName(r.Xsym), ldr.SymType(r.Sym()), ldr.SymDynid(r.Xsym))
                                }
-                               if !thearch.Xcoffreloc1(ctxt.Arch, ctxt.Out, s, r, int64(uint64(s.Value+int64(r.Off))-base)) {
-                                       Errorf(s, "unsupported obj reloc %d(%s)/%d to %s", r.Type, r.Type.String(), r.Siz, r.Sym.Name)
+                               if !thearch.Xcoffreloc1(ctxt.Arch, ctxt.Out, ldr, s, r, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-base)) {
+                                       ldr.Errorf(s, "unsupported obj reloc %d(%s)/%d to %s", r.Type(), r.Type(), r.Siz(), ldr.SymName(r.Sym()))
                                }
                        }
                }
@@ -1619,9 +1713,9 @@ func (f *xcoffFile) emitRelocations(ctxt *Link, fileoff int64) {
                for _, seg := range s.segs {
                        for _, sect := range seg.Sections {
                                if sect.Name == ".text" {
-                                       n += relocsect(sect, ctxt.Textp, 0)
+                                       n += relocsect(sect, ctxt.Textp2, 0)
                                } else {
-                                       n += relocsect(sect, ctxt.datap, 0)
+                                       n += relocsect(sect, ctxt.datap2, 0)
                                }
                        }
                }
@@ -1631,9 +1725,9 @@ func (f *xcoffFile) emitRelocations(ctxt *Link, fileoff int64) {
 dwarfLoop:
        for i := 0; i < len(Segdwarf.Sections); i++ {
                sect := Segdwarf.Sections[i]
-               si := dwarfp[i]
-               if si.secSym() != sect.Sym ||
-                       si.secSym().Sect != sect {
+               si := dwarfp2[i]
+               if si.secSym() != loader.Sym(sect.Sym2) ||
+                       ldr.SymSect(si.secSym()) != sect {
                        panic("inconsistency between dwarfp and Segdwarf")
                }
                for _, xcoffSect := range f.sections {
@@ -1655,17 +1749,16 @@ func xcoffCreateExportFile(ctxt *Link) (fname string) {
        fname = filepath.Join(*flagTmpdir, "export_file.exp")
        var buf bytes.Buffer
 
-       for _, s := range ctxt.loader.Syms {
-               if s == nil {
-                       continue
-               }
-               if !s.Attr.CgoExport() {
+       ldr := ctxt.loader
+       for s, nsym := loader.Sym(1), loader.Sym(ldr.NSym()); s < nsym; s++ {
+               if !ldr.AttrCgoExport(s) {
                        continue
                }
-               if !strings.HasPrefix(s.Extname(), "._cgoexp_") {
+               extname := ldr.SymExtname(s)
+               if !strings.HasPrefix(extname, "._cgoexp_") {
                        continue
                }
-               if s.Version != 0 {
+               if ldr.SymVersion(s) != 0 {
                        continue // Only export version 0 symbols. See the comment in doxcoff.
                }
 
@@ -1673,7 +1766,7 @@ func xcoffCreateExportFile(ctxt *Link) (fname string) {
                // exported by cgo.
                // The corresponding Go symbol is:
                // _cgoexp_hashcode_symname.
-               name := strings.SplitN(s.Extname(), "_", 4)[3]
+               name := strings.SplitN(extname, "_", 4)[3]
 
                buf.Write([]byte(name + "\n"))
        }
@@ -1684,5 +1777,4 @@ func xcoffCreateExportFile(ctxt *Link) (fname string) {
        }
 
        return fname
-
 }
index 185d668db7cd17e2068ea35eda903e95b6fb41ab..9e89b4b8019b042dda80139bcb12b113f44dc273 100644 (file)
@@ -403,22 +403,22 @@ func addelfdynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s lo
        return false
 }
 
-func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
+func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool {
        rs := r.Xsym
 
        emitReloc := func(v uint16, off uint64) {
                out.Write64(uint64(sectoff) + off)
-               out.Write32(uint32(rs.Dynid))
+               out.Write32(uint32(ldr.SymDynid(rs)))
                out.Write16(v)
        }
 
        var v uint16
-       switch r.Type {
+       switch r.Type() {
        default:
                return false
        case objabi.R_ADDR, objabi.R_DWARFSECREF:
                v = ld.XCOFF_R_POS
-               if r.Siz == 4 {
+               if r.Siz() == 4 {
                        v |= 0x1F << 8
                } else {
                        v |= 0x3F << 8
@@ -431,7 +431,7 @@ func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, se
        case objabi.R_POWER_TLS_LE:
                emitReloc(ld.XCOFF_R_TLS_LE|0x0F<<8, 2)
        case objabi.R_CALLPOWER:
-               if r.Siz != 4 {
+               if r.Siz() != 4 {
                        return false
                }
                emitReloc(ld.XCOFF_R_RBR|0x19<<8, 0)