diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go index 9a3af983a3..7754cf9bfa 100644 --- a/src/cmd/link/internal/amd64/asm.go +++ b/src/cmd/link/internal/amd64/asm.go @@ -185,6 +185,38 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade } return true + case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SUBTRACTOR*2 + 0: + // X86_64_RELOC_SUBTRACTOR must be followed by X86_64_RELOC_UNSIGNED. + // The pair of relocations resolves to the difference between two + // symbol addresses (each relocation specifies a symbol). + // See Darwin's header file include/mach-o/x86_64/reloc.h. + // ".quad _foo - _bar" is expressed as + // r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_bar + // r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo + // + // For the cases we care (the race syso), the symbol being subtracted + // out is always in the current section, so we can just convert it to + // a PC-relative relocation, with the addend adjusted. + // If later we need the more general form, we can introduce objabi.R_DIFF + // that works like this Mach-O relocation. + su := ldr.MakeSymbolUpdater(s) + outer, off := ld.FoldSubSymbolOffset(ldr, targ) + if outer != s { + ldr.Errorf(s, "unsupported X86_64_RELOC_SUBTRACTOR reloc: target %s, outer %s", + ldr.SymName(targ), ldr.SymName(outer)) + break + } + relocs := su.Relocs() + if rIdx+1 >= relocs.Count() || relocs.At(rIdx+1).Type() != objabi.MachoRelocOffset+ld.MACHO_X86_64_RELOC_UNSIGNED*2+0 || relocs.At(rIdx+1).Off() != r.Off() { + ldr.Errorf(s, "unexpected X86_64_RELOC_SUBTRACTOR reloc, must be followed by X86_64_RELOC_UNSIGNED at the same offset: %d %v %d", rIdx, relocs.At(rIdx+1).Type(), relocs.At(rIdx+1).Off()) + } + // The second relocation has the target symbol we want + su.SetRelocType(rIdx+1, objabi.R_PCREL) + su.SetRelocAdd(rIdx+1, r.Add()+int64(r.Off())-off) + // Remove the other relocation + su.SetRelocSiz(rIdx, 0) + return true + case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_BRANCH*2 + 1: if targType == sym.SDYNIMPORT { addpltsym(target, ldr, syms, targ) diff --git a/src/cmd/link/internal/loader/symbolbuilder.go b/src/cmd/link/internal/loader/symbolbuilder.go index 8abbb931e5..35749f9ea9 100644 --- a/src/cmd/link/internal/loader/symbolbuilder.go +++ b/src/cmd/link/internal/loader/symbolbuilder.go @@ -139,6 +139,11 @@ func (sb *SymbolBuilder) SetRelocAdd(i int, a int64) { sb.relocs[i].SetAdd(a) } +// SetRelocAdd sets the size of the 'i'-th relocation on this sym to 'sz' +func (sb *SymbolBuilder) SetRelocSiz(i int, sz uint8) { + sb.relocs[i].SetSiz(sz) +} + // Add n relocations, return a handle to the relocations. func (sb *SymbolBuilder) AddRelocs(n int) Relocs { sb.relocs = append(sb.relocs, make([]goobj.Reloc, n)...) diff --git a/src/cmd/link/internal/loadmacho/ldmacho.go b/src/cmd/link/internal/loadmacho/ldmacho.go index 0d2bca28e9..5e8022ce69 100644 --- a/src/cmd/link/internal/loadmacho/ldmacho.go +++ b/src/cmd/link/internal/loadmacho/ldmacho.go @@ -790,8 +790,6 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, rAdd = 0 // clear rAdd for next iteration } - - sb.SortRelocs() } return textp, nil