diff options
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/X86Reference.cpp')
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/X86Reference.cpp | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/lld/lib/ReaderWriter/ELF/X86Reference.cpp b/lld/lib/ReaderWriter/ELF/X86Reference.cpp new file mode 100644 index 00000000000..aae132cd6ed --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/X86Reference.cpp @@ -0,0 +1,121 @@ +//===- lib/ReaderWriter/ELF/X86Reference.cpp ----------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#include "ReferenceKinds.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" + +#include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ELF.h" + +namespace lld { +namespace elf { + +//===----------------------------------------------------------------------===// +// X86KindHandler +// TODO: more to do here +//===----------------------------------------------------------------------===// + +X86KindHandler::~X86KindHandler() { +} + +/// \brief The following relocation routines are derived from the +/// SYSTEM V APPLICATION BINARY INTERFACE: Intel386 Architecture Processor +/// Supplement (Fourth Edition) +/// Symbols used: +/// P: Place, address of the field being relocated, r_offset +/// S: Value of the symbol whose index resides in the relocation entry. +/// A: Addend used to compute the value, r_addend + +namespace x86 { +int relocNone(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + return X86KindHandler::NoError; +} + +/// \brief R_386_32 - word32: S + A +int reloc32(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + int32_t result = (uint32_t)(S + A); + *reinterpret_cast<llvm::support::ulittle32_t *>(location) = result | + *reinterpret_cast<llvm::support::ulittle32_t *>(location); + return X86KindHandler::NoError; +} +/// \brief R_386_PC32 - word32: S + A - P +int relocPC32(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + uint32_t result = (uint32_t)((S + A) - P); + *reinterpret_cast<llvm::support::ulittle32_t *>(location) = result + + *reinterpret_cast<llvm::support::ulittle32_t *>(location); + return X86KindHandler::NoError; +} + +} // namespace x86 + +X86KindHandler::X86KindHandler(){ + _fixupHandler[llvm::ELF::R_386_32] = x86::reloc32; + _fixupHandler[llvm::ELF::R_386_PC32] = x86::relocPC32; +} + +Reference::Kind X86KindHandler::stringToKind(StringRef str) { + return llvm::StringSwitch<Reference::Kind>(str) + .Case("none", none) + .Case("R_386_32", llvm::ELF::R_386_32) + .Case("R_386_PC32", llvm::ELF::R_386_PC32) + .Default(invalid); +} + +StringRef X86KindHandler::kindToString(Reference::Kind kind) { + switch ((int32_t)kind) { + case llvm::ELF::R_386_32: + return "R_386_32"; + case llvm::ELF::R_386_PC32: + return "R_386_PC32"; + default: + return "none"; + } +} + +bool X86KindHandler::isCallSite(Kind kind) { + llvm_unreachable("Unimplemented: X86KindHandler::isCallSite"); + return false; +} + +bool X86KindHandler::isPointer(Kind kind) { + llvm_unreachable("Unimplemented: X86KindHandler::isPointer"); + return false; +} + +bool X86KindHandler::isLazyImmediate(Kind kind) { + llvm_unreachable("Unimplemented: X86KindHandler::isLazyImmediate"); + return false; +} + +bool X86KindHandler::isLazyTarget(Kind kind) { + llvm_unreachable("Unimplemented: X86KindHandler::isLazyTarget"); + return false; +} + +void X86KindHandler::applyFixup(int32_t reloc, uint64_t addend, + uint8_t *location, uint64_t fixupAddress, + uint64_t targetAddress) { + int error; + if (_fixupHandler[reloc]) { + error = (_fixupHandler[reloc])(location, + fixupAddress, targetAddress, addend); + + switch ((RelocationError)error) { + case NoError: + return; + } + } +} + +} // namespace elf +} // namespace lld |

