Index: ELF/Arch/AArch64.cpp =================================================================== --- ELF/Arch/AArch64.cpp +++ ELF/Arch/AArch64.cpp @@ -59,6 +59,7 @@ GotRel = R_AARCH64_GLOB_DAT; NoneRel = R_AARCH64_NONE; PltRel = R_AARCH64_JUMP_SLOT; + SymbolicRel = R_AARCH64_ABS64; TlsDescRel = R_AARCH64_TLSDESC; TlsGotRel = R_AARCH64_TLS_TPREL64; PltEntrySize = 16; @@ -258,7 +259,6 @@ write32le(Loc, Val); break; case R_AARCH64_ABS64: - case R_AARCH64_GLOB_DAT: case R_AARCH64_PREL64: write64le(Loc, Val); break; Index: ELF/Arch/AMDGPU.cpp =================================================================== --- ELF/Arch/AMDGPU.cpp +++ ELF/Arch/AMDGPU.cpp @@ -35,6 +35,7 @@ RelativeRel = R_AMDGPU_RELATIVE64; GotRel = R_AMDGPU_ABS64; NoneRel = R_AMDGPU_NONE; + SymbolicRel = R_AMDGPU_ABS64; } static uint32_t getEFlags(InputFile *File) { Index: ELF/Arch/ARM.cpp =================================================================== --- ELF/Arch/ARM.cpp +++ ELF/Arch/ARM.cpp @@ -52,6 +52,7 @@ GotRel = R_ARM_GLOB_DAT; NoneRel = R_ARM_NONE; PltRel = R_ARM_JUMP_SLOT; + SymbolicRel = R_ARM_ABS32; TlsGotRel = R_ARM_TLS_TPOFF32; TlsModuleIndexRel = R_ARM_TLS_DTPMOD32; TlsOffsetRel = R_ARM_TLS_DTPOFF32; @@ -377,7 +378,6 @@ switch (Type) { case R_ARM_ABS32: case R_ARM_BASE_PREL: - case R_ARM_GLOB_DAT: case R_ARM_GOTOFF32: case R_ARM_GOT_BREL: case R_ARM_GOT_PREL: Index: ELF/Arch/Hexagon.cpp =================================================================== --- ELF/Arch/Hexagon.cpp +++ ELF/Arch/Hexagon.cpp @@ -40,6 +40,7 @@ PltRel = R_HEX_JMP_SLOT; RelativeRel = R_HEX_RELATIVE; GotRel = R_HEX_GLOB_DAT; + SymbolicRel = R_HEX_32; // The zero'th GOT entry is reserved for the address of _DYNAMIC. The // next 3 are reserved for the dynamic loader. Index: ELF/Arch/Mips.cpp =================================================================== --- ELF/Arch/Mips.cpp +++ ELF/Arch/Mips.cpp @@ -59,11 +59,13 @@ if (ELFT::Is64Bits) { RelativeRel = (R_MIPS_64 << 8) | R_MIPS_REL32; + SymbolicRel = R_MIPS_64; TlsGotRel = R_MIPS_TLS_TPREL64; TlsModuleIndexRel = R_MIPS_TLS_DTPMOD64; TlsOffsetRel = R_MIPS_TLS_DTPREL64; } else { RelativeRel = R_MIPS_REL32; + SymbolicRel = R_MIPS_32; TlsGotRel = R_MIPS_TLS_TPREL32; TlsModuleIndexRel = R_MIPS_TLS_DTPMOD32; TlsOffsetRel = R_MIPS_TLS_DTPREL32; Index: ELF/Arch/PPC.cpp =================================================================== --- ELF/Arch/PPC.cpp +++ ELF/Arch/PPC.cpp @@ -135,6 +135,7 @@ PltRel = R_PPC_JMP_SLOT; RelativeRel = R_PPC_RELATIVE; IRelativeRel = R_PPC_IRELATIVE; + SymbolicRel = R_PPC_ADDR32; GotBaseSymInGotPlt = false; GotHeaderEntriesNum = 3; GotPltHeaderEntriesNum = 0; @@ -288,7 +289,6 @@ write16(Loc, Val); break; case R_PPC_ADDR32: - case R_PPC_GLOB_DAT: case R_PPC_REL32: write32(Loc, Val); break; Index: ELF/Arch/PPC64.cpp =================================================================== --- ELF/Arch/PPC64.cpp +++ ELF/Arch/PPC64.cpp @@ -288,6 +288,7 @@ PltRel = R_PPC64_JMP_SLOT; RelativeRel = R_PPC64_RELATIVE; IRelativeRel = R_PPC64_IRELATIVE; + SymbolicRel = R_PPC64_ADDR64; PltEntrySize = 4; GotBaseSymInGotPlt = false; GotHeaderEntriesNum = 1; Index: ELF/Arch/SPARCV9.cpp =================================================================== --- ELF/Arch/SPARCV9.cpp +++ ELF/Arch/SPARCV9.cpp @@ -37,6 +37,7 @@ NoneRel = R_SPARC_NONE; PltRel = R_SPARC_JMP_SLOT; RelativeRel = R_SPARC_RELATIVE; + SymbolicRel = R_SPARC_64; PltEntrySize = 32; PltHeaderSize = 4 * PltEntrySize; @@ -114,7 +115,6 @@ break; case R_SPARC_64: case R_SPARC_UA64: - case R_SPARC_GLOB_DAT: // V-xword64 write64be(Loc, Val); break; Index: ELF/Arch/X86.cpp =================================================================== --- ELF/Arch/X86.cpp +++ ELF/Arch/X86.cpp @@ -52,6 +52,7 @@ PltRel = R_386_JUMP_SLOT; IRelativeRel = R_386_IRELATIVE; RelativeRel = R_386_RELATIVE; + SymbolicRel = R_386_32; TlsGotRel = R_386_TLS_TPOFF; TlsModuleIndexRel = R_386_TLS_DTPMOD32; TlsOffsetRel = R_386_TLS_DTPOFF32; @@ -291,7 +292,6 @@ write16le(Loc, Val); break; case R_386_32: - case R_386_GLOB_DAT: case R_386_GOT32: case R_386_GOT32X: case R_386_GOTOFF: Index: ELF/Arch/X86_64.cpp =================================================================== --- ELF/Arch/X86_64.cpp +++ ELF/Arch/X86_64.cpp @@ -55,6 +55,7 @@ PltRel = R_X86_64_JUMP_SLOT; RelativeRel = R_X86_64_RELATIVE; IRelativeRel = R_X86_64_IRELATIVE; + SymbolicRel = R_X86_64_64; TlsDescRel = R_X86_64_TLSDESC; TlsGotRel = R_X86_64_TPOFF64; TlsModuleIndexRel = R_X86_64_DTPMOD64; @@ -387,7 +388,6 @@ break; case R_X86_64_64: case R_X86_64_DTPOFF64: - case R_X86_64_GLOB_DAT: case R_X86_64_PC64: case R_X86_64_SIZE64: case R_X86_64_GOT64: Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -861,7 +861,7 @@ bool IsLinkTimeConstant = !Sym.IsPreemptible && (!Config->Pic || isAbsolute(Sym)); if (IsLinkTimeConstant) { - In.Got->Relocations.push_back({Expr, Target->GotRel, Off, 0, &Sym}); + In.Got->Relocations.push_back({Expr, Target->SymbolicRel, Off, 0, &Sym}); return; } @@ -919,10 +919,9 @@ } bool CanWrite = (Sec.Flags & SHF_WRITE) || !Config->ZText; if (CanWrite) { - // R_GOT refers to a position in the got, even if the symbol is preemptible. - bool IsPreemptibleValue = Sym.IsPreemptible && Expr != R_GOT; - - if (!IsPreemptibleValue) { + if ((!Sym.IsPreemptible && Type == Target->SymbolicRel) || Expr == R_GOT) { + // Use a relative relocation to adjust the value of a symbolic relocation + // to a non-preemptable symbol. addRelativeReloc(&Sec, Offset, &Sym, Addend, Expr, Type); return; } else if (RelType Rel = Target->getDynRel(Type)) { @@ -967,11 +966,14 @@ return; } - // Copy relocations are only possible if we are creating an executable. - if (Config->Shared) { - errorOrWarn("relocation " + toString(Type) + - " cannot be used against symbol " + toString(Sym) + - "; recompile with -fPIC" + getLocation(Sec, Sym, Offset)); + // Copy relocations (for STT_OBJECT) and non-PIC PLT (for STT_FUNC) are only + // possible if we are creating an executable. + if (Config->Shared || + (Config->Pie && Expr == R_ABS && Type != Target->SymbolicRel)) { + errorOrWarn( + "relocation " + toString(Type) + " cannot be used against " + + (Sym.getName().empty() ? "local symbol" : "symbol " + toString(Sym)) + + "; recompile with -fPIC" + getLocation(Sec, Sym, Offset)); return; } Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -1503,7 +1503,9 @@ // Write the addends to the relocated address if required. We skip // it if the written value would be zero. if (Config->WriteAddends && (Expr != R_ADDEND || Addend != 0)) - InputSec->Relocations.push_back({Expr, Type, OffsetInSec, Addend, Sym}); + InputSec->Relocations.push_back( + {Expr, Type == Target->GotRel ? Target->SymbolicRel : Type, OffsetInSec, + Addend, Sym}); addReloc({DynType, InputSec, OffsetInSec, Expr != R_ADDEND, Sym, Addend}); } Index: ELF/Target.h =================================================================== --- ELF/Target.h +++ ELF/Target.h @@ -95,6 +95,7 @@ RelType PltRel; RelType RelativeRel; RelType IRelativeRel; + RelType SymbolicRel; RelType TlsDescRel; RelType TlsGotRel; RelType TlsModuleIndexRel; Index: test/ELF/linkerscript/visibility.s =================================================================== --- test/ELF/linkerscript/visibility.s +++ test/ELF/linkerscript/visibility.s @@ -19,4 +19,4 @@ .data .hidden foo - .long foo + .quad foo Index: test/ELF/merge-string-error.s =================================================================== --- test/ELF/merge-string-error.s +++ test/ELF/merge-string-error.s @@ -6,6 +6,6 @@ .asciz "abc" .data - .long .rodata.str1.1 + 4 + .quad .rodata.str1.1 + 4 // CHECK: merge-string-error.s.tmp.o:(.rodata.str1.1): offset is outside the section Index: test/ELF/pack-dyn-relocs-loop.s =================================================================== --- test/ELF/pack-dyn-relocs-loop.s +++ test/ELF/pack-dyn-relocs-loop.s @@ -46,7 +46,7 @@ // CHECK-NEXT: ] // CHECK-NEXT: Address: 0x10004 // CHECK-NEXT: Offset: 0x10004 -// CHECK-NEXT: Size: 12 +// CHECK-NEXT: Size: 24 .data @@ -54,9 +54,9 @@ .section foo,"aw" foof: -.long foof -.long bar-53 -.long bar +.quad foof +.quad bar-53 +.quad bar .section x,"a" .zero 65036 Index: test/ELF/relocation-before-merge-start.s =================================================================== --- test/ELF/relocation-before-merge-start.s +++ test/ELF/relocation-before-merge-start.s @@ -4,6 +4,6 @@ // CHECK: relocation-before-merge-start.s.tmp.o:(.foo): offset is outside the section .data -.long .foo - 1 +.quad .foo - 1 .section .foo,"aM",@progbits,4 .quad 0 Index: test/ELF/relocation-past-merge-end.s =================================================================== --- test/ELF/relocation-past-merge-end.s +++ test/ELF/relocation-past-merge-end.s @@ -4,6 +4,6 @@ // CHECK: relocation-past-merge-end.s.tmp.o:(.foo): offset is outside the section .data -.long .foo + 10 +.quad .foo + 10 .section .foo,"aM",@progbits,4 .quad 0 Index: test/ELF/x86-64-dyn-rel-error5.s =================================================================== --- /dev/null +++ test/ELF/x86-64-dyn-rel-error5.s @@ -0,0 +1,20 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o +# RUN: not ld.lld -pie %t.o -o /dev/null 2>&1 | FileCheck %s +# RUN: not ld.lld -shared %t.o -o /dev/null 2>&1 | FileCheck %s + +## Check we don't create dynamic relocations in a writable section, +## if the number of bits is smaller than the wordsize. + +local: + +# CHECK: error: relocation R_X86_64_8 cannot be used against local symbol; recompile with -fPIC +# CHECK-NEXT: >>> defined in {{.*}}.o +# CHECK-NEXT: >>> referenced by {{.*}}.o:(.data+0x0) +# CHECK: error: relocation R_X86_64_16 cannot be used against local symbol; recompile with -fPIC +# CHECK: error: relocation R_X86_64_32 cannot be used against local symbol; recompile with -fPIC + +.data +.byte local # R_X86_64_8 +.short local # R_X86_64_16 +.long local # R_X86_64_32