From 84569e6caaf5af80459d8c4f4da511fdcba91a89 Mon Sep 17 00:00:00 2001 From: Eugene Leviant Date: Tue, 29 Nov 2016 08:05:44 +0000 Subject: [PATCH] [ELF] Refactor target error messages Differential revision: https://reviews.llvm.org/D27097 llvm-svn: 288114 --- lld/ELF/OutputSections.cpp | 1 + lld/ELF/OutputSections.h | 3 ++ lld/ELF/Target.cpp | 110 +++++++++++++++++++++----------------- lld/ELF/Writer.cpp | 28 ++++++++++ lld/ELF/Writer.h | 1 + lld/test/ELF/mips-align-err.s | 2 +- lld/test/ELF/x86-64-reloc-error.s | 4 +- lld/test/ELF/x86-64-reloc-range.s | 2 +- 8 files changed, 97 insertions(+), 54 deletions(-) diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index e4536ef..4a723d5 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -249,6 +249,7 @@ void fill(uint8_t *Buf, size_t Size, uint32_t Filler) { } template void OutputSection::writeTo(uint8_t *Buf) { + Loc = Buf; if (uint32_t Filler = Script::X->getFiller(this->Name)) fill(Buf, this->Size, Filler); diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 2dd213d..a4e59df 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -121,6 +121,9 @@ public: return B->getKind() == Regular; } std::vector *> Sections; + + // Location in the output buffer. + uint8_t *Loc = nullptr; }; template diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index a251f6b..ffbe16d 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -55,24 +55,32 @@ std::string toString(uint32_t Type) { 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"); + error(getErrorLocation(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"); + error(getErrorLocation(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"); + error(getErrorLocation(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)); + error(getErrorLocation(Loc) + "improper alignment for relocation " + + toString(Type)); } namespace { @@ -443,7 +451,7 @@ uint64_t X86TargetInfo::getImplicitAddend(const uint8_t *Buf, 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 +745,8 @@ void X86_64TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, memcpy(Inst, "\x48\xc7", 2); *RegSlot = 0xc0 | Reg; } else { - fatal("R_X86_64_GOTTPOFF must be used in MOVQ or ADDQ instructions only"); + fatal(getErrorLocation(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 +788,7 @@ void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, 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 +804,7 @@ void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, 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: @@ -806,7 +815,7 @@ void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, write64le(Loc, Val); break; default: - fatal("unrecognized reloc " + Twine(Type)); + fatal(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); } } @@ -975,7 +984,7 @@ void PPCTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, or32be(Loc, Val & 0x3FFFFFC); break; default: - fatal("unrecognized reloc " + Twine(Type)); + fatal(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); } } @@ -1095,18 +1104,18 @@ void PPC64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, 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: @@ -1138,7 +1147,7 @@ void PPC64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, 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: @@ -1148,12 +1157,12 @@ void PPC64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, 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)); + fatal(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); } } @@ -1311,12 +1320,12 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, 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: @@ -1335,26 +1344,26 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, 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: @@ -1385,11 +1394,11 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, 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: @@ -1397,7 +1406,7 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, updateAArch64Add(Loc, Val); break; default: - fatal("unrecognized reloc " + Twine(Type)); + fatal(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); } } @@ -1414,7 +1423,7 @@ void AArch64TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, // movk x0, #0x10 // nop // nop - checkUInt<32>(Val, Type); + checkUInt<32>(Loc, Val, Type); switch (Type) { case R_AARCH64_TLSDESC_ADD_LO12_NC: @@ -1466,7 +1475,7 @@ void AArch64TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, 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. @@ -1507,7 +1516,7 @@ void AMDGPUTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, write32le(Loc, Val >> 32); break; default: - fatal("unrecognized reloc " + Twine(Type)); + fatal(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); } } @@ -1703,7 +1712,7 @@ void ARMTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, 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: @@ -1712,7 +1721,7 @@ void ARMTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, 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 @@ -1726,16 +1735,16 @@ void ARMTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, 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 @@ -1760,7 +1769,7 @@ void ARMTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, 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 @@ -1778,14 +1787,14 @@ void ARMTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, 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 @@ -1808,7 +1817,7 @@ void ARMTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, (Val & 0x00ff)); // imm8 break; default: - fatal("unrecognized reloc " + Twine(Type)); + fatal(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); } } @@ -2014,8 +2023,8 @@ static void applyMipsPcReloc(uint8_t *Loc, uint32_t Type, uint64_t V) { 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)); } @@ -2148,8 +2157,8 @@ uint64_t MipsTargetInfo::getImplicitAddend(const uint8_t *Buf, } } -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, @@ -2170,7 +2179,8 @@ static std::pair calculateMipsRelChain(uint32_t Type, 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)); + error(getErrorLocation(Loc) + "unsupported relocations combination " + + Twine(Type)); return std::make_pair(Type & 0xff, Val); } @@ -2187,7 +2197,7 @@ void MipsTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, 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: @@ -2209,7 +2219,7 @@ void MipsTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, 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: @@ -2255,7 +2265,7 @@ void MipsTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, applyMipsPcReloc(Loc, Type, Val); break; default: - fatal("unrecognized reloc " + Twine(Type)); + fatal(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); } } diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index c7fc9a8..b74c251 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1558,6 +1558,34 @@ template void Writer::writeBuildId() { In::BuildId->writeBuildId({Start, End}); } +template static std::string getErrorLoc(uint8_t *Loc) { + 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) + return IS->getLocation(Loc - ISLoc) + ": "; + } + return ""; +} + +std::string elf::getErrorLocation(uint8_t *Loc) { + switch (Config->EKind) { + case ELF32LEKind: + return getErrorLoc(Loc); + case ELF32BEKind: + return getErrorLoc(Loc); + case ELF64LEKind: + return getErrorLoc(Loc); + case ELF64BEKind: + return getErrorLoc(Loc); + default: + llvm_unreachable("unknown ELF type"); + } +} + template void elf::writeResult(); template void elf::writeResult(); template void elf::writeResult(); diff --git a/lld/ELF/Writer.h b/lld/ELF/Writer.h index 4e353ac..a88161f 100644 --- a/lld/ELF/Writer.h +++ b/lld/ELF/Writer.h @@ -48,6 +48,7 @@ uint8_t getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag, llvm::StringRef FileName); bool isMipsN32Abi(const InputFile *F); +std::string getErrorLocation(uint8_t *Loc); } } diff --git a/lld/test/ELF/mips-align-err.s b/lld/test/ELF/mips-align-err.s index 28b192a..0c71ffb 100644 --- a/lld/test/ELF/mips-align-err.s +++ b/lld/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: diff --git a/lld/test/ELF/x86-64-reloc-error.s b/lld/test/ELF/x86-64-reloc-error.s index 9b7e17d..ece1bd4 100644 --- a/lld/test/ELF/x86-64-reloc-error.s +++ b/lld/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 diff --git a/lld/test/ELF/x86-64-reloc-range.s b/lld/test/ELF/x86-64-reloc-range.s index 8319eaa..08f604e 100644 --- a/lld/test/ELF/x86-64-reloc-range.s +++ b/lld/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 -- 2.7.4