ELF: Support detection of relocation errors during processing
At the moment errors in relocation processing such as out of range values are not detected or at best trapped by asserts which will not be present in release builds. This patch adds support for checking error return values from applyRelocation() calls and printing an appropriate error message. It also adds support for printing multiple errors rather than just the first one. llvm-svn: 226557
This commit is contained in:
parent
ea6de1f81d
commit
a8c4d48478
|
@ -462,7 +462,7 @@ std::error_code AArch64TargetRelocationHandler::applyRelocation(
|
|||
targetVAddress, ref.addend());
|
||||
break;
|
||||
default:
|
||||
unhandledReferenceType(*atom._atom, ref);
|
||||
return make_unhandled_reloc_error();
|
||||
}
|
||||
|
||||
return std::error_code();
|
||||
|
|
|
@ -20,9 +20,6 @@ template <class ELFT> class AArch64TargetLayout;
|
|||
|
||||
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;
|
||||
|
|
|
@ -19,7 +19,7 @@ using namespace elf;
|
|||
AArch64TargetHandler::AArch64TargetHandler(AArch64LinkingContext &context)
|
||||
: _context(context),
|
||||
_AArch64TargetLayout(new AArch64TargetLayout<AArch64ELFType>(context)),
|
||||
_AArch64RelocationHandler(new AArch64TargetRelocationHandler(context)) {}
|
||||
_AArch64RelocationHandler(new AArch64TargetRelocationHandler()) {}
|
||||
|
||||
void AArch64TargetHandler::registerRelocationNames(Registry ®istry) {
|
||||
registry.addKindTable(Reference::KindNamespace::ELF,
|
||||
|
|
|
@ -344,7 +344,7 @@ std::error_code HexagonTargetRelocationHandler::applyRelocation(
|
|||
break;
|
||||
|
||||
default:
|
||||
unhandledReferenceType(*atom._atom, ref);
|
||||
return make_unhandled_reloc_error();
|
||||
}
|
||||
|
||||
return std::error_code();
|
||||
|
|
|
@ -20,9 +20,8 @@ class HexagonTargetHandler;
|
|||
|
||||
class HexagonTargetRelocationHandler final : public TargetRelocationHandler {
|
||||
public:
|
||||
HexagonTargetRelocationHandler(HexagonTargetLayout<HexagonELFType> &layout,
|
||||
ELFLinkingContext &targetInfo)
|
||||
: TargetRelocationHandler(targetInfo), _hexagonTargetLayout(layout) {}
|
||||
HexagonTargetRelocationHandler(HexagonTargetLayout<HexagonELFType> &layout)
|
||||
: _hexagonTargetLayout(layout) {}
|
||||
|
||||
std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
|
||||
const lld::AtomLayout &,
|
||||
|
|
|
@ -23,7 +23,7 @@ HexagonTargetHandler::HexagonTargetHandler(HexagonLinkingContext &context)
|
|||
_hexagonRuntimeFile(new HexagonRuntimeFile<HexagonELFType>(context)),
|
||||
_hexagonTargetLayout(new HexagonTargetLayout<HexagonELFType>(context)),
|
||||
_hexagonRelocationHandler(new HexagonTargetRelocationHandler(
|
||||
*_hexagonTargetLayout.get(), context)) {}
|
||||
*_hexagonTargetLayout.get())) {}
|
||||
|
||||
std::unique_ptr<Writer> HexagonTargetHandler::getWriter() {
|
||||
switch (_hexagonLinkingContext.getOutputELFType()) {
|
||||
|
|
|
@ -341,7 +341,7 @@ std::error_code MipsTargetRelocationHandler::applyRelocation(
|
|||
// Do nothing.
|
||||
break;
|
||||
default:
|
||||
unhandledReferenceType(*atom._atom, ref);
|
||||
return make_unhandled_reloc_error();
|
||||
}
|
||||
|
||||
if (shuffle)
|
||||
|
|
|
@ -18,9 +18,8 @@ class MipsTargetHandler;
|
|||
|
||||
class MipsTargetRelocationHandler final : public TargetRelocationHandler {
|
||||
public:
|
||||
MipsTargetRelocationHandler(MipsTargetLayout<Mips32ElELFType> &layout,
|
||||
ELFLinkingContext &targetInfo)
|
||||
: TargetRelocationHandler(targetInfo), _mipsTargetLayout(layout) {}
|
||||
MipsTargetRelocationHandler(MipsTargetLayout<Mips32ElELFType> &layout)
|
||||
: _mipsTargetLayout(layout) {}
|
||||
|
||||
std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
|
||||
const lld::AtomLayout &,
|
||||
|
|
|
@ -21,8 +21,7 @@ typedef llvm::object::ELFType<llvm::support::little, 2, false> Mips32ElELFType;
|
|||
MipsTargetHandler::MipsTargetHandler(MipsLinkingContext &ctx)
|
||||
: _ctx(ctx), _runtimeFile(new MipsRuntimeFile<Mips32ElELFType>(ctx)),
|
||||
_targetLayout(new MipsTargetLayout<Mips32ElELFType>(ctx)),
|
||||
_relocationHandler(new MipsTargetRelocationHandler(*_targetLayout, ctx)) {
|
||||
}
|
||||
_relocationHandler(new MipsTargetRelocationHandler(*_targetLayout)) {}
|
||||
|
||||
std::unique_ptr<Writer> MipsTargetHandler::getWriter() {
|
||||
switch (_ctx.getOutputELFType()) {
|
||||
|
|
|
@ -52,7 +52,7 @@ std::error_code PPCTargetRelocationHandler::applyRelocation(
|
|||
break;
|
||||
|
||||
default:
|
||||
unhandledReferenceType(*atom._atom, ref);
|
||||
return make_unhandled_reloc_error();
|
||||
}
|
||||
|
||||
return std::error_code();
|
||||
|
@ -61,7 +61,7 @@ std::error_code PPCTargetRelocationHandler::applyRelocation(
|
|||
PPCTargetHandler::PPCTargetHandler(PPCLinkingContext &context)
|
||||
: _ppcLinkingContext(context),
|
||||
_ppcTargetLayout(new PPCTargetLayout<PPCELFType>(context)),
|
||||
_ppcRelocationHandler(new PPCTargetRelocationHandler(context)) {}
|
||||
_ppcRelocationHandler(new PPCTargetRelocationHandler()) {}
|
||||
|
||||
void PPCTargetHandler::registerRelocationNames(Registry ®istry) {
|
||||
registry.addKindTable(Reference::KindNamespace::ELF,
|
||||
|
|
|
@ -25,9 +25,6 @@ public:
|
|||
|
||||
class PPCTargetRelocationHandler final : public TargetRelocationHandler {
|
||||
public:
|
||||
PPCTargetRelocationHandler(ELFLinkingContext &context)
|
||||
: TargetRelocationHandler(context) {}
|
||||
|
||||
std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
|
||||
const lld::AtomLayout &,
|
||||
const Reference &) const override;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/FileOutputBuffer.h"
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
|
@ -269,6 +270,31 @@ protected:
|
|||
int32_t _contentPermissions;
|
||||
bool _isLoadedInMemory;
|
||||
std::vector<lld::AtomLayout *> _atoms;
|
||||
mutable std::mutex _outputMutex;
|
||||
|
||||
void printError(const std::string &errorStr, const AtomLayout &atom,
|
||||
const Reference &ref) const {
|
||||
StringRef kindValStr;
|
||||
if (!this->_context.registry().referenceKindToString(ref.kindNamespace(),
|
||||
ref.kindArch(),
|
||||
ref.kindValue(),
|
||||
kindValStr)) {
|
||||
kindValStr = "unknown";
|
||||
}
|
||||
|
||||
std::string errStr = (Twine(errorStr) + " in file " +
|
||||
atom._atom->file().path() +
|
||||
": reference from " + atom._atom->name() +
|
||||
"+" + Twine(ref.offsetInAtom()) +
|
||||
" to " + ref.target()->name() +
|
||||
"+" + Twine(ref.addend()) +
|
||||
" of type " + Twine(ref.kindValue()) +
|
||||
" (" + kindValStr + ")\n").str();
|
||||
|
||||
// Take the lock to prevent output getting interleaved between threads
|
||||
std::lock_guard<std::mutex> lock(_outputMutex);
|
||||
llvm::errs() << errStr;
|
||||
}
|
||||
};
|
||||
|
||||
/// Align the offset to the required modulus defined by the atom alignment
|
||||
|
@ -377,6 +403,7 @@ template <class ELFT>
|
|||
void AtomSection<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &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 +420,16 @@ void AtomSection<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout,
|
|||
std::memcpy(atomContent, content.data(), contentSize);
|
||||
const TargetRelocationHandler &relHandler =
|
||||
this->_context.template getTargetHandler<ELFT>().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)
|
||||
llvm::report_fatal_error("relocating output");
|
||||
}
|
||||
|
||||
/// \brief A OutputSection represents a set of sections grouped by the same
|
||||
|
|
|
@ -43,32 +43,12 @@ template <class ELFT> class TargetLayout;
|
|||
class TargetRelocationHandler {
|
||||
public:
|
||||
/// Constructor
|
||||
TargetRelocationHandler(ELFLinkingContext &targetInfo) : _ctx(targetInfo) {}
|
||||
TargetRelocationHandler() {}
|
||||
virtual ~TargetRelocationHandler() {}
|
||||
|
||||
virtual std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
|
||||
const lld::AtomLayout &,
|
||||
const Reference &) const = 0;
|
||||
|
||||
protected:
|
||||
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 (!_ctx.registry().referenceKindToString(
|
||||
ref.kindNamespace(), ref.kindArch(), ref.kindValue(), kindValStr)) {
|
||||
kindValStr = "unknown";
|
||||
}
|
||||
|
||||
llvm::errs() << ref.kindValue() << " (" << kindValStr << ")\n";
|
||||
llvm::report_fatal_error("unhandled reference type");
|
||||
}
|
||||
|
||||
private:
|
||||
ELFLinkingContext &_ctx;
|
||||
};
|
||||
|
||||
/// \brief TargetHandler contains all the information responsible to handle a
|
||||
|
@ -91,6 +71,15 @@ public:
|
|||
/// How does the target deal with writing ELF output.
|
||||
virtual std::unique_ptr<Writer> getWriter() = 0;
|
||||
};
|
||||
|
||||
inline std::error_code make_unhandled_reloc_error() {
|
||||
return make_dynamic_error_code(Twine("Unhandled reference type"));
|
||||
}
|
||||
|
||||
inline std::error_code make_out_of_range_reloc_error() {
|
||||
return make_dynamic_error_code(Twine("Relocation out of range"));
|
||||
}
|
||||
|
||||
} // end namespace elf
|
||||
} // end namespace lld
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ std::error_code X86TargetRelocationHandler::applyRelocation(
|
|||
relocPC32(location, relocVAddress, targetVAddress, ref.addend());
|
||||
break;
|
||||
default:
|
||||
unhandledReferenceType(*atom._atom, ref);
|
||||
return make_unhandled_reloc_error();
|
||||
}
|
||||
|
||||
return std::error_code();
|
||||
|
|
|
@ -18,9 +18,6 @@ typedef llvm::object::ELFType<llvm::support::little, 2, false> X86ELFType;
|
|||
|
||||
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;
|
||||
|
|
|
@ -50,4 +50,4 @@ void X86TargetHandler::registerRelocationNames(Registry ®istry) {
|
|||
X86TargetHandler::X86TargetHandler(X86LinkingContext &context)
|
||||
: _x86LinkingContext(context),
|
||||
_x86TargetLayout(new X86TargetLayout<X86ELFType>(context)),
|
||||
_x86RelocationHandler(new X86TargetRelocationHandler(context)) {}
|
||||
_x86RelocationHandler(new X86TargetRelocationHandler()) {}
|
||||
|
|
|
@ -123,7 +123,7 @@ std::error_code X86_64TargetRelocationHandler::applyRelocation(
|
|||
case R_X86_64_DTPOFF64:
|
||||
break;
|
||||
default:
|
||||
unhandledReferenceType(*atom._atom, ref);
|
||||
return make_unhandled_reloc_error();
|
||||
}
|
||||
|
||||
return std::error_code();
|
||||
|
|
|
@ -20,10 +20,8 @@ template <class ELFT> class X86_64TargetLayout;
|
|||
|
||||
class X86_64TargetRelocationHandler final : public TargetRelocationHandler {
|
||||
public:
|
||||
X86_64TargetRelocationHandler(X86_64TargetLayout<X86_64ELFType> &layout,
|
||||
ELFLinkingContext &targetInfo)
|
||||
: TargetRelocationHandler(targetInfo), _tlsSize(0),
|
||||
_x86_64Layout(layout) {}
|
||||
X86_64TargetRelocationHandler(X86_64TargetLayout<X86_64ELFType> &layout)
|
||||
: _tlsSize(0), _x86_64Layout(layout) {}
|
||||
|
||||
std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
|
||||
const lld::AtomLayout &,
|
||||
|
|
|
@ -20,7 +20,7 @@ X86_64TargetHandler::X86_64TargetHandler(X86_64LinkingContext &context)
|
|||
: _context(context),
|
||||
_x86_64TargetLayout(new X86_64TargetLayout<X86_64ELFType>(context)),
|
||||
_x86_64RelocationHandler(new X86_64TargetRelocationHandler(
|
||||
*_x86_64TargetLayout.get(), context)) {}
|
||||
*_x86_64TargetLayout.get())) {}
|
||||
|
||||
void X86_64TargetHandler::registerRelocationNames(Registry ®istry) {
|
||||
registry.addKindTable(Reference::KindNamespace::ELF,
|
||||
|
|
Loading…
Reference in New Issue