diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go index f2b76fb78b..30fab9de1c 100644 --- a/src/cmd/link/internal/amd64/asm.go +++ b/src/cmd/link/internal/amd64/asm.go @@ -522,20 +522,21 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sy return true } -func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool { +func pereloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool { var v uint32 rs := r.Xsym + rt := r.Type() - if rs.Dynid < 0 { - ld.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type) + if ldr.SymDynid(rs) < 0 { + ldr.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", rt, sym.RelocName(arch, rt), ldr.SymName(rs), ldr.SymType(rs), ldr.SymType(rs)) return false } out.Write32(uint32(sectoff)) - out.Write32(uint32(rs.Dynid)) + out.Write32(uint32(ldr.SymDynid(rs))) - switch r.Type { + switch rt { default: return false @@ -543,7 +544,7 @@ func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, secto v = ld.IMAGE_REL_AMD64_SECREL case objabi.R_ADDR: - if r.Siz == 8 { + if r.Siz() == 8 { v = ld.IMAGE_REL_AMD64_ADDR64 } else { v = ld.IMAGE_REL_AMD64_ADDR32 diff --git a/src/cmd/link/internal/arm/asm.go b/src/cmd/link/internal/arm/asm.go index e01124f0a9..e910d3785f 100644 --- a/src/cmd/link/internal/arm/asm.go +++ b/src/cmd/link/internal/arm/asm.go @@ -322,19 +322,20 @@ func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtRe return false } -func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool { +func pereloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool { rs := r.Xsym + rt := r.Type() - if rs.Dynid < 0 { - ld.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type) + if ldr.SymDynid(rs) < 0 { + ldr.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", rt, sym.RelocName(arch, rt), ldr.SymName(rs), ldr.SymType(rs), ldr.SymType(rs)) return false } out.Write32(uint32(sectoff)) - out.Write32(uint32(rs.Dynid)) + out.Write32(uint32(ldr.SymDynid(rs))) var v uint32 - switch r.Type { + switch rt { default: // unsupported relocation type return false diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 8fc1f737c2..3c9914a219 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -278,7 +278,7 @@ type Arch struct { Gentext func(*Link) Gentext2 func(*Link, *loader.Loader) Machoreloc1 func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtRelocView, int64) bool - PEreloc1 func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, 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 // TLSIEtoLE converts a TLS Initial Executable relocation to diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index 75d6bbf05d..176c3b00bf 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -319,16 +319,15 @@ func Main(arch *sys.Arch, theArch Arch) { ctxt.loader.InitOutData() thearch.Asmb(ctxt, ctxt.loader) newreloc := ctxt.Is386() || ctxt.IsAMD64() || ctxt.IsARM() || ctxt.IsARM64() || ctxt.IsMIPS() || ctxt.IsMIPS64() || ctxt.IsRISCV64() || ctxt.IsS390X() || ctxt.IsWasm() || ctxt.IsPPC64() - newasmb2 := ctxt.IsDarwin() + newasmb2 := ctxt.IsDarwin() || ctxt.IsWindows() if newreloc { bench.Start("reloc") ctxt.reloc() if !newasmb2 { bench.Start("loadlibfull") // We don't need relocations at this point. - // An exception is internal linking on Windows, see pe.go:addPEBaseRelocSym - // Wasm is another exception, where it applies text relocations in Asmb2. - needReloc := (ctxt.IsWindows() && ctxt.IsInternal()) || ctxt.IsWasm() + // Wasm is an exception, where it applies text relocations in Asmb2. + needReloc := ctxt.IsWasm() // 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) diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go index 362d2fd0a5..5edba67a59 100644 --- a/src/cmd/link/internal/ld/pe.go +++ b/src/cmd/link/internal/ld/pe.go @@ -472,8 +472,8 @@ func (f *peFile) addInitArray(ctxt *Link) *peSection { ctxt.Out.SeekSet(int64(sect.pointerToRawData)) sect.checkOffset(ctxt.Out.Offset()) - init_entry := ctxt.Syms.Lookup(*flagEntrySymbol, 0) - addr := uint64(init_entry.Value) - init_entry.Sect.Vaddr + init_entry := ctxt.loader.Lookup(*flagEntrySymbol, 0) + addr := uint64(ctxt.loader.SymValue(init_entry)) - ctxt.loader.SymSect(init_entry).Vaddr switch objabi.GOARCH { case "386", "arm": ctxt.Out.Write32(uint32(addr)) @@ -489,62 +489,62 @@ func (f *peFile) emitRelocations(ctxt *Link) { 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) int { + relocsect := func(sect *sym.Section, syms []loader.Sym, base uint64) int { // If main section has no bits, nothing to relocate. if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen { return 0 } - relocs := 0 + nrelocs := 0 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 := int32(sect.Vaddr + sect.Length) - for _, sym := range syms { - if !sym.Attr.Reachable() { + for _, s := range syms { + if !ldr.AttrReachable(s) { continue } - if sym.Value >= int64(eaddr) { + if ldr.SymValue(s) >= int64(eaddr) { break } - for ri := range sym.R { - r := &sym.R[ri] - if r.Done { + relocs := ldr.ExtRelocs(s) + for ri := 0; ri < relocs.Count(); ri++ { + r := relocs.At(ri) + if r.Xsym == 0 { + ctxt.Errorf(s, "missing xsym in relocation") continue } - if r.Xsym == nil { - Errorf(sym, "missing xsym in relocation") - continue + if ldr.SymDynid(r.Xsym) < 0 { + ctxt.Errorf(s, "reloc %d to non-coff symbol %s (outer=%s) %d", r.Type(), ldr.SymName(r.Sym()), ldr.SymName(r.Xsym), ldr.SymType(r.Sym())) } - if r.Xsym.Dynid < 0 { - Errorf(sym, "reloc %d to non-coff symbol %s (outer=%s) %d", r.Type, r.Sym.Name, r.Xsym.Name, r.Sym.Type) + if !thearch.PEreloc1(ctxt.Arch, ctxt.Out, ldr, s, r, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-base)) { + ctxt.Errorf(s, "unsupported obj reloc %d/%d to %s", r.Type(), r.Siz(), ldr.SymName(r.Sym())) } - if !thearch.PEreloc1(ctxt.Arch, ctxt.Out, sym, r, int64(uint64(sym.Value+int64(r.Off))-base)) { - Errorf(sym, "unsupported obj reloc %d/%d to %s", r.Type, r.Siz, r.Sym.Name) - } - relocs++ + nrelocs++ } } sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff - return relocs + return nrelocs } sects := []struct { peSect *peSection seg *sym.Segment - syms []*sym.Symbol + syms []loader.Sym }{ - {f.textSect, &Segtext, ctxt.Textp}, - {f.rdataSect, &Segrodata, ctxt.datap}, - {f.dataSect, &Segdata, ctxt.datap}, + {f.textSect, &Segtext, ctxt.Textp2}, + {f.rdataSect, &Segrodata, ctxt.datap2}, + {f.dataSect, &Segdata, ctxt.datap2}, } for _, s := range sects { s.peSect.emitRelocations(ctxt.Out, func() int { @@ -559,9 +559,9 @@ func (f *peFile) emitRelocations(ctxt *Link) { 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 _, pesect := range f.sections { @@ -576,12 +576,12 @@ dwarfLoop: } f.ctorsSect.emitRelocations(ctxt.Out, func() int { - dottext := ctxt.Syms.Lookup(".text", 0) + dottext := ldr.Lookup(".text", 0) ctxt.Out.Write32(0) - ctxt.Out.Write32(uint32(dottext.Dynid)) + ctxt.Out.Write32(uint32(ldr.SymDynid(dottext))) switch objabi.GOARCH { default: - Errorf(dottext, "unknown architecture for PE: %q\n", objabi.GOARCH) + ctxt.Errorf(dottext, "unknown architecture for PE: %q\n", objabi.GOARCH) case "386": ctxt.Out.Write16(IMAGE_REL_I386_DIR32) case "amd64": @@ -595,12 +595,12 @@ dwarfLoop: // writeSymbol appends symbol s to file f symbol table. // It also sets s.Dynid to written symbol number. -func (f *peFile) writeSymbol(out *OutBuf, s *sym.Symbol, value int64, sectidx int, typ uint16, class uint8) { - if len(s.Name) > 8 { +func (f *peFile) writeSymbol(out *OutBuf, ldr *loader.Loader, s loader.Sym, name string, value int64, sectidx int, typ uint16, class uint8) { + if len(name) > 8 { out.Write32(0) - out.Write32(uint32(f.stringTable.add(s.Name))) + out.Write32(uint32(f.stringTable.add(name))) } else { - out.WriteStringN(s.Name, 8) + out.WriteStringN(name, 8) } out.Write32(uint32(value)) out.Write16(uint16(sectidx)) @@ -608,31 +608,32 @@ func (f *peFile) writeSymbol(out *OutBuf, s *sym.Symbol, value int64, sectidx in out.Write8(class) out.Write8(0) // no aux entries - s.Dynid = int32(f.symbolCount) + ldr.SetSymDynid(s, int32(f.symbolCount)) f.symbolCount++ } // mapToPESection searches peFile f for s symbol's location. // It returns PE section index, and offset within that section. -func (f *peFile) mapToPESection(s *sym.Symbol, linkmode LinkMode) (pesectidx int, offset int64, err error) { - if s.Sect == nil { - return 0, 0, fmt.Errorf("could not map %s symbol with no section", s.Name) +func (f *peFile) mapToPESection(ldr *loader.Loader, s loader.Sym, linkmode LinkMode) (pesectidx int, offset int64, err error) { + sect := ldr.SymSect(s) + if sect == nil { + return 0, 0, fmt.Errorf("could not map %s symbol with no section", ldr.SymName(s)) } - if s.Sect.Seg == &Segtext { - return f.textSect.index, int64(uint64(s.Value) - Segtext.Vaddr), nil + if sect.Seg == &Segtext { + return f.textSect.index, int64(uint64(ldr.SymValue(s)) - Segtext.Vaddr), nil } - if s.Sect.Seg == &Segrodata { - return f.rdataSect.index, int64(uint64(s.Value) - Segrodata.Vaddr), nil + if sect.Seg == &Segrodata { + return f.rdataSect.index, int64(uint64(ldr.SymValue(s)) - Segrodata.Vaddr), nil } - if s.Sect.Seg != &Segdata { - return 0, 0, fmt.Errorf("could not map %s symbol with non .text or .rdata or .data section", s.Name) + if sect.Seg != &Segdata { + return 0, 0, fmt.Errorf("could not map %s symbol with non .text or .rdata or .data section", ldr.SymName(s)) } - v := uint64(s.Value) - Segdata.Vaddr + v := uint64(ldr.SymValue(s)) - Segdata.Vaddr if linkmode != LinkExternal { return f.dataSect.index, int64(v), nil } - if s.Type == sym.SDATA { + if ldr.SymType(s) == sym.SDATA { return f.dataSect.index, int64(v), nil } // Note: although address of runtime.edata (type sym.SDATA) is at the start of .bss section @@ -645,60 +646,100 @@ func (f *peFile) mapToPESection(s *sym.Symbol, linkmode LinkMode) (pesectidx int // writeSymbols writes all COFF symbol table records. func (f *peFile) writeSymbols(ctxt *Link) { + ldr := ctxt.loader + addsym := func(s loader.Sym) { + t := ldr.SymType(s) + if ldr.SymSect(s) == nil && t != sym.SDYNIMPORT && t != sym.SHOSTOBJ && t != sym.SUNDEFEXT { + return + } - put := func(ctxt *Link, s *sym.Symbol, name string, type_ SymbolType, addr int64) { - if s == nil { - return - } - if s.Sect == nil && type_ != UndefinedSym { - return - } - switch type_ { - default: - return - case DataSym, BSSSym, TextSym, UndefinedSym: - } + name := ldr.SymName(s) // Only windows/386 requires underscore prefix on external symbols. - if ctxt.Arch.Family == sys.I386 && - ctxt.LinkMode == LinkExternal && - (s.Type == sym.SHOSTOBJ || s.Type == sym.SUNDEFEXT || s.Attr.CgoExport()) { - s.Name = "_" + s.Name + if ctxt.Is386() && ctxt.IsExternal() && + (t == sym.SHOSTOBJ || t == sym.SUNDEFEXT || ldr.AttrCgoExport(s)) { + name = "_" + name } - var typ uint16 - if ctxt.LinkMode == LinkExternal { - typ = IMAGE_SYM_TYPE_NULL + var peSymType uint16 + if ctxt.IsExternal() { + peSymType = IMAGE_SYM_TYPE_NULL } else { // TODO: fix IMAGE_SYM_DTYPE_ARRAY value and use following expression, instead of 0x0308 - typ = IMAGE_SYM_DTYPE_ARRAY<<8 + IMAGE_SYM_TYPE_STRUCT - typ = 0x0308 // "array of structs" + // peSymType = IMAGE_SYM_DTYPE_ARRAY<<8 + IMAGE_SYM_TYPE_STRUCT + peSymType = 0x0308 // "array of structs" } - sect, value, err := f.mapToPESection(s, ctxt.LinkMode) + sect, value, err := f.mapToPESection(ldr, s, ctxt.LinkMode) if err != nil { - if type_ == UndefinedSym { - typ = IMAGE_SYM_DTYPE_FUNCTION + if t == sym.SDYNIMPORT || t == sym.SHOSTOBJ || t == sym.SUNDEFEXT { + peSymType = IMAGE_SYM_DTYPE_FUNCTION } else { - Errorf(s, "addpesym: %v", err) + ctxt.Errorf(s, "addpesym: %v", err) } } class := IMAGE_SYM_CLASS_EXTERNAL - if s.IsFileLocal() || s.Attr.VisibilityHidden() || s.Attr.Local() { + if ldr.IsFileLocal(s) || ldr.AttrVisibilityHidden(s) || ldr.AttrLocal(s) { class = IMAGE_SYM_CLASS_STATIC } - f.writeSymbol(ctxt.Out, s, value, sect, typ, uint8(class)) + f.writeSymbol(ctxt.Out, ldr, s, name, value, sect, peSymType, uint8(class)) } if ctxt.LinkMode == LinkExternal { // Include section symbols as external, because // .ctors and .debug_* section relocations refer to it. for _, pesect := range f.sections { - sym := ctxt.Syms.Lookup(pesect.name, 0) - f.writeSymbol(ctxt.Out, sym, 0, pesect.index, IMAGE_SYM_TYPE_NULL, IMAGE_SYM_CLASS_STATIC) + s := ldr.LookupOrCreateSym(pesect.name, 0) + f.writeSymbol(ctxt.Out, ldr, s, pesect.name, 0, pesect.index, IMAGE_SYM_TYPE_NULL, IMAGE_SYM_CLASS_STATIC) } } - genasmsym(ctxt, put) + // Add special runtime.text and runtime.etext symbols. + s := ldr.Lookup("runtime.text", 0) + if ldr.SymType(s) == sym.STEXT { + addsym(s) + } + s = ldr.Lookup("runtime.etext", 0) + if ldr.SymType(s) == sym.STEXT { + addsym(s) + } + + // Add text symbols. + for _, s := range ctxt.Textp2 { + addsym(s) + } + + shouldBeInSymbolTable := func(s loader.Sym) bool { + if ldr.AttrNotInSymbolTable(s) { + return false + } + name := ldr.RawSymName(s) // TODO: try not to read the name + if name == "" || name[0] == '.' { + return false + } + return true + } + + // Add data symbols and external references. + for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ { + if !ldr.AttrReachable(s) { + continue + } + t := ldr.SymType(s) + if t >= sym.SELFRXSECT && t < sym.SXREF { // data sections handled in dodata + if t == sym.STLSBSS { + continue + } + if !shouldBeInSymbolTable(s) { + continue + } + addsym(s) + } + + switch t { + case sym.SDYNIMPORT, sym.SHOSTOBJ, sym.SUNDEFEXT, sym.SCONST: + addsym(s) + } + } } // writeSymbolTableAndStringTable writes out symbol and string tables for peFile f. @@ -800,8 +841,8 @@ func (f *peFile) writeOptionalHeader(ctxt *Link) { oh64.SizeOfUninitializedData = 0 oh.SizeOfUninitializedData = 0 if ctxt.LinkMode != LinkExternal { - oh64.AddressOfEntryPoint = uint32(Entryvalue(ctxt) - PEBASE) - oh.AddressOfEntryPoint = uint32(Entryvalue(ctxt) - PEBASE) + oh64.AddressOfEntryPoint = uint32(Entryvalue2(ctxt) - PEBASE) + oh.AddressOfEntryPoint = uint32(Entryvalue2(ctxt) - PEBASE) } oh64.BaseOfCode = f.textSect.virtualAddress oh.BaseOfCode = f.textSect.virtualAddress @@ -1109,7 +1150,7 @@ func peimporteddlls() []string { func addimports(ctxt *Link, datsect *peSection) { ldr := ctxt.loader startoff := ctxt.Out.Offset() - dynamic := ctxt.Syms.Lookup(".windynamic", 0) + dynamic := ldr.LookupOrCreateSym(".windynamic", 0) // skip import descriptor table (will write it later) n := uint64(0) @@ -1130,7 +1171,7 @@ func addimports(ctxt *Link, datsect *peSection) { for m := d.ms; m != nil; m = m.next { m.off = uint64(pefile.nextSectOffset) + uint64(ctxt.Out.Offset()) - uint64(startoff) ctxt.Out.Write16(0) // hint - strput(ctxt.Out, ldr.Syms[m.s].Extname()) + strput(ctxt.Out, ldr.SymExtname(m.s)) } } @@ -1165,7 +1206,7 @@ func addimports(ctxt *Link, datsect *peSection) { endoff := ctxt.Out.Offset() // write FirstThunks (allocated in .data section) - ftbase := uint64(dynamic.Value) - uint64(datsect.virtualAddress) - PEBASE + ftbase := uint64(ldr.SymValue(dynamic)) - uint64(datsect.virtualAddress) - PEBASE ctxt.Out.SeekSet(int64(uint64(datsect.pointerToRawData) + ftbase)) for d := dr; d != nil; d = d.next { @@ -1205,8 +1246,8 @@ func addimports(ctxt *Link, datsect *peSection) { // update data directory pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect.virtualAddress pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect.virtualSize - pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = uint32(dynamic.Value - PEBASE) - pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].Size = uint32(dynamic.Size) + pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = uint32(ldr.SymValue(dynamic) - PEBASE) + pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].Size = uint32(ldr.SymSize(dynamic)) out.SeekSet(endoff) } @@ -1235,7 +1276,7 @@ func addexports(ctxt *Link) { nexport := len(dexport) size := binary.Size(&e) + 10*nexport + len(*flagOutfile) + 1 for _, s := range dexport { - size += len(ldr.Syms[s].Extname()) + 1 + size += len(ldr.SymExtname(s)) + 1 } if nexport == 0 { @@ -1271,7 +1312,7 @@ func addexports(ctxt *Link) { // put EXPORT Address Table for _, s := range dexport { - out.Write32(uint32(ldr.Syms[s].Value - PEBASE)) + out.Write32(uint32(ldr.SymValue(s) - PEBASE)) } // put EXPORT Name Pointer Table @@ -1279,7 +1320,7 @@ func addexports(ctxt *Link) { for _, s := range dexport { out.Write32(uint32(v)) - v += len(ldr.Syms[s].Extname()) + 1 + v += len(ldr.SymExtname(s)) + 1 } // put EXPORT Ordinal Table @@ -1291,8 +1332,8 @@ func addexports(ctxt *Link) { out.WriteStringN(*flagOutfile, len(*flagOutfile)+1) for _, s := range dexport { - ss := ldr.Syms[s] - out.WriteStringN(ss.Extname(), len(ss.Extname())+1) + name := ldr.SymExtname(s) + out.WriteStringN(name, len(name)+1) } sect.pad(out, uint32(size)) } @@ -1300,8 +1341,6 @@ func addexports(ctxt *Link) { // peBaseRelocEntry represents a single relocation entry. type peBaseRelocEntry struct { typeOff uint16 - rel *sym.Reloc - sym *sym.Symbol // For debug } // peBaseRelocBlock represents a Base Relocation Block. A block @@ -1338,13 +1377,13 @@ func (rt *peBaseRelocTable) init(ctxt *Link) { rt.blocks = make(map[uint32]peBaseRelocBlock) } -func (rt *peBaseRelocTable) addentry(ctxt *Link, s *sym.Symbol, r *sym.Reloc) { +func (rt *peBaseRelocTable) addentry(ldr *loader.Loader, s loader.Sym, r *loader.Reloc2) { // pageSize is the size in bytes of a page // described by a base relocation block. const pageSize = 0x1000 const pageMask = pageSize - 1 - addr := s.Value + int64(r.Off) - int64(PEBASE) + addr := ldr.SymValue(s) + int64(r.Off()) - int64(PEBASE) page := uint32(addr &^ pageMask) off := uint32(addr & pageMask) @@ -1355,12 +1394,10 @@ func (rt *peBaseRelocTable) addentry(ctxt *Link, s *sym.Symbol, r *sym.Reloc) { e := peBaseRelocEntry{ typeOff: uint16(off & 0xFFF), - rel: r, - sym: s, } // Set entry type - switch r.Siz { + switch r.Siz() { default: Exitf("unsupported relocation size %d\n", r.Siz) case 4: @@ -1392,30 +1429,32 @@ func (rt *peBaseRelocTable) write(ctxt *Link) { } } -func addPEBaseRelocSym(ctxt *Link, s *sym.Symbol, rt *peBaseRelocTable) { - for ri := 0; ri < len(s.R); ri++ { - r := &s.R[ri] - - if r.Sym == nil { +func addPEBaseRelocSym(ldr *loader.Loader, s loader.Sym, rt *peBaseRelocTable) { + relocs := ldr.Relocs(s) + for ri := 0; ri < relocs.Count(); ri++ { + r := relocs.At2(ri) + if r.Type() >= objabi.ElfRelocOffset { continue } - if !r.Sym.Attr.Reachable() { + if r.Siz() == 0 { // informational relocation continue } - if r.Type >= objabi.ElfRelocOffset { + if r.Type() == objabi.R_DWARFFILEREF { continue } - if r.Siz == 0 { // informational relocation + rs := r.Sym() + rs = ldr.ResolveABIAlias(rs) + if rs == 0 { continue } - if r.Type == objabi.R_DWARFFILEREF { + if !ldr.AttrReachable(s) { continue } - switch r.Type { + switch r.Type() { default: case objabi.R_ADDR: - rt.addentry(ctxt, s, r) + rt.addentry(ldr, s, &r) } } } @@ -1437,11 +1476,12 @@ func addPEBaseReloc(ctxt *Link) { rt.init(ctxt) // Get relocation information - for _, s := range ctxt.Textp { - addPEBaseRelocSym(ctxt, s, &rt) + ldr := ctxt.loader + for _, s := range ctxt.Textp2 { + addPEBaseRelocSym(ldr, s, &rt) } - for _, s := range ctxt.datap { - addPEBaseRelocSym(ctxt, s, &rt) + for _, s := range ctxt.datap2 { + addPEBaseRelocSym(ldr, s, &rt) } // Write relocation information diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 02cd0b89d8..0990768903 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -692,6 +692,8 @@ func (l *Loader) SymVersion(i Sym) int { return int(abiToVer(r.Sym(li).ABI(), r.version)) } +func (l *Loader) IsFileLocal(i Sym) bool { return l.SymVersion(i) >= sym.SymVerStatic } + // Returns the type of the i-th symbol. func (l *Loader) SymType(i Sym) sym.SymKind { if l.IsExternal(i) { diff --git a/src/cmd/link/internal/x86/asm.go b/src/cmd/link/internal/x86/asm.go index 5297d15e39..b42bfd3dc2 100644 --- a/src/cmd/link/internal/x86/asm.go +++ b/src/cmd/link/internal/x86/asm.go @@ -402,20 +402,21 @@ func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtRe return false } -func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool { +func pereloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool { var v uint32 rs := r.Xsym + rt := r.Type() - if rs.Dynid < 0 { - ld.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type) + if ldr.SymDynid(rs) < 0 { + ldr.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", rt, sym.RelocName(arch, rt), ldr.SymName(rs), ldr.SymType(rs), ldr.SymType(rs)) return false } out.Write32(uint32(sectoff)) - out.Write32(uint32(rs.Dynid)) + out.Write32(uint32(ldr.SymDynid(rs))) - switch r.Type { + switch rt { default: return false