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:
Sid Manning
2012-10-25 17:53:04 +00:00
parent 8fe3a6bda4
commit 823e8bb7be
9 changed files with 249 additions and 124 deletions

View File

@@ -4,5 +4,6 @@ add_lld_library(lldELF
ReferenceKinds.cpp
HexagonReference.cpp
PPCReference.cpp
X86Reference.cpp
WriterOptionsELF.cpp
)

View File

@@ -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:

View File

@@ -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:

View File

@@ -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

View File

@@ -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;
};

View 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

Binary file not shown.

Binary file not shown.

42
lld/test/elf/x86.objtxt Normal file
View 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