Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -121,6 +121,9 @@ return B->getKind() == Regular; } std::vector *> Sections; + + // Location in the output buffer. + uint8_t *Loc = nullptr; }; template Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -249,6 +249,7 @@ } template void OutputSection::writeTo(uint8_t *Buf) { + Loc = Buf; if (uint32_t Filler = Script::X->getFiller(this->Name)) fill(Buf, this->Size, Filler); Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -55,24 +55,28 @@ return getELFRelocationTypeName(Config->EMachine, Type); } -template static void checkInt(int64_t V, uint32_t Type) { +template +static void checkInt(uint8_t *Loc, int64_t V, uint32_t Type) { if (!isInt(V)) - error("relocation " + toString(Type) + " out of range"); + errorAt(false, Loc, "relocation " + toString(Type) + " out of range"); } -template static void checkUInt(uint64_t V, uint32_t Type) { +template +static void checkUInt(uint8_t *Loc, uint64_t V, uint32_t Type) { if (!isUInt(V)) - error("relocation " + toString(Type) + " out of range"); + errorAt(false, Loc, "relocation " + toString(Type) + " out of range"); } -template static void checkIntUInt(uint64_t V, uint32_t Type) { +template +static void checkIntUInt(uint8_t *Loc, uint64_t V, uint32_t Type) { if (!isInt(V) && !isUInt(V)) - error("relocation " + toString(Type) + " out of range"); + errorAt(false, Loc, "relocation " + toString(Type) + " out of range"); } -template static void checkAlignment(uint64_t V, uint32_t Type) { +template +static void checkAlignment(uint8_t *Loc, uint64_t V, uint32_t Type) { if ((V & (N - 1)) != 0) - error("improper alignment for relocation " + toString(Type)); + errorAt(false, Loc, "improper alignment for relocation " + toString(Type)); } namespace { @@ -443,7 +447,7 @@ void X86TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { - checkInt<32>(Val, Type); + checkInt<32>(Loc, Val, Type); write32le(Loc, Val); } @@ -737,7 +741,8 @@ memcpy(Inst, "\x48\xc7", 2); *RegSlot = 0xc0 | Reg; } else { - fatal("R_X86_64_GOTTPOFF must be used in MOVQ or ADDQ instructions only"); + errorAt(true, Loc - 3, + "R_X86_64_GOTTPOFF must be used in MOVQ or ADDQ instructions only"); } // The original code used a PC relative relocation. @@ -779,7 +784,7 @@ uint64_t Val) const { switch (Type) { case R_X86_64_32: - checkUInt<32>(Val, Type); + checkUInt<32>(Loc, Val, Type); write32le(Loc, Val); break; case R_X86_64_32S: @@ -795,7 +800,7 @@ case R_X86_64_TLSLD: case R_X86_64_DTPOFF32: case R_X86_64_SIZE32: - checkInt<32>(Val, Type); + checkInt<32>(Loc, Val, Type); write32le(Loc, Val); break; case R_X86_64_64: @@ -805,7 +810,7 @@ write64le(Loc, Val); break; default: - fatal("unrecognized reloc " + Twine(Type)); + errorAt(true, Loc, "unrecognized reloc " + Twine(Type)); } } @@ -974,7 +979,7 @@ or32be(Loc, Val & 0x3FFFFFC); break; default: - fatal("unrecognized reloc " + Twine(Type)); + errorAt(true, Loc, "unrecognized reloc " + Twine(Type)); } } @@ -1094,18 +1099,18 @@ switch (Type) { case R_PPC64_ADDR14: { - checkAlignment<4>(Val, Type); + checkAlignment<4>(Loc, Val, Type); // Preserve the AA/LK bits in the branch instruction uint8_t AALK = Loc[3]; write16be(Loc + 2, (AALK & 3) | (Val & 0xfffc)); break; } case R_PPC64_ADDR16: - checkInt<16>(Val, Type); + checkInt<16>(Loc, Val, Type); write16be(Loc, Val); break; case R_PPC64_ADDR16_DS: - checkInt<16>(Val, Type); + checkInt<16>(Loc, Val, Type); write16be(Loc, (read16be(Loc) & 3) | (Val & ~3)); break; case R_PPC64_ADDR16_HA: @@ -1137,7 +1142,7 @@ break; case R_PPC64_ADDR32: case R_PPC64_REL32: - checkInt<32>(Val, Type); + checkInt<32>(Loc, Val, Type); write32be(Loc, Val); break; case R_PPC64_ADDR64: @@ -1147,12 +1152,12 @@ break; case R_PPC64_REL24: { uint32_t Mask = 0x03FFFFFC; - checkInt<24>(Val, Type); + checkInt<24>(Loc, Val, Type); write32be(Loc, (read32be(Loc) & ~Mask) | (Val & Mask)); break; } default: - fatal("unrecognized reloc " + Twine(Type)); + errorAt(true, Loc, "unrecognized reloc " + Twine(Type)); } } @@ -1310,12 +1315,12 @@ switch (Type) { case R_AARCH64_ABS16: case R_AARCH64_PREL16: - checkIntUInt<16>(Val, Type); + checkIntUInt<16>(Loc, Val, Type); write16le(Loc, Val); break; case R_AARCH64_ABS32: case R_AARCH64_PREL32: - checkIntUInt<32>(Val, Type); + checkIntUInt<32>(Loc, Val, Type); write32le(Loc, Val); break; case R_AARCH64_ABS64: @@ -1333,26 +1338,26 @@ case R_AARCH64_ADR_PREL_PG_HI21: case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: case R_AARCH64_TLSDESC_ADR_PAGE21: - checkInt<33>(Val, Type); + checkInt<33>(Loc, Val, Type); updateAArch64Addr(Loc, Val >> 12); break; case R_AARCH64_ADR_PREL_LO21: - checkInt<21>(Val, Type); + checkInt<21>(Loc, Val, Type); updateAArch64Addr(Loc, Val); break; case R_AARCH64_CALL26: case R_AARCH64_JUMP26: - checkInt<28>(Val, Type); + checkInt<28>(Loc, Val, Type); or32le(Loc, (Val & 0x0FFFFFFC) >> 2); break; case R_AARCH64_CONDBR19: - checkInt<21>(Val, Type); + checkInt<21>(Loc, Val, Type); or32le(Loc, (Val & 0x1FFFFC) << 3); break; case R_AARCH64_LD64_GOT_LO12_NC: case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: case R_AARCH64_TLSDESC_LD64_LO12_NC: - checkAlignment<8>(Val, Type); + checkAlignment<8>(Loc, Val, Type); or32le(Loc, (Val & 0xFF8) << 7); break; case R_AARCH64_LDST128_ABS_LO12_NC: @@ -1383,11 +1388,11 @@ or32le(Loc, (Val & 0xFFFF000000000000) >> 43); break; case R_AARCH64_TSTBR14: - checkInt<16>(Val, Type); + checkInt<16>(Loc, Val, Type); or32le(Loc, (Val & 0xFFFC) << 3); break; case R_AARCH64_TLSLE_ADD_TPREL_HI12: - checkInt<24>(Val, Type); + checkInt<24>(Loc, Val, Type); updateAArch64Add(Loc, Val >> 12); break; case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: @@ -1395,7 +1400,7 @@ updateAArch64Add(Loc, Val); break; default: - fatal("unrecognized reloc " + Twine(Type)); + errorAt(true, Loc, "unrecognized reloc " + Twine(Type)); } } @@ -1412,7 +1417,7 @@ // movk x0, #0x10 // nop // nop - checkUInt<32>(Val, Type); + checkUInt<32>(Loc, Val, Type); switch (Type) { case R_AARCH64_TLSDESC_ADD_LO12_NC: @@ -1464,7 +1469,7 @@ void AArch64TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { - checkUInt<32>(Val, Type); + checkUInt<32>(Loc, Val, Type); if (Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) { // Generate MOVZ. @@ -1505,7 +1510,7 @@ write32le(Loc, Val >> 32); break; default: - fatal("unrecognized reloc " + Twine(Type)); + errorAt(true, Loc, "unrecognized reloc " + Twine(Type)); } } @@ -1699,7 +1704,7 @@ write32le(Loc, Val); break; case R_ARM_PREL31: - checkInt<31>(Val, Type); + checkInt<31>(Loc, Val, Type); write32le(Loc, (read32le(Loc) & 0x80000000) | (Val & ~0x80000000)); break; case R_ARM_CALL: @@ -1708,7 +1713,7 @@ if (Val & 1) { // If bit 0 of Val is 1 the target is Thumb, we must select a BLX. // The BLX encoding is 0xfa:H:imm24 where Val = imm24:H:'1' - checkInt<26>(Val, Type); + checkInt<26>(Loc, Val, Type); write32le(Loc, 0xfa000000 | // opcode ((Val & 2) << 23) | // H ((Val >> 2) & 0x00ffffff)); // imm24 @@ -1722,16 +1727,16 @@ case R_ARM_JUMP24: case R_ARM_PC24: case R_ARM_PLT32: - checkInt<26>(Val, Type); + checkInt<26>(Loc, Val, Type); write32le(Loc, (read32le(Loc) & ~0x00ffffff) | ((Val >> 2) & 0x00ffffff)); break; case R_ARM_THM_JUMP11: - checkInt<12>(Val, Type); + checkInt<12>(Loc, Val, Type); write16le(Loc, (read32le(Loc) & 0xf800) | ((Val >> 1) & 0x07ff)); break; case R_ARM_THM_JUMP19: // Encoding T3: Val = S:J2:J1:imm6:imm11:0 - checkInt<21>(Val, Type); + checkInt<21>(Loc, Val, Type); write16le(Loc, (read16le(Loc) & 0xfbc0) | // opcode cond ((Val >> 10) & 0x0400) | // S @@ -1756,7 +1761,7 @@ case R_ARM_THM_JUMP24: // Encoding B T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0 // FIXME: Use of I1 and I2 require v6T2ops - checkInt<25>(Val, Type); + checkInt<25>(Loc, Val, Type); write16le(Loc, 0xf000 | // opcode ((Val >> 14) & 0x0400) | // S @@ -1774,14 +1779,14 @@ break; case R_ARM_MOVT_ABS: case R_ARM_MOVT_PREL: - checkInt<32>(Val, Type); + checkInt<32>(Loc, Val, Type); write32le(Loc, (read32le(Loc) & ~0x000f0fff) | (((Val >> 16) & 0xf000) << 4) | ((Val >> 16) & 0xfff)); break; case R_ARM_THM_MOVT_ABS: case R_ARM_THM_MOVT_PREL: // Encoding T1: A = imm4:i:imm3:imm8 - checkInt<32>(Val, Type); + checkInt<32>(Loc, Val, Type); write16le(Loc, 0xf2c0 | // opcode ((Val >> 17) & 0x0400) | // i @@ -1804,7 +1809,7 @@ (Val & 0x00ff)); // imm8 break; default: - fatal("unrecognized reloc " + Twine(Type)); + errorAt(true, Loc, "unrecognized reloc " + Twine(Type)); } } @@ -2010,8 +2015,8 @@ uint32_t Mask = 0xffffffff >> (32 - BSIZE); uint32_t Instr = read32(Loc); if (SHIFT > 0) - checkAlignment<(1 << SHIFT)>(V, Type); - checkInt(V, Type); + checkAlignment<(1 << SHIFT)>(Loc, V, Type); + checkInt(Loc, V, Type); write32(Loc, (Instr & ~Mask) | ((V >> SHIFT) & Mask)); } @@ -2144,8 +2149,8 @@ } } -static std::pair calculateMipsRelChain(uint32_t Type, - uint64_t Val) { +static std::pair +calculateMipsRelChain(uint8_t *Loc, uint32_t Type, uint64_t Val) { // MIPS N64 ABI packs multiple relocations into the single relocation // record. In general, all up to three relocations can have arbitrary // types. In fact, Clang and GCC uses only a few combinations. For now, @@ -2166,7 +2171,7 @@ return std::make_pair(Type2, Val); if (Type2 == R_MIPS_SUB && (Type3 == R_MIPS_HI16 || Type3 == R_MIPS_LO16)) return std::make_pair(Type3, -Val); - error("unsupported relocations combination " + Twine(Type)); + errorAt(false, Loc, "unsupported relocations combination " + Twine(Type)); return std::make_pair(Type & 0xff, Val); } @@ -2183,7 +2188,7 @@ Type == R_MIPS_TLS_TPREL32 || Type == R_MIPS_TLS_TPREL64) Val -= 0x7000; if (ELFT::Is64Bits || Config->MipsN32Abi) - std::tie(Type, Val) = calculateMipsRelChain(Type, Val); + std::tie(Type, Val) = calculateMipsRelChain(Loc, Type, Val); switch (Type) { case R_MIPS_32: case R_MIPS_GPREL32: @@ -2205,7 +2210,7 @@ case R_MIPS_GPREL16: case R_MIPS_TLS_GD: case R_MIPS_TLS_LDM: - checkInt<16>(Val, Type); + checkInt<16>(Loc, Val, Type); // fallthrough case R_MIPS_CALL16: case R_MIPS_CALL_LO16: @@ -2251,7 +2256,7 @@ applyMipsPcReloc(Loc, Type, Val); break; default: - fatal("unrecognized reloc " + Twine(Type)); + errorAt(true, Loc, "unrecognized reloc " + Twine(Type)); } } Index: ELF/Writer.h =================================================================== --- ELF/Writer.h +++ ELF/Writer.h @@ -11,6 +11,7 @@ #define LLD_ELF_WRITER_H #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" #include #include @@ -48,6 +49,7 @@ llvm::StringRef FileName); bool isMipsN32Abi(const InputFile *F); +void errorAt(bool Fatal, uint8_t *Loc, const llvm::Twine &Msg); } } Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1547,6 +1547,48 @@ In::BuildId->writeBuildId({Start, End}); } +template static std::string getErrorLocation(uint8_t *Loc) { + std::string ErrLoc; + + for (InputSectionData *D : Symtab::X->Sections) { + auto *IS = dyn_cast_or_null>(D); + if (!IS || !IS->OutSec) + continue; + + uint8_t *ISLoc = cast>(IS->OutSec)->Loc + IS->OutSecOff; + if (ISLoc <= Loc && ISLoc + IS->getSize() > Loc) { + ErrLoc = getLocation(*IS, Loc - ISLoc); + break; + } + } + return ErrLoc; +} + +void elf::errorAt(bool Fatal, uint8_t *Loc, const Twine &Msg) { + std::string ErrLoc; + switch (Config->EKind) { + case ELF32LEKind: + ErrLoc = getErrorLocation(Loc); + break; + case ELF32BEKind: + ErrLoc = getErrorLocation(Loc); + break; + case ELF64LEKind: + ErrLoc = getErrorLocation(Loc); + break; + case ELF64BEKind: + ErrLoc = getErrorLocation(Loc); + break; + default: + llvm_unreachable("unknown ELF type"); + } + + if (Fatal) + fatal(ErrLoc.empty() ? Msg : ErrLoc + ": " + Msg.str()); + else + error(ErrLoc.empty() ? Msg : ErrLoc + ": " + Msg.str()); +} + template void elf::writeResult(); template void elf::writeResult(); template void elf::writeResult(); Index: test/ELF/mips-align-err.s =================================================================== --- test/ELF/mips-align-err.s +++ test/ELF/mips-align-err.s @@ -4,7 +4,7 @@ # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ # RUN: -mcpu=mips32r6 %S/Inputs/mips-align-err.s -o %t2.o # RUN: not ld.lld %t.o %t2.o -o %t.exe 2>&1 | FileCheck %s -# CHECK: improper alignment for relocation R_MIPS_PC16 +# CHECK: {{.*}}:(.text+0x1): improper alignment for relocation R_MIPS_PC16 .globl __start __start: Index: test/ELF/x86-64-reloc-error.s =================================================================== --- test/ELF/x86-64-reloc-error.s +++ test/ELF/x86-64-reloc-error.s @@ -6,5 +6,5 @@ movl $big, %edx movq $foo - 0x1000000000000, %rdx -# CHECK: R_X86_64_32 out of range -# CHECK: R_X86_64_32S out of range +# CHECK: {{.*}}:(.text+0x1): relocation R_X86_64_32 out of range +# CHECK: {{.*}}:(.text+0x8): relocation R_X86_64_32S out of range Index: test/ELF/x86-64-reloc-range.s =================================================================== --- test/ELF/x86-64-reloc-range.s +++ test/ELF/x86-64-reloc-range.s @@ -1,7 +1,7 @@ // RUN: llvm-mc %s -o %t.o -triple x86_64-pc-linux -filetype=obj // RUN: not ld.lld %t.o -o %t.so -shared 2>&1 | FileCheck %s -// CHECK: relocation R_X86_64_PC32 out of range +// CHECK: {{.*}}:(.text+0x3): relocation R_X86_64_PC32 out of range // CHECK-NOT: relocation lea foo(%rip), %rax