diff --git a/lld/ELF/DWARF.cpp b/lld/ELF/DWARF.cpp --- a/lld/ELF/DWARF.cpp +++ b/lld/ELF/DWARF.cpp @@ -57,18 +57,18 @@ namespace { template struct LLDRelocationResolver { - // In the ELF ABIs, S sepresents the value of the symbol in the relocation + // In the ELF ABIs, s sepresents the value of the symbol in the relocation // entry. For Rela, the addend is stored as part of the relocation entry. - static uint64_t resolve(object::RelocationRef ref, uint64_t s, - uint64_t /* A */) { + static Expected resolve(object::RelocationRef ref, uint64_t s, + uint64_t /*a*/) { return s + ref.getRawDataRefImpl().p; } }; template struct LLDRelocationResolver> { - // For Rel, the addend A is supplied by the caller. - static uint64_t resolve(object::RelocationRef /*Ref*/, uint64_t s, - uint64_t a) { + // For Rel, the addend a is supplied by the caller. + static Expected resolve(object::RelocationRef /*ref*/, uint64_t s, + uint64_t a) { return s + a; } }; diff --git a/llvm/include/llvm/Object/RelocationResolver.h b/llvm/include/llvm/Object/RelocationResolver.h --- a/llvm/include/llvm/Object/RelocationResolver.h +++ b/llvm/include/llvm/Object/RelocationResolver.h @@ -31,7 +31,8 @@ namespace llvm { namespace object { -using RelocationResolver = uint64_t (*)(RelocationRef R, uint64_t S, uint64_t A); +using RelocationResolver = Expected (*)(RelocationRef R, uint64_t S, + uint64_t A); std::pair getRelocationResolver(const ObjectFile &Obj); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp @@ -25,10 +25,20 @@ return A; if (SecNdx) *SecNdx = E->SectionIndex; - uint64_t R = E->Resolver(E->Reloc, E->SymbolValue, A); - if (E->Reloc2) - R = E->Resolver(*E->Reloc2, E->SymbolValue2, R); - return R; + ErrorAsOutParameter ErrAsOut(Err); + if (Err && *Err) + return A; + + Expected R = E->Resolver(E->Reloc, E->SymbolValue, A); + if (E->Reloc2 && R) + R = E->Resolver(*E->Reloc2, E->SymbolValue2, *R); + if (R) + return *R; + if (Err) + *Err = R.takeError(); + else + consumeError(R.takeError()); + return A; } Optional diff --git a/llvm/lib/Object/RelocationResolver.cpp b/llvm/lib/Object/RelocationResolver.cpp --- a/llvm/lib/Object/RelocationResolver.cpp +++ b/llvm/lib/Object/RelocationResolver.cpp @@ -23,6 +23,21 @@ return *AddendOrErr; } +static Expected reportError(StringRef type, const Twine &v, + int64_t min, uint64_t max) { + return createStringError(inconvertibleErrorCode(), + "relocation " + type + " out of range: " + Twine(v) + + " is not in [" + Twine(min) + ", " + Twine(max) + + "]"); +} + +static Expected checkInt(uint32_t machine, uint32_t type, int64_t v, int n) { + if (v == llvm::SignExtend64(v, n)) + return v; + return reportError(getELFRelocationTypeName(machine, type), Twine(v), + minIntN(n), maxIntN(n)); +} + static bool supportsX86_64(uint64_t Type) { switch (Type) { case ELF::R_X86_64_NONE: @@ -38,19 +53,24 @@ } } -static uint64_t resolveX86_64(RelocationRef R, uint64_t S, uint64_t A) { - switch (R.getType()) { +static Expected resolveX86_64(RelocationRef r, uint64_t s, + uint64_t /*a*/) { + uint32_t type = r.getType(); + uint64_t a = getELFAddend(r); + switch (type) { case ELF::R_X86_64_NONE: - return A; + return a; case ELF::R_X86_64_64: case ELF::R_X86_64_DTPOFF32: case ELF::R_X86_64_DTPOFF64: - return S + getELFAddend(R); - case ELF::R_X86_64_PC32: - return S + getELFAddend(R) - R.getOffset(); + return s + a; + case ELF::R_X86_64_PC32: { + uint64_t v = s + a - r.getOffset(); + return checkInt(ELF::EM_X86_64, type, v, 32); + } case ELF::R_X86_64_32: case ELF::R_X86_64_32S: - return (S + getELFAddend(R)) & 0xFFFFFFFF; + return (s + a) & 0xFFFFFFFF; default: llvm_unreachable("Invalid relocation type"); } @@ -66,7 +86,8 @@ } } -static uint64_t resolveAArch64(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolveAArch64(RelocationRef R, uint64_t S, + uint64_t A) { switch (R.getType()) { case ELF::R_AARCH64_ABS32: return (S + getELFAddend(R)) & 0xFFFFFFFF; @@ -87,7 +108,7 @@ } } -static uint64_t resolveBPF(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolveBPF(RelocationRef R, uint64_t S, uint64_t A) { switch (R.getType()) { case ELF::R_BPF_64_32: return (S + A) & 0xFFFFFFFF; @@ -109,7 +130,8 @@ } } -static uint64_t resolveMips64(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolveMips64(RelocationRef R, uint64_t S, + uint64_t A) { switch (R.getType()) { case ELF::R_MIPS_32: return (S + getELFAddend(R)) & 0xFFFFFFFF; @@ -132,7 +154,8 @@ } } -static uint64_t resolvePPC64(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolvePPC64(RelocationRef R, uint64_t S, + uint64_t A) { switch (R.getType()) { case ELF::R_PPC64_ADDR32: return (S + getELFAddend(R)) & 0xFFFFFFFF; @@ -153,7 +176,8 @@ } } -static uint64_t resolveSystemZ(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolveSystemZ(RelocationRef R, uint64_t S, + uint64_t A) { switch (R.getType()) { case ELF::R_390_32: return (S + getELFAddend(R)) & 0xFFFFFFFF; @@ -176,7 +200,8 @@ } } -static uint64_t resolveSparc64(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolveSparc64(RelocationRef R, uint64_t S, + uint64_t A) { switch (R.getType()) { case ELF::R_SPARC_32: case ELF::R_SPARC_64: @@ -198,7 +223,8 @@ } } -static uint64_t resolveAmdgpu(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolveAmdgpu(RelocationRef R, uint64_t S, + uint64_t A) { switch (R.getType()) { case ELF::R_AMDGPU_ABS32: case ELF::R_AMDGPU_ABS64: @@ -219,7 +245,7 @@ } } -static uint64_t resolveX86(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolveX86(RelocationRef R, uint64_t S, uint64_t A) { switch (R.getType()) { case ELF::R_386_NONE: return A; @@ -236,7 +262,8 @@ return Type == ELF::R_PPC_ADDR32; } -static uint64_t resolvePPC32(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolvePPC32(RelocationRef R, uint64_t S, + uint64_t A) { if (R.getType() == ELF::R_PPC_ADDR32) return (S + getELFAddend(R)) & 0xFFFFFFFF; llvm_unreachable("Invalid relocation type"); @@ -246,7 +273,7 @@ return Type == ELF::R_ARM_ABS32; } -static uint64_t resolveARM(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolveARM(RelocationRef R, uint64_t S, uint64_t A) { if (R.getType() == ELF::R_ARM_ABS32) return (S + A) & 0xFFFFFFFF; llvm_unreachable("Invalid relocation type"); @@ -262,7 +289,7 @@ } } -static uint64_t resolveAVR(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolveAVR(RelocationRef R, uint64_t S, uint64_t A) { switch (R.getType()) { case ELF::R_AVR_16: return (S + getELFAddend(R)) & 0xFFFF; @@ -277,7 +304,8 @@ return Type == ELF::R_LANAI_32; } -static uint64_t resolveLanai(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolveLanai(RelocationRef R, uint64_t S, + uint64_t A) { if (R.getType() == ELF::R_LANAI_32) return (S + getELFAddend(R)) & 0xFFFFFFFF; llvm_unreachable("Invalid relocation type"); @@ -293,7 +321,8 @@ } } -static uint64_t resolveMips32(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolveMips32(RelocationRef R, uint64_t S, + uint64_t A) { // FIXME: Take in account implicit addends to get correct results. uint32_t Rel = R.getType(); if (Rel == ELF::R_MIPS_32) @@ -313,7 +342,8 @@ } } -static uint64_t resolveSparc32(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolveSparc32(RelocationRef R, uint64_t S, + uint64_t A) { uint32_t Rel = R.getType(); if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32) return S + getELFAddend(R); @@ -324,7 +354,8 @@ return Type == ELF::R_HEX_32; } -static uint64_t resolveHexagon(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolveHexagon(RelocationRef R, uint64_t S, + uint64_t A) { if (R.getType() == ELF::R_HEX_32) return S + getELFAddend(R); llvm_unreachable("Invalid relocation type"); @@ -351,7 +382,8 @@ } } -static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolveRISCV(RelocationRef R, uint64_t S, + uint64_t A) { int64_t RA = getELFAddend(R); switch (R.getType()) { case ELF::R_RISCV_NONE: @@ -395,7 +427,8 @@ } } -static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolveCOFFX86(RelocationRef R, uint64_t S, + uint64_t A) { switch (R.getType()) { case COFF::IMAGE_REL_I386_SECREL: case COFF::IMAGE_REL_I386_DIR32: @@ -415,7 +448,8 @@ } } -static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolveCOFFX86_64(RelocationRef R, uint64_t S, + uint64_t A) { switch (R.getType()) { case COFF::IMAGE_REL_AMD64_SECREL: return (S + A) & 0xFFFFFFFF; @@ -426,11 +460,54 @@ } } +static bool supportsCOFFARM(uint64_t Type) { + switch (Type) { + case COFF::IMAGE_REL_ARM_SECREL: + case COFF::IMAGE_REL_ARM_ADDR32: + return true; + default: + return false; + } +} + +static Expected resolveCOFFARM(RelocationRef R, uint64_t S, uint64_t A) { + switch (R.getType()) { + case COFF::IMAGE_REL_ARM_SECREL: + case COFF::IMAGE_REL_ARM_ADDR32: + return (S + A) & 0xFFFFFFFF; + default: + llvm_unreachable("Invalid relocation type"); + } +} + +static bool supportsCOFFARM64(uint64_t Type) { + switch (Type) { + case COFF::IMAGE_REL_ARM64_SECREL: + case COFF::IMAGE_REL_ARM64_ADDR64: + return true; + default: + return false; + } +} + +static Expected resolveCOFFARM64(RelocationRef R, uint64_t S, + uint64_t A) { + switch (R.getType()) { + case COFF::IMAGE_REL_ARM64_SECREL: + return (S + A) & 0xFFFFFFFF; + case COFF::IMAGE_REL_ARM64_ADDR64: + return S + A; + default: + llvm_unreachable("Invalid relocation type"); + } +} + static bool supportsMachOX86_64(uint64_t Type) { return Type == MachO::X86_64_RELOC_UNSIGNED; } -static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolveMachOX86_64(RelocationRef R, uint64_t S, + uint64_t A) { if (R.getType() == MachO::X86_64_RELOC_UNSIGNED) return S; llvm_unreachable("Invalid relocation type"); @@ -455,7 +532,8 @@ } } -static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) { +static Expected resolveWasm32(RelocationRef R, uint64_t S, + uint64_t A) { switch (R.getType()) { case wasm::R_WASM_FUNCTION_INDEX_LEB: case wasm::R_WASM_TABLE_INDEX_SLEB: @@ -478,9 +556,19 @@ std::pair getRelocationResolver(const ObjectFile &Obj) { if (Obj.isCOFF()) { - if (Obj.getBytesInAddress() == 8) + switch (Obj.getArch()) { + case Triple::x86_64: return {supportsCOFFX86_64, resolveCOFFX86_64}; - return {supportsCOFFX86, resolveCOFFX86}; + case Triple::x86: + return {supportsCOFFX86, resolveCOFFX86}; + case Triple::arm: + case Triple::thumb: + return {supportsCOFFARM, resolveCOFFARM}; + case Triple::aarch64: + return {supportsCOFFARM64, resolveCOFFARM64}; + default: + return {nullptr, nullptr}; + } } else if (Obj.isELF()) { if (Obj.getBytesInAddress() == 8) { switch (Obj.getArch()) { diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -4744,9 +4744,11 @@ FileStr); uint64_t Addend = Data.getAddress(&Offset); - uint64_t SymValue = Resolver(Reloc, RelocSymValue, Addend); - this->printFunctionStackSize(Obj, SymValue, FunctionSec, StackSizeSectionName, - Data, &Offset); + if (Expected SymValue = Resolver(Reloc, RelocSymValue, Addend)) + this->printFunctionStackSize(Obj, *SymValue, FunctionSec, + StackSizeSectionName, Data, &Offset); + else + reportWarning(SymValue.takeError(), FileStr); } template