Index: include/lld/Core/Error.h =================================================================== --- include/lld/Core/Error.h +++ include/lld/Core/Error.h @@ -58,6 +58,18 @@ return std::error_code(static_cast(e), LinkerScriptReaderCategory()); } +const std::error_category &RelocationCategory(); + +enum class RelocationError { + success = 0, + unhandled_reference_type, + out_of_range, +}; + +inline std::error_code make_error_code(RelocationError e) { + return std::error_code(static_cast(e), RelocationCategory()); +} + /// Creates an error_code object that has associated with it an arbitrary /// error messsage. The value() of the error_code will always be non-zero /// but its value is meaningless. The messsage() will be (a copy of) the @@ -75,6 +87,7 @@ template <> struct is_error_code_enum : std::true_type {}; template <> struct is_error_code_enum : std::true_type {}; +template <> struct is_error_code_enum : std::true_type {}; } #endif Index: lib/Core/Error.cpp =================================================================== --- lib/Core/Error.cpp +++ lib/Core/Error.cpp @@ -97,6 +97,30 @@ return o; } +class _RelocationErrorCategory : public std::error_category { +public: + const char *name() const LLVM_NOEXCEPT override { + return "lld.relocation"; + } + + std::string message(int ev) const override { + switch (static_cast(ev)) { + case RelocationError::success: return "Success"; + case RelocationError::unhandled_reference_type: + return "Unhandled reference type"; + case RelocationError::out_of_range: + return "Relocation out of range"; + } + llvm_unreachable("An enumerator of RelocationError does not have a " + "message defined."); + } +}; + +const std::error_category &lld::RelocationCategory() { + static _RelocationErrorCategory o; + return o; +} + namespace lld { Index: lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h =================================================================== --- lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h +++ lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h @@ -21,9 +21,6 @@ class AArch64TargetRelocationHandler final : public TargetRelocationHandler { public: - AArch64TargetRelocationHandler(ELFLinkingContext &targetInfo) - : TargetRelocationHandler(targetInfo) {} - std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const lld::AtomLayout &, const Reference &) const override; Index: lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp =================================================================== --- lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp +++ lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp @@ -16,6 +16,12 @@ #define PAGE(X) ((X) & ~0x0FFFL) +bool withinSignedUnsignedRange(int64_t X, int bits) { + if (X < -(1L << (bits - 1)) || X >= (1L << bits)) + return false; + return true; +} + /// \brief R_AARCH64_ABS64 - word64: S + A static void relocR_AARCH64_ABS64(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { @@ -41,9 +47,11 @@ } /// \brief R_AARCH64_ABS32 - word32: S + A -static void relocR_AARCH64_ABS32(uint8_t *location, uint64_t P, uint64_t S, - int64_t A) { - int32_t result = (int32_t)(S + A); +static std::error_code relocR_AARCH64_ABS32(uint8_t *location, uint64_t P, + uint64_t S, int64_t A) { + int64_t result = (S + A); + if (!withinSignedUnsignedRange(result, 32)) + return RelocationError::out_of_range; DEBUG_WITH_TYPE( "AArch64", llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -"; llvm::dbgs() << " S: 0x" << Twine::utohexstr(S); @@ -53,6 +61,7 @@ *reinterpret_cast(location) = result | (int32_t) * reinterpret_cast(location); + return std::error_code(); } /// \brief R_AARCH64_ADR_PREL_PG_HI21 - Page(S+A) - Page(P) @@ -385,8 +394,8 @@ ref.addend()); break; case R_AARCH64_ABS32: - relocR_AARCH64_ABS32(location, relocVAddress, targetVAddress, ref.addend()); - break; + return relocR_AARCH64_ABS32(location, relocVAddress, targetVAddress, + ref.addend()); // Runtime only relocations. Ignore here. case R_AARCH64_RELATIVE: case R_AARCH64_IRELATIVE: @@ -462,7 +471,7 @@ targetVAddress, ref.addend()); break; default: - unhandledReferenceType(*atom._atom, ref); + return RelocationError::unhandled_reference_type; } return std::error_code(); Index: lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp =================================================================== --- lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp +++ lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp @@ -19,8 +19,7 @@ AArch64TargetHandler::AArch64TargetHandler(AArch64LinkingContext &context) : DefaultTargetHandler(context), _context(context), _AArch64TargetLayout(new AArch64TargetLayout(context)), - _AArch64RelocationHandler( - new AArch64TargetRelocationHandler(context)) {} + _AArch64RelocationHandler(new AArch64TargetRelocationHandler()) {} void AArch64TargetHandler::registerRelocationNames(Registry ®istry) { registry.addKindTable(Reference::KindNamespace::ELF, Index: lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h =================================================================== --- lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h +++ lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h @@ -21,10 +21,8 @@ class HexagonTargetRelocationHandler final : public TargetRelocationHandler { public: - HexagonTargetRelocationHandler(HexagonTargetLayout &layout, - ELFLinkingContext &targetInfo) - : TargetRelocationHandler(targetInfo), - _hexagonTargetLayout(layout) {} + HexagonTargetRelocationHandler(HexagonTargetLayout &layout) + : _hexagonTargetLayout(layout) {} std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const lld::AtomLayout &, Index: lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp =================================================================== --- lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp +++ lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp @@ -344,7 +344,7 @@ break; default: - unhandledReferenceType(*atom._atom, ref); + return RelocationError::unhandled_reference_type; } return std::error_code(); Index: lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp =================================================================== --- lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp +++ lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp @@ -23,7 +23,7 @@ _hexagonRuntimeFile(new HexagonRuntimeFile(context)), _hexagonTargetLayout(new HexagonTargetLayout(context)), _hexagonRelocationHandler(new HexagonTargetRelocationHandler( - *_hexagonTargetLayout.get(), context)) {} + *_hexagonTargetLayout.get())) {} std::unique_ptr HexagonTargetHandler::getWriter() { switch (_hexagonLinkingContext.getOutputELFType()) { Index: lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h =================================================================== --- lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h +++ lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h @@ -19,10 +19,8 @@ class MipsTargetRelocationHandler final : public TargetRelocationHandler { public: - MipsTargetRelocationHandler(MipsTargetLayout &layout, - ELFLinkingContext &targetInfo) - : TargetRelocationHandler(targetInfo), - _mipsTargetLayout(layout) {} + MipsTargetRelocationHandler(MipsTargetLayout &layout) + : _mipsTargetLayout(layout) {} std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const lld::AtomLayout &, Index: lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp =================================================================== --- lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp +++ lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp @@ -341,7 +341,7 @@ // Do nothing. break; default: - unhandledReferenceType(*atom._atom, ref); + return RelocationError::unhandled_reference_type; } if (shuffle) Index: lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp =================================================================== --- lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp +++ lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp @@ -22,7 +22,7 @@ : DefaultTargetHandler(ctx), _ctx(ctx), _runtimeFile(new MipsRuntimeFile(ctx)), _targetLayout(new MipsTargetLayout(ctx)), - _relocationHandler(new MipsTargetRelocationHandler(*_targetLayout, ctx)) {} + _relocationHandler(new MipsTargetRelocationHandler(*_targetLayout)) {} std::unique_ptr MipsTargetHandler::getWriter() { switch (_ctx.getOutputELFType()) { Index: lib/ReaderWriter/ELF/PPC/PPCTargetHandler.h =================================================================== --- lib/ReaderWriter/ELF/PPC/PPCTargetHandler.h +++ lib/ReaderWriter/ELF/PPC/PPCTargetHandler.h @@ -26,10 +26,8 @@ class PPCTargetRelocationHandler final : public TargetRelocationHandler { public: - PPCTargetRelocationHandler(ELFLinkingContext &context, - PPCTargetLayout &layout) - : TargetRelocationHandler(context), - _ppcTargetLayout(layout) {} + PPCTargetRelocationHandler(PPCTargetLayout &layout) + : _ppcTargetLayout(layout) {} virtual std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const lld::AtomLayout &, Index: lib/ReaderWriter/ELF/PPC/PPCTargetHandler.cpp =================================================================== --- lib/ReaderWriter/ELF/PPC/PPCTargetHandler.cpp +++ lib/ReaderWriter/ELF/PPC/PPCTargetHandler.cpp @@ -52,7 +52,7 @@ break; default: - unhandledReferenceType(*atom._atom, ref); + return RelocationError::unhandled_reference_type; } return std::error_code(); @@ -62,7 +62,7 @@ : DefaultTargetHandler(context), _ppcLinkingContext(context), _ppcTargetLayout(new PPCTargetLayout(context)), _ppcRelocationHandler( - new PPCTargetRelocationHandler(context, *_ppcTargetLayout.get())) {} + new PPCTargetRelocationHandler(*_ppcTargetLayout.get())) {} void PPCTargetHandler::registerRelocationNames(Registry ®istry) { registry.addKindTable(Reference::KindNamespace::ELF, Index: lib/ReaderWriter/ELF/SectionChunks.h =================================================================== --- lib/ReaderWriter/ELF/SectionChunks.h +++ lib/ReaderWriter/ELF/SectionChunks.h @@ -269,6 +269,24 @@ int32_t _contentPermissions; bool _isLoadedInMemory; std::vector _atoms; + + void printError(const std::string &errorStr, const AtomLayout &atom, + const Reference &ref) const { + llvm::errs() << errorStr << " in file " << atom._atom->file().path() + << ": reference from " << atom._atom->name() << "+" + << ref.offsetInAtom() << " to " << ref.target()->name() + << "+" << ref.addend() << " of type "; + + StringRef kindValStr; + if (!this->_context.registry().referenceKindToString(ref.kindNamespace(), + ref.kindArch(), + ref.kindValue(), + kindValStr)) { + kindValStr = "unknown"; + } + + llvm::errs() << ref.kindValue() << " (" << kindValStr << ")\n"; + } }; /// Align the offset to the required modulus defined by the atom alignment @@ -377,6 +395,7 @@ void AtomSection::write(ELFWriter *writer, TargetLayout &layout, llvm::FileOutputBuffer &buffer) { uint8_t *chunkBuffer = buffer.getBufferStart(); + bool success = true; parallel_for_each(_atoms.begin(), _atoms.end(), [&](lld::AtomLayout * ai) { DEBUG_WITH_TYPE("Section", llvm::dbgs() << "Writing atom: " << ai->_atom->name() @@ -393,9 +412,16 @@ std::memcpy(atomContent, content.data(), contentSize); const TargetRelocationHandler &relHandler = this->_context.template getTargetHandler().getRelocationHandler(); - for (const auto ref : *definedAtom) - relHandler.applyRelocation(*writer, buffer, *ai, *ref); + for (const auto ref : *definedAtom) { + if (std::error_code EC = relHandler.applyRelocation(*writer, buffer, + *ai, *ref)) { + printError(EC.message(), *ai, *ref); + success = false; + } + } }); + if (success == false) + llvm::report_fatal_error("relocating output"); } /// \brief A OutputSection represents a set of sections grouped by the same Index: lib/ReaderWriter/ELF/TargetHandler.h =================================================================== --- lib/ReaderWriter/ELF/TargetHandler.h +++ lib/ReaderWriter/ELF/TargetHandler.h @@ -42,35 +42,11 @@ template class TargetRelocationHandler { public: - /// Constructor - TargetRelocationHandler(ELFLinkingContext &targetInfo) - : _context(targetInfo) {} - virtual std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const lld::AtomLayout &, const Reference &) const = 0; - void unhandledReferenceType(const Atom &atom, const Reference &ref) const { - llvm::errs() << "Unhandled reference type in file " << atom.file().path() - << ": reference from " << atom.name() << "+" - << ref.offsetInAtom() << " to " << ref.target()->name() - << "+" << ref.addend() << " of type "; - - StringRef kindValStr; - if (!_context.registry().referenceKindToString(ref.kindNamespace(), - ref.kindArch(), - ref.kindValue(), - kindValStr)) { - kindValStr = "unknown"; - } - - llvm::errs() << ref.kindValue() << " (" << kindValStr << ")\n"; - llvm::report_fatal_error("unhandled reference type"); - } - virtual ~TargetRelocationHandler() {} -private: - ELFLinkingContext &_context; }; /// \brief TargetHandler contains all the information responsible to handle a Index: lib/ReaderWriter/ELF/X86/X86RelocationHandler.h =================================================================== --- lib/ReaderWriter/ELF/X86/X86RelocationHandler.h +++ lib/ReaderWriter/ELF/X86/X86RelocationHandler.h @@ -20,9 +20,6 @@ class X86TargetRelocationHandler final : public TargetRelocationHandler { public: - X86TargetRelocationHandler(ELFLinkingContext &targetInfo) - : TargetRelocationHandler(targetInfo) {} - std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const lld::AtomLayout &, const Reference &) const override; Index: lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp =================================================================== --- lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp +++ lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp @@ -52,7 +52,7 @@ relocPC32(location, relocVAddress, targetVAddress, ref.addend()); break; default: - unhandledReferenceType(*atom._atom, ref); + return RelocationError::unhandled_reference_type; } return std::error_code(); Index: lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp =================================================================== --- lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp +++ lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp @@ -50,5 +50,4 @@ X86TargetHandler::X86TargetHandler(X86LinkingContext &context) : DefaultTargetHandler(context), _x86LinkingContext(context), _x86TargetLayout(new X86TargetLayout(context)), - _x86RelocationHandler( - new X86TargetRelocationHandler(context)) {} + _x86RelocationHandler(new X86TargetRelocationHandler()) {} Index: lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h =================================================================== --- lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h +++ lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h @@ -21,10 +21,8 @@ class X86_64TargetRelocationHandler final : public TargetRelocationHandler { public: - X86_64TargetRelocationHandler(X86_64TargetLayout &layout, - ELFLinkingContext &targetInfo) - : TargetRelocationHandler(targetInfo), - _tlsSize(0), _x86_64Layout(layout) {} + X86_64TargetRelocationHandler(X86_64TargetLayout &layout) + : _tlsSize(0), _x86_64Layout(layout) {} std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const lld::AtomLayout &, Index: lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp =================================================================== --- lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp +++ lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp @@ -123,7 +123,7 @@ case R_X86_64_DTPOFF64: break; default: - unhandledReferenceType(*atom._atom, ref); + return RelocationError::unhandled_reference_type; } return std::error_code(); Index: lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp =================================================================== --- lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp +++ lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp @@ -20,8 +20,7 @@ : DefaultTargetHandler(context), _context(context), _x86_64TargetLayout(new X86_64TargetLayout(context)), _x86_64RelocationHandler( - new X86_64TargetRelocationHandler(*_x86_64TargetLayout.get(), - context)) {} + new X86_64TargetRelocationHandler(*_x86_64TargetLayout.get())) {} void X86_64TargetHandler::registerRelocationNames(Registry ®istry) { registry.addKindTable(Reference::KindNamespace::ELF, Index: test/elf/AArch64/rel-abs32-overflow.test =================================================================== --- /dev/null +++ test/elf/AArch64/rel-abs32-overflow.test @@ -0,0 +1,53 @@ +# Check handling of R_AARCH64_ABS32 relocation overflow. +# RUN: yaml2obj -format=elf %s > %t-obj +# RUN: not lld -flavor gnu -target arm64 -o %t-exe %t-obj 2>&1 | FileCheck %s + +# CHECK: Relocation out of range in file {{.*}}: reference from data1+0 to data2+34359738369 of type 258 (R_AARCH64_ABS32) +# CHECK: Relocation out of range in file {{.*}}: reference from data2+0 to data1+34359738369 of type 258 (R_AARCH64_ABS32) + +!ELF +FileHeader: !FileHeader + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_AARCH64 + +Sections: +- Name: .text + Type: SHT_PROGBITS + Content: "00000000" + AddressAlign: 16 + Flags: [SHF_ALLOC, SHF_EXECINSTR] +- Name: .data + Type: SHT_PROGBITS + Content: "0000000000000000" + AddressAlign: 16 + Flags: [SHF_ALLOC, SHF_WRITE] + +- Name: .rela.data + Type: SHT_RELA + Info: .data + AddressAlign: 8 + Relocations: + - Offset: 0x0 + Symbol: data2 + Type: R_AARCH64_ABS32 + Addend: 0x800000001 + - Offset: 0x4 + Symbol: data1 + Type: R_AARCH64_ABS32 + Addend: 0x800000001 + +Symbols: + Global: + - Name: _start + Section: .text + Value: 0x0 + Size: 4 + - Name: data1 + Section: .data + Size: 4 + - Name: data2 + Section: .data + Value: 0x4 + Size: 4