Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -713,7 +713,12 @@ } else { // We don't know anything about the finaly symbol. Just ask the dynamic // linker to handle the relocation for us. - AddDyn({Target->getDynRel(Type), &C, Offset, false, &Body, Addend}); + const auto &P = Target->getDynRel(Type); + if (!P.second) + error(getLocation(C, Offset) + ": relocation " + getRelName(Type) + + " cannot be used against shared object; recompile with -fPIC."); + + AddDyn({P.first, &C, Offset, false, &Body, Addend}); // MIPS ABI turns using of GOT and dynamic relocations inside out. // While regular ABI uses dynamic relocations to fill up GOT entries // MIPS ABI requires dynamic linker to fills up GOT entries using Index: ELF/Target.h =================================================================== --- ELF/Target.h +++ ELF/Target.h @@ -26,7 +26,9 @@ virtual bool isTlsInitialExecRel(uint32_t Type) const; virtual bool isTlsLocalDynamicRel(uint32_t Type) const; virtual bool isTlsGlobalDynamicRel(uint32_t Type) const; - virtual uint32_t getDynRel(uint32_t Type) const { return Type; } + virtual std::pair<uint32_t, bool> getDynRel(uint32_t Type) const { + return {Type, true}; + } virtual void writeGotPltHeader(uint8_t *Buf) const {} virtual void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const {}; virtual uint64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const; Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -75,11 +75,6 @@ error("improper alignment for relocation " + getRelName(Type)); } -static void errorDynRel(uint32_t Type) { - error("relocation " + getRelName(Type) + - " cannot be used against shared object; recompile with -fPIC."); -} - namespace { class X86TargetInfo final : public TargetInfo { public: @@ -87,7 +82,7 @@ RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override; uint64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override; void writeGotPltHeader(uint8_t *Buf) const override; - uint32_t getDynRel(uint32_t Type) const override; + std::pair<uint32_t, bool> getDynRel(uint32_t Type) const override; bool isTlsLocalDynamicRel(uint32_t Type) const override; bool isTlsGlobalDynamicRel(uint32_t Type) const override; bool isTlsInitialExecRel(uint32_t Type) const override; @@ -109,7 +104,7 @@ public: X86_64TargetInfo(); RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override; - uint32_t getDynRel(uint32_t Type) const override; + std::pair<uint32_t, bool> getDynRel(uint32_t Type) const override; bool isTlsLocalDynamicRel(uint32_t Type) const override; bool isTlsGlobalDynamicRel(uint32_t Type) const override; bool isTlsInitialExecRel(uint32_t Type) const override; @@ -153,7 +148,7 @@ public: AArch64TargetInfo(); RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override; - uint32_t getDynRel(uint32_t Type) const override; + std::pair<uint32_t, bool> getDynRel(uint32_t Type) const override; bool isTlsInitialExecRel(uint32_t Type) const override; void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; void writePltHeader(uint8_t *Buf) const override; @@ -179,7 +174,7 @@ public: ARMTargetInfo(); RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override; - uint32_t getDynRel(uint32_t Type) const override; + std::pair<uint32_t, bool> getDynRel(uint32_t Type) const override; uint64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override; bool isTlsLocalDynamicRel(uint32_t Type) const override; bool isTlsGlobalDynamicRel(uint32_t Type) const override; @@ -198,7 +193,7 @@ MipsTargetInfo(); RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override; uint64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override; - uint32_t getDynRel(uint32_t Type) const override; + std::pair<uint32_t, bool> getDynRel(uint32_t Type) const override; bool isTlsLocalDynamicRel(uint32_t Type) const override; bool isTlsGlobalDynamicRel(uint32_t Type) const override; void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; @@ -365,12 +360,12 @@ write32le(Buf, S.getPltVA<ELF32LE>() + 6); } -uint32_t X86TargetInfo::getDynRel(uint32_t Type) const { +std::pair<uint32_t, bool> X86TargetInfo::getDynRel(uint32_t Type) const { if (Type == R_386_TLS_LE) - return R_386_TLS_TPOFF; + return {R_386_TLS_TPOFF, true}; if (Type == R_386_TLS_LE_32) - return R_386_TLS_TPOFF32; - return Type; + return {R_386_TLS_TPOFF32, true}; + return {Type, true}; } bool X86TargetInfo::isTlsGlobalDynamicRel(uint32_t Type) const { @@ -637,10 +632,11 @@ } template <class ELFT> -uint32_t X86_64TargetInfo<ELFT>::getDynRel(uint32_t Type) const { +std::pair<uint32_t, bool> +X86_64TargetInfo<ELFT>::getDynRel(uint32_t Type) const { if (Type == R_X86_64_PC32 || Type == R_X86_64_32) - errorDynRel(Type); - return Type; + return {Type, false}; + return {Type, true}; } template <class ELFT> @@ -698,7 +694,8 @@ 0x48, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00 // addq x@tpoff,%rax }; memcpy(Loc - 4, Inst, sizeof(Inst)); - // Both code sequences are PC relatives, but since we are moving the constant + // Both code sequences are PC relatives, but since we are moving the + // constant // forward by 8 bytes we have to subtract the value by 8. relocateOne(Loc + 8, R_X86_64_PC32, Val - 8); } @@ -739,7 +736,8 @@ memcpy(Inst, "\x48\xc7", 2); *RegSlot = 0xc0 | Reg; } else { - fatal("R_X86_64_GOTTPOFF must be used in MOVQ or ADDQ instructions only"); + fatal("R_X86_64_GOTTPOFF must be used in MOVQ or ADDQ instructions " + "only"); } // The original code used a PC relative relocation. @@ -820,8 +818,10 @@ const uint8_t Op = Data[-2]; const uint8_t ModRm = Data[-1]; // FIXME: When PIC is disabled and foo is defined locally in the - // lower 32 bit address space, memory operand in mov can be converted into - // immediate operand. Otherwise, mov must be changed to lea. We support only + // lower 32 bit address space, memory operand in mov can be converted + // into + // immediate operand. Otherwise, mov must be changed to lea. We support + // only // latter relaxation at this moment. if (Op == 0x8b) return R_RELAX_GOT_PC; @@ -838,7 +838,8 @@ } // A subset of relaxations can only be applied for no-PIC. This method -// handles such relaxations. Instructions encoding information was taken from: +// handles such relaxations. Instructions encoding information was taken +// from: // "Intel 64 and IA-32 Architectures Software Developer's Manual V2" // (http://www.intel.com/content/dam/www/public/us/en/documents/manuals/ // 64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf) @@ -855,8 +856,10 @@ // YYY is MODRM.reg(register 2), ZZZ is MODRM.rm(register 1). // XX has different meanings: // 00: The operand's memory address is in reg1. - // 01: The operand's memory address is reg1 + a byte-sized displacement. - // 10: The operand's memory address is reg1 + a word-sized displacement. + // 01: The operand's memory address is reg1 + a byte-sized + // displacement. + // 10: The operand's memory address is reg1 + a word-sized + // displacement. // 11: The operand is reg1 itself. // If an instruction requires only one operand, the unused reg2 field // holds extra opcode bits rather than a register code @@ -874,7 +877,8 @@ // REX byte is encoded as 0100WRXB, where // 0100 is 4bit fixed pattern. // REX.W When 1, a 64-bit operand size is used. Otherwise, when 0, the - // default operand size is used (which is 32-bit for most but not all + // default operand size is used (which is 32-bit for most but not + // all // instructions). // REX.R This 1-bit value is an extension to the MODRM.reg field. // REX.X This 1-bit value is an extension to the SIB.index field. @@ -886,7 +890,8 @@ return; } - // If we are here then we need to relax the adc, add, and, cmp, or, sbb, sub + // If we are here then we need to relax the adc, add, and, cmp, or, sbb, + // sub // or xor operations. // Convert "binop foo@GOTPCREL(%rip), %reg" to "binop $foo, %reg". @@ -928,8 +933,10 @@ // Convert call/jmp instructions. if (ModRm == 0x15) { - // ABI says we can convert "call *foo@GOTPCREL(%rip)" to "nop; call foo". - // Instead we convert to "addr32 call foo" where addr32 is an instruction + // ABI says we can convert "call *foo@GOTPCREL(%rip)" to "nop; call + // foo". + // Instead we convert to "addr32 call foo" where addr32 is an + // instruction // prefix. That makes result expression to be a single instruction. Loc[-2] = 0x67; // addr32 prefix Loc[-1] = 0xe8; // call @@ -1004,11 +1011,14 @@ // The PPC64 ELF ABI v1 spec, says: // - // It is normally desirable to put segments with different characteristics + // It is normally desirable to put segments with different + // characteristics // in separate 256 Mbyte portions of the address space, to give the - // operating system full paging flexibility in the 64-bit address space. + // operating system full paging flexibility in the 64-bit address + // space. // - // And because the lowest non-zero 256M boundary is 0x10000000, PPC64 linkers + // And because the lowest non-zero 256M boundary is 0x10000000, PPC64 + // linkers // use 0x10000000 as the starting address. DefaultImageBase = 0x10000000; } @@ -1016,16 +1026,20 @@ static uint64_t PPC64TocOffset = 0x8000; uint64_t getPPC64TocBase() { - // The TOC consists of sections .got, .toc, .tocbss, .plt in that order. The - // TOC starts where the first of these sections starts. We always create a - // .got when we see a relocation that uses it, so for us the start is always + // The TOC consists of sections .got, .toc, .tocbss, .plt in that order. + // The + // TOC starts where the first of these sections starts. We always create + // a + // .got when we see a relocation that uses it, so for us the start is + // always // the .got. uint64_t TocVA = In<ELF64BE>::Got->getVA(); // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000 // thus permitting a full 64 Kbytes segment. Note that the glibc startup // code (crt1.o) assumes that you can get from the TOC base to the - // start of the .toc section with only a single (signed) 16-bit relocation. + // start of the .toc section with only a single (signed) 16-bit + // relocation. return TocVA + PPC64TocOffset; } @@ -1052,11 +1066,15 @@ unsigned RelOff) const { uint64_t Off = GotEntryAddr - getPPC64TocBase(); - // FIXME: What we should do, in theory, is get the offset of the function - // descriptor in the .opd section, and use that as the offset from %r2 (the - // TOC-base pointer). Instead, we have the GOT-entry offset, and that will + // FIXME: What we should do, in theory, is get the offset of the + // function + // descriptor in the .opd section, and use that as the offset from %r2 + // (the + // TOC-base pointer). Instead, we have the GOT-entry offset, and that + // will // be a pointer to the function descriptor in the .opd section. Using - // this scheme is simpler, but requires an extra indirection per PLT dispatch. + // this scheme is simpler, but requires an extra indirection per PLT + // dispatch. write32be(Buf, 0xf8410028); // std %r2, 40(%r1) write32be(Buf + 4, 0x3d620000 | applyPPCHa(Off)); // addis %r11, %r2, X@ha @@ -1172,7 +1190,8 @@ PltHeaderSize = 32; MaxPageSize = 65536; - // It doesn't seem to be documented anywhere, but tls on aarch64 uses variant + // It doesn't seem to be documented anywhere, but tls on aarch64 uses + // variant // 1 of the tls structures and the tcb size is 16. TcbSize = 16; } @@ -1246,12 +1265,10 @@ Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC; } -uint32_t AArch64TargetInfo::getDynRel(uint32_t Type) const { +std::pair<uint32_t, bool> AArch64TargetInfo::getDynRel(uint32_t Type) const { if (Type == R_AARCH64_ABS32 || Type == R_AARCH64_ABS64) - return Type; - // Keep it going with a dummy value so that we can find more reloc errors. - errorDynRel(Type); - return R_AARCH64_ABS32; + return {Type, true}; + return {R_AARCH64_ABS32, false}; } void AArch64TargetInfo::writeGotPlt(uint8_t *Buf, const SymbolBody &) const { @@ -1266,7 +1283,8 @@ const uint8_t PltData[] = { 0xf0, 0x7b, 0xbf, 0xa9, // stp x16, x30, [sp,#-16]! 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[2])) - 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[2]))] + 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, + // Offset(&(.plt.got[2]))] 0x10, 0x02, 0x00, 0x91, // add x16, x16, Offset(&(.plt.got[2])) 0x20, 0x02, 0x1f, 0xd6, // br x17 0x1f, 0x20, 0x03, 0xd5, // nop @@ -1605,15 +1623,14 @@ return R_TLS; } } - -uint32_t ARMTargetInfo::getDynRel(uint32_t Type) const { +std::pair<uint32_t, bool> ARMTargetInfo::getDynRel(uint32_t Type) const { if (Type == R_ARM_TARGET1 && !Config->Target1Rel) - return R_ARM_ABS32; + return {R_ARM_ABS32, true}; if (Type == R_ARM_ABS32) - return Type; - // Keep it going with a dummy value so that we can find more reloc errors. - errorDynRel(Type); - return R_ARM_ABS32; + return {Type, true}; + // Keep it going with a dummy value so that we can find more reloc + // errors. + return {R_ARM_ABS32, false}; } void ARMTargetInfo::writeGotPlt(uint8_t *Buf, const SymbolBody &) const { @@ -1638,7 +1655,8 @@ uint64_t PltEntryAddr, int32_t Index, unsigned RelOff) const { // FIXME: Using simple code sequence with simple relocations. - // There is a more optimal sequence but it requires support for the group + // There is a more optimal sequence but it requires support for the + // group // relocations. See ELF for the ARM Architecture Appendix A.3 const uint8_t PltData[] = { 0x04, 0xc0, 0x9f, 0xe5, // ldr ip, L2 @@ -1671,7 +1689,8 @@ break; case R_ARM_THM_JUMP19: case R_ARM_THM_JUMP24: - // Source is Thumb, all PLT entries are ARM so interworking is required. + // Source is Thumb, all PLT entries are ARM so interworking is + // required. // Otherwise we need to interwork if Symbol has bit 0 clear (ARM). if (Expr == R_PLT_PC) return R_THUNK_PLT_PC; @@ -1717,7 +1736,8 @@ break; } if ((read32le(Loc) & 0xfe000000) == 0xfa000000) - // BLX (always unconditional) instruction to an ARM Target, select an + // BLX (always unconditional) instruction to an ARM Target, select + // an // unconditional BL. write32le(Loc, 0xeb000000 | (read32le(Loc) & 0x00ffffff)); // fall through as BL encoding is shared with B @@ -1745,7 +1765,8 @@ ((Val >> 1) & 0x07ff)); // imm11 break; case R_ARM_THM_CALL: - // R_ARM_THM_CALL is used for BL and BLX instructions, depending on the + // R_ARM_THM_CALL is used for BL and BLX instructions, depending on + // the // value of bit 0 of Val, we must select a BL or BLX instruction if ((Val & 1) == 0) { // Ensure BLX destination is 4-byte aligned. As BLX instruction may @@ -1977,12 +1998,12 @@ } template <class ELFT> -uint32_t MipsTargetInfo<ELFT>::getDynRel(uint32_t Type) const { +std::pair<uint32_t, bool> MipsTargetInfo<ELFT>::getDynRel(uint32_t Type) const { if (Type == R_MIPS_32 || Type == R_MIPS_64) - return RelativeRel; - // Keep it going with a dummy value so that we can find more reloc errors. - errorDynRel(Type); - return R_MIPS_32; + return {RelativeRel, true}; + // Keep it going with a dummy value so that we can find more reloc + // errors. + return {R_MIPS_32, false}; } template <class ELFT> @@ -2089,11 +2110,13 @@ RelExpr MipsTargetInfo<ELFT>::getThunkExpr(RelExpr Expr, uint32_t Type, const InputFile &File, const SymbolBody &S) const { - // Any MIPS PIC code function is invoked with its address in register $t9. + // Any MIPS PIC code function is invoked with its address in register + // $t9. // So if we have a branch instruction from non-PIC code to the PIC one // we cannot make the jump directly and need to create a small stubs // to save the target function address. - // See page 3-38 ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf + // See page 3-38 + // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf if (Type != R_MIPS_26) return Expr; auto *F = dyn_cast<ELFFileBase<ELFT>>(&File); @@ -2158,7 +2181,8 @@ // The first relocation is a 'real' relocation which is calculated // using the corresponding symbol's value. The second and the third // relocations used to modify result of the first one: extend it to - // 64-bit, extract high or low part etc. For details, see part 2.9 Relocation + // 64-bit, extract high or low part etc. For details, see part 2.9 + // Relocation // at the https://dmz-portal.mips.com/mw/images/8/82/007-4658-001.pdf uint32_t Type2 = (Type >> 8) & 0xff; uint32_t Type3 = (Type >> 16) & 0xff; Index: test/ELF/aarch64-fpic-abs16.s =================================================================== --- test/ELF/aarch64-fpic-abs16.s +++ test/ELF/aarch64-fpic-abs16.s @@ -1,7 +1,7 @@ // REQUIRES: aarch64 // RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o // RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s -// CHECK: relocation R_AARCH64_ABS16 cannot be used against shared object; recompile with -fPIC. +// CHECK: {{.*}}:(.data+0x0): relocation R_AARCH64_ABS16 cannot be used against shared object; recompile with -fPIC. .data .hword foo Index: test/ELF/aarch64-fpic-prel16.s =================================================================== --- test/ELF/aarch64-fpic-prel16.s +++ test/ELF/aarch64-fpic-prel16.s @@ -1,7 +1,7 @@ // REQUIRES: aarch64 // RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o // RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s -// CHECK: relocation R_AARCH64_PREL16 cannot be used against shared object; recompile with -fPIC. +// CHECK: {{.*}}:(.data+0x0): relocation R_AARCH64_PREL16 cannot be used against shared object; recompile with -fPIC. .data .hword foo - . Index: test/ELF/aarch64-fpic-prel32.s =================================================================== --- test/ELF/aarch64-fpic-prel32.s +++ test/ELF/aarch64-fpic-prel32.s @@ -1,7 +1,7 @@ // REQUIRES: aarch64 // RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o // RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s -// CHECK: relocation R_AARCH64_PREL32 cannot be used against shared object; recompile with -fPIC. +// CHECK: {{.*}}:(.data+0x0): relocation R_AARCH64_PREL32 cannot be used against shared object; recompile with -fPIC. .data .word foo - . Index: test/ELF/aarch64-fpic-prel64.s =================================================================== --- test/ELF/aarch64-fpic-prel64.s +++ test/ELF/aarch64-fpic-prel64.s @@ -1,7 +1,7 @@ // REQUIRES: aarch64 // RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o // RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s -// CHECK: relocation R_AARCH64_PREL64 cannot be used against shared object; recompile with -fPIC. +// CHECK: {{.*}}:(.data+0x0): relocation R_AARCH64_PREL64 cannot be used against shared object; recompile with -fPIC. .data .xword foo - . Index: test/ELF/x86-64-dyn-rel-error.s =================================================================== --- test/ELF/x86-64-dyn-rel-error.s +++ test/ELF/x86-64-dyn-rel-error.s @@ -9,4 +9,4 @@ .data .long bar -// CHECK: R_X86_64_32 cannot be used against shared object; recompile with -fPIC. +// CHECK: {{.*}}:(.data+0x0): relocation R_X86_64_32 cannot be used against shared object; recompile with -fPIC. Index: test/ELF/x86-64-dyn-rel-error2.s =================================================================== --- test/ELF/x86-64-dyn-rel-error2.s +++ test/ELF/x86-64-dyn-rel-error2.s @@ -9,4 +9,4 @@ .data .long bar - . -// CHECK: R_X86_64_PC32 cannot be used against shared object; recompile with -fPIC. +// CHECK: {{.*}}:(.data+0x0): relocation R_X86_64_PC32 cannot be used against shared object; recompile with -fPIC. Index: test/ELF/x86-64-reloc-32-fpic.s =================================================================== --- test/ELF/x86-64-reloc-32-fpic.s +++ test/ELF/x86-64-reloc-32-fpic.s @@ -1,7 +1,7 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o # RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s -# CHECK: relocation R_X86_64_32 cannot be used against shared object; recompile with -fPIC. +# CHECK: {{.*}}:(.data+0x0): relocation R_X86_64_32 cannot be used against shared object; recompile with -fPIC. .data .long _shared Index: test/ELF/x86-64-reloc-pc32-fpic.s =================================================================== --- test/ELF/x86-64-reloc-pc32-fpic.s +++ test/ELF/x86-64-reloc-pc32-fpic.s @@ -1,7 +1,7 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o # RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s -# CHECK: relocation R_X86_64_PC32 cannot be used against shared object; recompile with -fPIC. +# CHECK: {{.*}}:(.data+0x1): relocation R_X86_64_PC32 cannot be used against shared object; recompile with -fPIC. .data call _shared