mirror of
https://github.com/intel/llvm.git
synced 2026-01-18 16:50:51 +08:00
This patch changes the following:
* Use conventional naming for KindHandlers. * Add X86 relocation routines. * Use std::function instead of function pointers in _fixupHandler map. * Change _fixupHandler map from std::map to llvm::DenseMap. * Add simple testcase for x86 relocations. llvm-svn: 166700
This commit is contained in:
@@ -4,5 +4,6 @@ add_lld_library(lldELF
|
||||
ReferenceKinds.cpp
|
||||
HexagonReference.cpp
|
||||
PPCReference.cpp
|
||||
X86Reference.cpp
|
||||
WriterOptionsELF.cpp
|
||||
)
|
||||
|
||||
@@ -21,11 +21,11 @@ namespace lld {
|
||||
namespace elf {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// KindHandler_hexagon
|
||||
// HexagonKindHandler
|
||||
// TODO: more to do here
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
KindHandler_hexagon::~KindHandler_hexagon() {
|
||||
HexagonKindHandler::~HexagonKindHandler() {
|
||||
}
|
||||
|
||||
/// \brief The following relocation routines are derived from the
|
||||
@@ -36,70 +36,70 @@ KindHandler_hexagon::~KindHandler_hexagon() {
|
||||
/// S: Value of the symbol whose index resides in the relocation entry.
|
||||
|
||||
namespace hexagon {
|
||||
int reloc_NONE(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
|
||||
return KindHandler_hexagon::NoError;
|
||||
int relocNONE(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
|
||||
return HexagonKindHandler::NoError;
|
||||
}
|
||||
|
||||
/// \brief Word32_B22: 0x01ff3ffe : (S + A - P) >> 2 : Verify
|
||||
int reloc_B22_PCREL(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
|
||||
int relocB22PCREL(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
|
||||
int32_t result = (uint32_t)(((S + A) - P)>>2);
|
||||
if ((result < 0x200000) && (result > -0x200000)) {
|
||||
result = ((result<<1) & 0x3ffe) | ((result<<3) & 0x01ff0000);
|
||||
*reinterpret_cast<llvm::support::ulittle32_t *>(location) = result |
|
||||
*reinterpret_cast<llvm::support::ulittle32_t *>(location);
|
||||
return KindHandler_hexagon::NoError;
|
||||
return HexagonKindHandler::NoError;
|
||||
}
|
||||
return KindHandler_hexagon::Overflow;
|
||||
return HexagonKindHandler::Overflow;
|
||||
}
|
||||
|
||||
/// \brief Word32_B15: 0x00df20fe : (S + A - P) >> 2 : Verify
|
||||
int reloc_B15_PCREL(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
|
||||
int relocB15PCREL(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
|
||||
int32_t result = (uint32_t)(((S + A) - P)>>2);
|
||||
if ((result < 0x8000) && (result > -0x8000)) {
|
||||
result = ((result<<1) & 0x20fe) | ((result<<7) & 0x00df0000);
|
||||
*reinterpret_cast<llvm::support::ulittle32_t *>(location) = result |
|
||||
*reinterpret_cast<llvm::support::ulittle32_t *>(location);
|
||||
return KindHandler_hexagon::NoError;
|
||||
return HexagonKindHandler::NoError;
|
||||
}
|
||||
return KindHandler_hexagon::Overflow;
|
||||
return HexagonKindHandler::Overflow;
|
||||
}
|
||||
|
||||
/// \brief Word32_LO: 0x00c03fff : (S + A) : Truncate
|
||||
int reloc_LO16(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
|
||||
int relocLO16(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
|
||||
uint32_t result = (uint32_t)(S + A);
|
||||
result = ((result & 0x3fff) | ((result << 2) & 0x00c00000));
|
||||
*reinterpret_cast<llvm::support::ulittle32_t *>(location) = result |
|
||||
*reinterpret_cast<llvm::support::ulittle32_t *>(location);
|
||||
return KindHandler_hexagon::NoError;
|
||||
return HexagonKindHandler::NoError;
|
||||
}
|
||||
|
||||
/// \brief Word32_LO: 0x00c03fff : (S + A) >> 16 : Truncate
|
||||
int reloc_HI16(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
|
||||
int relocHI16(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
|
||||
uint32_t result = (uint32_t)((S + A)>>16);
|
||||
result = ((result & 0x3fff) | ((result << 2) & 0x00c00000));
|
||||
*reinterpret_cast<llvm::support::ulittle32_t *>(location) = result |
|
||||
*reinterpret_cast<llvm::support::ulittle32_t *>(location);
|
||||
return KindHandler_hexagon::NoError;
|
||||
return HexagonKindHandler::NoError;
|
||||
}
|
||||
|
||||
/// \brief Word32: 0xffffffff : (S + A) : Truncate
|
||||
int reloc_32(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
|
||||
int reloc32(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
|
||||
uint32_t result = (uint32_t)(S + A);
|
||||
*reinterpret_cast<llvm::support::ulittle32_t *>(location) = result |
|
||||
*reinterpret_cast<llvm::support::ulittle32_t *>(location);
|
||||
return KindHandler_hexagon::NoError;
|
||||
return HexagonKindHandler::NoError;
|
||||
}
|
||||
} // namespace hexagon
|
||||
|
||||
KindHandler_hexagon::KindHandler_hexagon(){
|
||||
_fixupHandler[llvm::ELF::R_HEX_B22_PCREL] = hexagon::reloc_B22_PCREL;
|
||||
_fixupHandler[llvm::ELF::R_HEX_B15_PCREL] = hexagon::reloc_B15_PCREL;
|
||||
_fixupHandler[llvm::ELF::R_HEX_LO16] = hexagon::reloc_LO16;
|
||||
_fixupHandler[llvm::ELF::R_HEX_HI16] = hexagon::reloc_HI16;
|
||||
_fixupHandler[llvm::ELF::R_HEX_32] = hexagon::reloc_32;
|
||||
HexagonKindHandler::HexagonKindHandler(){
|
||||
_fixupHandler[llvm::ELF::R_HEX_B22_PCREL] = hexagon::relocB22PCREL;
|
||||
_fixupHandler[llvm::ELF::R_HEX_B15_PCREL] = hexagon::relocB15PCREL;
|
||||
_fixupHandler[llvm::ELF::R_HEX_LO16] = hexagon::relocLO16;
|
||||
_fixupHandler[llvm::ELF::R_HEX_HI16] = hexagon::relocHI16;
|
||||
_fixupHandler[llvm::ELF::R_HEX_32] = hexagon::reloc32;
|
||||
}
|
||||
|
||||
Reference::Kind KindHandler_hexagon::stringToKind(StringRef str) {
|
||||
Reference::Kind HexagonKindHandler::stringToKind(StringRef str) {
|
||||
return llvm::StringSwitch<Reference::Kind>(str)
|
||||
.Case("none", none)
|
||||
.Case("R_HEX_B22_PCREL", llvm::ELF::R_HEX_B22_PCREL)
|
||||
@@ -110,7 +110,7 @@ Reference::Kind KindHandler_hexagon::stringToKind(StringRef str) {
|
||||
.Default(invalid);
|
||||
}
|
||||
|
||||
StringRef KindHandler_hexagon::kindToString(Reference::Kind kind) {
|
||||
StringRef HexagonKindHandler::kindToString(Reference::Kind kind) {
|
||||
switch (static_cast<int32_t>(kind)) {
|
||||
case llvm::ELF::R_HEX_B22_PCREL:
|
||||
return "R_HEX_B22_PCREL";
|
||||
@@ -127,34 +127,34 @@ StringRef KindHandler_hexagon::kindToString(Reference::Kind kind) {
|
||||
}
|
||||
}
|
||||
|
||||
bool KindHandler_hexagon::isCallSite(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: KindHandler_hexagon::isCallSite");
|
||||
bool HexagonKindHandler::isCallSite(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: HexagonKindHandler::isCallSite");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KindHandler_hexagon::isPointer(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: KindHandler_hexagon::isPointer");
|
||||
bool HexagonKindHandler::isPointer(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: HexagonKindHandler::isPointer");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KindHandler_hexagon::isLazyImmediate(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: KindHandler_hexagon::isLazyImmediate");
|
||||
bool HexagonKindHandler::isLazyImmediate(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: HexagonKindHandler::isLazyImmediate");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KindHandler_hexagon::isLazyTarget(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: KindHandler_hexagon::isLazyTarget");
|
||||
bool HexagonKindHandler::isLazyTarget(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: HexagonKindHandler::isLazyTarget");
|
||||
return false;
|
||||
}
|
||||
|
||||
void KindHandler_hexagon::applyFixup(int32_t reloc, uint64_t addend,
|
||||
void HexagonKindHandler::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);
|
||||
error = (_fixupHandler[reloc])(location,
|
||||
fixupAddress, targetAddress, addend);
|
||||
|
||||
switch ((RelocationError)error) {
|
||||
case NoError:
|
||||
|
||||
@@ -21,11 +21,11 @@ namespace lld {
|
||||
namespace elf {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// KindHandler_ppc
|
||||
// PPCKindHandler
|
||||
// TODO: more to do here
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
KindHandler_ppc::~KindHandler_ppc() {
|
||||
PPCKindHandler::~PPCKindHandler() {
|
||||
}
|
||||
|
||||
/// \brief The following relocation routines are derived from the
|
||||
@@ -36,35 +36,35 @@ KindHandler_ppc::~KindHandler_ppc() {
|
||||
/// S: Value of the symbol whose index resides in the relocation entry.
|
||||
|
||||
namespace ppc {
|
||||
int reloc_NONE(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
|
||||
return KindHandler_ppc::NoError;
|
||||
int relocNONE(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
|
||||
return PPCKindHandler::NoError;
|
||||
}
|
||||
|
||||
/// \brief low24 (S + A - P) >> 2 : Verify
|
||||
int reloc_B24_PCREL(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
|
||||
int relocB24PCREL(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
|
||||
int32_t result = (uint32_t)(((S + A) - P));
|
||||
if ((result < 0x1000000) && (result > -0x1000000)) {
|
||||
result &= ~-(0x1000000);
|
||||
*reinterpret_cast<llvm::support::ubig32_t *>(location) = result |
|
||||
*reinterpret_cast<llvm::support::ubig32_t *>(location);
|
||||
return KindHandler_ppc::NoError;
|
||||
return PPCKindHandler::NoError;
|
||||
}
|
||||
return KindHandler_ppc::Overflow;
|
||||
return PPCKindHandler::Overflow;
|
||||
}
|
||||
} // namespace ppc
|
||||
|
||||
KindHandler_ppc::KindHandler_ppc(llvm::support::endianness endian){
|
||||
_fixupHandler[llvm::ELF::R_PPC_REL24] = ppc::reloc_B24_PCREL;
|
||||
PPCKindHandler::PPCKindHandler(llvm::support::endianness endian){
|
||||
_fixupHandler[llvm::ELF::R_PPC_REL24] = ppc::relocB24PCREL;
|
||||
}
|
||||
|
||||
Reference::Kind KindHandler_ppc::stringToKind(StringRef str) {
|
||||
Reference::Kind PPCKindHandler::stringToKind(StringRef str) {
|
||||
return llvm::StringSwitch<Reference::Kind>(str)
|
||||
.Case("none", none)
|
||||
.Case("R_PPC_REL24", llvm::ELF::R_PPC_REL24)
|
||||
.Default(invalid);
|
||||
}
|
||||
|
||||
StringRef KindHandler_ppc::kindToString(Reference::Kind kind) {
|
||||
StringRef PPCKindHandler::kindToString(Reference::Kind kind) {
|
||||
switch ((int32_t)kind) {
|
||||
case llvm::ELF::R_PPC_REL24:
|
||||
return "R_PPC_REL24";
|
||||
@@ -73,34 +73,34 @@ StringRef KindHandler_ppc::kindToString(Reference::Kind kind) {
|
||||
}
|
||||
}
|
||||
|
||||
bool KindHandler_ppc::isCallSite(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: KindHandler_ppc::isCallSite");
|
||||
bool PPCKindHandler::isCallSite(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: PPCKindHandler::isCallSite");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KindHandler_ppc::isPointer(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: KindHandler_ppc::isPointer");
|
||||
bool PPCKindHandler::isPointer(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: PPCKindHandler::isPointer");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KindHandler_ppc::isLazyImmediate(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: KindHandler_ppc::isLazyImmediate");
|
||||
bool PPCKindHandler::isLazyImmediate(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: PPCKindHandler::isLazyImmediate");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KindHandler_ppc::isLazyTarget(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: KindHandler_ppc::isLazyTarget");
|
||||
bool PPCKindHandler::isLazyTarget(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: PPCKindHandler::isLazyTarget");
|
||||
return false;
|
||||
}
|
||||
|
||||
void KindHandler_ppc::applyFixup(int32_t reloc, uint64_t addend,
|
||||
void PPCKindHandler::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);
|
||||
error = (_fixupHandler[reloc])(location,
|
||||
fixupAddress, targetAddress, addend);
|
||||
|
||||
switch ((RelocationError)error) {
|
||||
case NoError:
|
||||
|
||||
@@ -32,66 +32,16 @@ std::unique_ptr<KindHandler> KindHandler::makeHandler(uint16_t arch,
|
||||
llvm::support::endianness endian) {
|
||||
switch(arch) {
|
||||
case llvm::ELF::EM_HEXAGON:
|
||||
return std::unique_ptr<KindHandler>(new KindHandler_hexagon());
|
||||
return std::unique_ptr<KindHandler>(new HexagonKindHandler());
|
||||
case llvm::ELF::EM_386:
|
||||
return std::unique_ptr<KindHandler>(new KindHandler_x86());
|
||||
return std::unique_ptr<KindHandler>(new X86KindHandler());
|
||||
case llvm::ELF::EM_PPC:
|
||||
return std::unique_ptr<KindHandler>(new KindHandler_ppc(endian));
|
||||
return std::unique_ptr<KindHandler>(new PPCKindHandler(endian));
|
||||
default:
|
||||
llvm_unreachable("arch not supported");
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// KindHandler_x86
|
||||
// TODO: more to do here
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
KindHandler_x86::~KindHandler_x86() {}
|
||||
|
||||
Reference::Kind KindHandler_x86::stringToKind(StringRef str) {
|
||||
return llvm::StringSwitch<Reference::Kind>(str)
|
||||
.Case("none", none)
|
||||
.Default(invalid);
|
||||
}
|
||||
|
||||
StringRef KindHandler_x86::kindToString(Reference::Kind kind) {
|
||||
switch ( (Kinds)kind ) {
|
||||
case invalid:
|
||||
return "invalid";
|
||||
case none:
|
||||
return "none";
|
||||
}
|
||||
llvm_unreachable("invalid x86 Reference kind");
|
||||
}
|
||||
|
||||
bool KindHandler_x86::isCallSite(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: KindHandler_x86::isCallSite");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KindHandler_x86::isPointer(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: KindHandler_x86::isPointer");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KindHandler_x86::isLazyImmediate(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: KindHandler_x86::isLazyImmediate");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KindHandler_x86::isLazyTarget(Kind kind) {
|
||||
llvm_unreachable("Unimplemented: KindHandler_x86::isLazyTarget");
|
||||
return false;
|
||||
}
|
||||
|
||||
void KindHandler_x86::applyFixup(int32_t reloc, uint64_t addend,
|
||||
uint8_t *location, uint64_t fixupAddress,
|
||||
uint64_t targetAddress) {
|
||||
// TODO: Add reloc funcs for X86
|
||||
return;
|
||||
}
|
||||
|
||||
} // namespace elf
|
||||
} // namespace lld
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
class KindHandler_hexagon : public KindHandler {
|
||||
class HexagonKindHandler : public KindHandler {
|
||||
public:
|
||||
|
||||
// Note: Reference::Kinds are a another representation of
|
||||
@@ -70,8 +70,8 @@ public:
|
||||
Overflow
|
||||
};
|
||||
|
||||
virtual ~KindHandler_hexagon();
|
||||
KindHandler_hexagon();
|
||||
virtual ~HexagonKindHandler();
|
||||
HexagonKindHandler();
|
||||
virtual Kind stringToKind(StringRef str);
|
||||
virtual StringRef kindToString(Kind);
|
||||
virtual bool isCallSite(Kind);
|
||||
@@ -82,22 +82,29 @@ public:
|
||||
uint8_t *location,
|
||||
uint64_t fixupAddress, uint64_t targetAddress);
|
||||
|
||||
// A map is used here and in the other handlers but if performace overhead
|
||||
// becomes an issue this could be implemented as an array of function pointers.
|
||||
private:
|
||||
std::map<int32_t,
|
||||
int (*)(uint8_t *location, uint64_t fixupAddress,
|
||||
uint64_t targetAddress, uint64_t addend)> _fixupHandler;
|
||||
llvm::DenseMap<int32_t,
|
||||
std::function <int (uint8_t *location, uint64_t fixupAddress,
|
||||
uint64_t targetAddress, uint64_t addend)> > _fixupHandler;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class KindHandler_x86 : public KindHandler {
|
||||
class X86KindHandler : public KindHandler {
|
||||
public:
|
||||
enum Kinds {
|
||||
invalid, // used to denote an error creating a Reference
|
||||
none,
|
||||
};
|
||||
|
||||
virtual ~KindHandler_x86();
|
||||
enum RelocationError {
|
||||
NoError,
|
||||
};
|
||||
|
||||
virtual ~X86KindHandler();
|
||||
X86KindHandler();
|
||||
virtual Kind stringToKind(StringRef str);
|
||||
virtual StringRef kindToString(Kind);
|
||||
virtual bool isCallSite(Kind);
|
||||
@@ -107,9 +114,13 @@ public:
|
||||
virtual void applyFixup(int32_t reloc, uint64_t addend, uint8_t *location,
|
||||
uint64_t fixupAddress, uint64_t targetAddress);
|
||||
|
||||
private:
|
||||
llvm::DenseMap<int32_t,
|
||||
std::function <int (uint8_t *location, uint64_t fixupAddress,
|
||||
uint64_t targetAddress, uint64_t addend)> > _fixupHandler;
|
||||
};
|
||||
|
||||
class KindHandler_ppc : public KindHandler {
|
||||
class PPCKindHandler : public KindHandler {
|
||||
public:
|
||||
|
||||
// Note: Reference::Kinds are a another representation of
|
||||
@@ -127,8 +138,8 @@ public:
|
||||
Overflow
|
||||
};
|
||||
|
||||
virtual ~KindHandler_ppc();
|
||||
KindHandler_ppc(llvm::support::endianness endian);
|
||||
virtual ~PPCKindHandler();
|
||||
PPCKindHandler(llvm::support::endianness endian);
|
||||
virtual Kind stringToKind(StringRef str);
|
||||
virtual StringRef kindToString(Kind);
|
||||
virtual bool isCallSite(Kind);
|
||||
@@ -140,9 +151,9 @@ public:
|
||||
uint64_t fixupAddress, uint64_t targetAddress);
|
||||
|
||||
private:
|
||||
std::map<int32_t,
|
||||
int (*)(uint8_t *location, uint64_t fixupAddress,
|
||||
uint64_t targetAddress, uint64_t addend)> _fixupHandler;
|
||||
llvm::DenseMap<int32_t,
|
||||
std::function <int (uint8_t *location, uint64_t fixupAddress,
|
||||
uint64_t targetAddress, uint64_t addend)> > _fixupHandler;
|
||||
|
||||
};
|
||||
|
||||
|
||||
121
lld/lib/ReaderWriter/ELF/X86Reference.cpp
Normal file
121
lld/lib/ReaderWriter/ELF/X86Reference.cpp
Normal file
@@ -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
|
||||
BIN
lld/test/elf/Inputs/reloc-xb.x86
Normal file
BIN
lld/test/elf/Inputs/reloc-xb.x86
Normal file
Binary file not shown.
BIN
lld/test/elf/Inputs/reloc-xt.x86
Normal file
BIN
lld/test/elf/Inputs/reloc-xt.x86
Normal file
Binary file not shown.
42
lld/test/elf/x86.objtxt
Normal file
42
lld/test/elf/x86.objtxt
Normal file
@@ -0,0 +1,42 @@
|
||||
# Source for input file: reloc-xb.x86
|
||||
# xb.S:
|
||||
# .section .text, "ax", @progbits
|
||||
# .align 0x4
|
||||
# .globl _start
|
||||
# _start:
|
||||
# .globl back
|
||||
# back:
|
||||
# call target
|
||||
#
|
||||
# Source for input file: reloc-xt.x86
|
||||
# xt.S:
|
||||
# .section .text, "ax", @progbits
|
||||
#
|
||||
# .globl target
|
||||
# target:
|
||||
# call back
|
||||
#
|
||||
# Assembled with: "as --32"
|
||||
|
||||
RUN: lld-core -reader ELF -arch=i386 %p/Inputs/reloc-xb.x86 %p/Inputs/reloc-xt.x86 | FileCheck %s -check-prefix x86-yaml
|
||||
|
||||
x86-yaml: - name: back
|
||||
x86-yaml: scope: global
|
||||
x86-yaml: type: code
|
||||
x86-yaml: section-name: .text
|
||||
x86-yaml: content: [ E8, FC, FF, FF, FF ]
|
||||
x86-yaml: fixups:
|
||||
x86-yaml: - offset: 1
|
||||
x86-yaml: kind: call32
|
||||
x86-yaml: target: target
|
||||
|
||||
x86-yaml: - name: target
|
||||
x86-yaml: scope: global
|
||||
x86-yaml: type: code
|
||||
x86-yaml: section-name: .text
|
||||
x86-yaml: content: [ E8, FC, FF, FF, FF ]
|
||||
x86-yaml: fixups:
|
||||
x86-yaml: - offset: 1
|
||||
x86-yaml: kind: call32
|
||||
x86-yaml: target: back
|
||||
|
||||
Reference in New Issue
Block a user