diff options
Diffstat (limited to 'lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp')
-rw-r--r-- | lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp b/lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp new file mode 100644 index 000000000000..da5a24c6ec37 --- /dev/null +++ b/lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp @@ -0,0 +1,57 @@ +//===- lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp ------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "X86LinkingContext.h" +#include "X86TargetHandler.h" +#include "llvm/Support/Endian.h" + +using namespace lld; +using namespace lld::elf; +using namespace llvm::support::endian; + +namespace { +/// \brief R_386_32 - word32: S + A +static int reloc32(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + int32_t result = (uint32_t)(S + A); + write32le(location, result | read32le(location)); + return 0; +} + +/// \brief R_386_PC32 - word32: S + A - P +static int relocPC32(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + uint32_t result = (uint32_t)((S + A) - P); + write32le(location, result + read32le(location)); + return 0; +} +} + +std::error_code X86TargetRelocationHandler::applyRelocation( + ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::AtomLayout &atom, + const Reference &ref) const { + uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset; + uint8_t *location = atomContent + ref.offsetInAtom(); + uint64_t targetVAddress = writer.addressOfAtom(ref.target()); + uint64_t relocVAddress = atom._virtualAddr + ref.offsetInAtom(); + + if (ref.kindNamespace() != Reference::KindNamespace::ELF) + return std::error_code(); + assert(ref.kindArch() == Reference::KindArch::x86); + switch (ref.kindValue()) { + case R_386_32: + reloc32(location, relocVAddress, targetVAddress, ref.addend()); + break; + case R_386_PC32: + relocPC32(location, relocVAddress, targetVAddress, ref.addend()); + break; + default: + return make_unhandled_reloc_error(); + } + + return std::error_code(); +} |