From: Jeremy Faller Date: Mon, 11 May 2020 18:35:54 +0000 (-0400) Subject: [dev.link] cmd/link: move xcoff to loader represenatation X-Git-Tag: go1.16beta1~1378^2~127 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=4e03dac77c2a8f5c3a16fc2a66477f2140d8394b;p=gostls13.git [dev.link] cmd/link: move xcoff to loader represenatation Change-Id: I5b260493ffd7945f665c466e892be18d81e7940a Reviewed-on: https://go-review.googlesource.com/c/go/+/233340 Run-TryBot: Jeremy Faller Reviewed-by: Than McIntosh Reviewed-by: Cherry Zhang --- diff --git a/src/cmd/link/internal/ld/data2.go b/src/cmd/link/internal/ld/data2.go deleted file mode 100644 index 0b3c6f01e1..0000000000 --- a/src/cmd/link/internal/ld/data2.go +++ /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 -} diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index e5378225dc..d3382b5252 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -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. diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index 465a765db8..bc170f9eb8 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -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) diff --git a/src/cmd/link/internal/ld/xcoff.go b/src/cmd/link/internal/ld/xcoff.go index 96c5a58af5..506dde232f 100644 --- a/src/cmd/link/internal/ld/xcoff.go +++ b/src/cmd/link/internal/ld/xcoff.go @@ -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 - } diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go index 185d668db7..9e89b4b801 100644 --- a/src/cmd/link/internal/ppc64/asm.go +++ b/src/cmd/link/internal/ppc64/asm.go @@ -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)