forked from OSchip/llvm-project
[ELF][x86-64] Add X86_64TargetRelocationHandler and friends.
llvm-svn: 173897
This commit is contained in:
parent
4e9d9cd23b
commit
457a77739b
|
@ -1,5 +1,6 @@
|
|||
add_lld_library(lldX86_64ELFTarget
|
||||
X86_64TargetInfo.cpp
|
||||
X86_64TargetHandler.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(lldX86_64ELFTarget
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
//===- lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp ----------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "X86_64TargetHandler.h"
|
||||
#include "X86_64TargetInfo.h"
|
||||
|
||||
using namespace lld;
|
||||
using namespace elf;
|
||||
|
||||
using namespace llvm::ELF;
|
||||
|
||||
namespace {
|
||||
/// \brief R_X86_64_64 - word64: S + A
|
||||
void reloc64(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
|
||||
uint64_t result = S + A;
|
||||
*reinterpret_cast<llvm::support::ulittle64_t *>(location) = result |
|
||||
(uint64_t)*reinterpret_cast<llvm::support::ulittle64_t *>(location);
|
||||
}
|
||||
|
||||
/// \brief R_X86_64_PC32 - word32: S + A - P
|
||||
void relocPC32(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
|
||||
uint32_t result = (uint32_t)((S + A) - P);
|
||||
*reinterpret_cast<llvm::support::ulittle32_t *>(location) = result +
|
||||
(uint32_t)*reinterpret_cast<llvm::support::ulittle32_t *>(location);
|
||||
}
|
||||
|
||||
/// \brief R_X86_64_32 - word32: S + A
|
||||
void reloc32(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
|
||||
int32_t result = (uint32_t)(S + A);
|
||||
*reinterpret_cast<llvm::support::ulittle32_t *>(location) = result |
|
||||
(uint32_t)*reinterpret_cast<llvm::support::ulittle32_t *>(location);
|
||||
// TODO: Make sure that the result zero extends to the 64bit value.
|
||||
}
|
||||
|
||||
/// \brief R_X86_64_32S - word32: S + A
|
||||
void reloc32S(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
|
||||
int32_t result = (int32_t)(S + A);
|
||||
*reinterpret_cast<llvm::support::little32_t *>(location) = result |
|
||||
(int32_t)*reinterpret_cast<llvm::support::little32_t *>(location);
|
||||
// TODO: Make sure that the result sign extends to the 64bit value.
|
||||
}
|
||||
} // end anon namespace
|
||||
|
||||
ErrorOr<void> X86_64TargetRelocationHandler::applyRelocation(
|
||||
ELFWriter &writer, llvm::FileOutputBuffer &buf, const 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();
|
||||
|
||||
switch (ref.kind()) {
|
||||
case R_X86_64_64:
|
||||
reloc64(location, relocVAddress, targetVAddress, ref.addend());
|
||||
break;
|
||||
case R_X86_64_PC32:
|
||||
relocPC32(location, relocVAddress, targetVAddress, ref.addend());
|
||||
break;
|
||||
case R_X86_64_32:
|
||||
reloc32(location, relocVAddress, targetVAddress, ref.addend());
|
||||
break;
|
||||
case R_X86_64_32S:
|
||||
reloc32S(location, relocVAddress, targetVAddress, ref.addend());
|
||||
break;
|
||||
// Runtime only relocations. Ignore here.
|
||||
case R_X86_64_IRELATIVE:
|
||||
break;
|
||||
default: {
|
||||
std::string str;
|
||||
llvm::raw_string_ostream s(str);
|
||||
auto name = _targetInfo.stringFromRelocKind(ref.kind());
|
||||
s << "Unhandled relocation: "
|
||||
<< (name ? *name : "<unknown>" ) << " (" << ref.kind() << ")";
|
||||
s.flush();
|
||||
llvm_unreachable(str.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
return error_code::success();
|
||||
}
|
||||
|
||||
X86_64TargetHandler::X86_64TargetHandler(X86_64TargetInfo &targetInfo)
|
||||
: DefaultTargetHandler(targetInfo), _relocationHandler(targetInfo) {
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
//===- lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h ------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLD_READER_WRITER_ELF_X86_64_TARGET_HANDLER_H
|
||||
#define LLD_READER_WRITER_ELF_X86_64_TARGET_HANDLER_H
|
||||
|
||||
#include "DefaultTargetHandler.h"
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
typedef llvm::object::ELFType<llvm::support::little, 8, false> X86_64ELFType;
|
||||
class X86_64TargetInfo;
|
||||
|
||||
class X86_64TargetRelocationHandler LLVM_FINAL
|
||||
: public TargetRelocationHandler<X86_64ELFType> {
|
||||
public:
|
||||
X86_64TargetRelocationHandler(const X86_64TargetInfo &ti) : _targetInfo(ti) {}
|
||||
|
||||
virtual ErrorOr<void> applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
|
||||
const AtomLayout &,
|
||||
const Reference &)const;
|
||||
|
||||
private:
|
||||
const X86_64TargetInfo &_targetInfo;
|
||||
};
|
||||
|
||||
class X86_64TargetHandler LLVM_FINAL
|
||||
: public DefaultTargetHandler<X86_64ELFType> {
|
||||
public:
|
||||
X86_64TargetHandler(X86_64TargetInfo &targetInfo);
|
||||
|
||||
virtual const X86_64TargetRelocationHandler &getRelocationHandler() const {
|
||||
return _relocationHandler;
|
||||
}
|
||||
|
||||
private:
|
||||
X86_64TargetRelocationHandler _relocationHandler;
|
||||
};
|
||||
} // end namespace elf
|
||||
} // end namespace lld
|
||||
|
||||
#endif
|
|
@ -10,7 +10,7 @@
|
|||
#ifndef LLD_READER_WRITER_ELF_X86_64_TARGETINFO_H
|
||||
#define LLD_READER_WRITER_ELF_X86_64_TARGETINFO_H
|
||||
|
||||
#include "DefaultTargetHandler.h"
|
||||
#include "X86_64TargetHandler.h"
|
||||
|
||||
#include "lld/Core/LinkerOptions.h"
|
||||
#include "lld/ReaderWriter/ELFTargetInfo.h"
|
||||
|
@ -20,12 +20,13 @@
|
|||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
typedef llvm::object::ELFType<llvm::support::little, 8, false> X86_64ELFType;
|
||||
|
||||
class X86_64TargetInfo LLVM_FINAL : public ELFTargetInfo {
|
||||
public:
|
||||
X86_64TargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {
|
||||
_targetHandler = std::unique_ptr<TargetHandlerBase>(
|
||||
new DefaultTargetHandler<llvm::object::ELFType<llvm::support::little,
|
||||
8, false> >(*this));
|
||||
_targetHandler =
|
||||
std::unique_ptr<TargetHandlerBase>(new X86_64TargetHandler(*this));
|
||||
}
|
||||
|
||||
virtual uint64_t getPageSize() const { return 0x1000; }
|
||||
|
@ -47,7 +48,7 @@ public:
|
|||
virtual ErrorOr<std::string> stringFromRelocKind(int32_t kind) const;
|
||||
|
||||
};
|
||||
} // elf
|
||||
} // lld
|
||||
} // end namespace elf
|
||||
} // end namespace lld
|
||||
|
||||
#endif // LLD_READER_WRITER_ELF_X86_64_TARGETINFO_H
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue