Move relocation processing to Target.

I will add a couple of ppc64 relocs in the next patches.

llvm-svn: 248319
This commit is contained in:
Rafael Espindola 2015-09-22 20:54:08 +00:00
parent eb538abfbd
commit c40108858d
5 changed files with 90 additions and 60 deletions

View File

@ -13,8 +13,6 @@
#include "OutputSections.h" #include "OutputSections.h"
#include "Target.h" #include "Target.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm; using namespace llvm;
using namespace llvm::ELF; using namespace llvm::ELF;
using namespace llvm::object; using namespace llvm::object;
@ -26,57 +24,6 @@ template <class ELFT>
InputSection<ELFT>::InputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header) InputSection<ELFT>::InputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header)
: File(F), Header(Header) {} : File(F), Header(Header) {}
template <class ELFT>
void InputSection<ELFT>::relocateOne(uint8_t *Buf, const Elf_Rel &Rel,
uint32_t Type, uintX_t BaseAddr,
uintX_t SymVA) {
uintX_t Offset = Rel.r_offset;
uint8_t *Location = Buf + Offset;
uint32_t Addend = *(support::ulittle32_t *)Location;
switch (Type) {
case R_386_PC32:
support::endian::write32le(Location, SymVA + Addend - (BaseAddr + Offset));
break;
case R_386_32:
support::endian::write32le(Location, SymVA + Addend);
break;
default:
llvm::errs() << Twine("unrecognized reloc ") + Twine(Type) << '\n';
break;
}
}
template <class ELFT>
void InputSection<ELFT>::relocateOne(uint8_t *Buf, const Elf_Rela &Rel,
uint32_t Type, uintX_t BaseAddr,
uintX_t SymVA) {
uintX_t Offset = Rel.r_offset;
uint8_t *Location = Buf + Offset;
switch (Type) {
case R_X86_64_PC32:
support::endian::write32le(Location,
SymVA + Rel.r_addend - (BaseAddr + Offset));
break;
case R_X86_64_64:
support::endian::write64le(Location, SymVA + Rel.r_addend);
break;
case R_X86_64_32: {
case R_X86_64_32S:
uint64_t VA = SymVA + Rel.r_addend;
if (Type == R_X86_64_32 && !isUInt<32>(VA))
error("R_X86_64_32 out of range");
else if (!isInt<32>(VA))
error("R_X86_64_32S out of range");
support::endian::write32le(Location, VA);
break;
}
default:
llvm::errs() << Twine("unrecognized reloc ") + Twine(Type) << '\n';
break;
}
}
template <class ELFT> template <class ELFT>
template <bool isRela> template <bool isRela>
void InputSection<ELFT>::relocate( void InputSection<ELFT>::relocate(
@ -134,7 +81,8 @@ void InputSection<ELFT>::relocate(
} }
} }
relocateOne(Buf, RI, Type, BaseAddr, SymVA); Target->relocateOne(Buf, reinterpret_cast<const void *>(&RI), Type,
BaseAddr, SymVA);
} }
} }

View File

@ -60,11 +60,6 @@ public:
SmallVector<const Elf_Shdr *, 1> RelocSections; SmallVector<const Elf_Shdr *, 1> RelocSections;
private: private:
void relocateOne(uint8_t *Buf, const Elf_Rela &Rel, uint32_t Type,
uintX_t BaseAddr, uintX_t SymVA);
void relocateOne(uint8_t *Buf, const Elf_Rel &Rel, uint32_t Type,
uintX_t BaseAddr, uintX_t SymVA);
template <bool isRela> template <bool isRela>
void relocate(uint8_t *Buf, void relocate(uint8_t *Buf,
llvm::iterator_range< llvm::iterator_range<

View File

@ -40,7 +40,9 @@ void SymbolTable::addFile(std::unique_ptr<InputFile> File) {
} }
template <class ELFT> void SymbolTable::init(uint16_t EMachine) { template <class ELFT> void SymbolTable::init(uint16_t EMachine) {
if (EMachine == EM_X86_64) if (EMachine == EM_PPC64)
Target.reset(new PPC64TargetInfo());
else if (EMachine == EM_X86_64)
Target.reset(new X86_64TargetInfo()); Target.reset(new X86_64TargetInfo());
else else
Target.reset(new X86TargetInfo()); Target.reset(new X86TargetInfo());

View File

@ -8,12 +8,15 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Target.h" #include "Target.h"
#include "Error.h"
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/Object/ELF.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"
#include "llvm/Support/ELF.h" #include "llvm/Support/ELF.h"
using namespace llvm; using namespace llvm;
using namespace llvm::object;
using namespace llvm::ELF; using namespace llvm::ELF;
namespace lld { namespace lld {
@ -59,6 +62,27 @@ bool X86TargetInfo::relocNeedsPlt(uint32_t Type) const {
} }
} }
void X86TargetInfo::relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
uint64_t BaseAddr, uint64_t SymVA) const {
typedef ELFFile<ELF32LE>::Elf_Rel Elf_Rel;
auto &Rel = *reinterpret_cast<const Elf_Rel *>(RelP);
uint32_t Offset = Rel.r_offset;
uint8_t *Location = Buf + Offset;
uint32_t Addend = *(support::ulittle32_t *)Location;
switch (Type) {
case R_386_PC32:
support::endian::write32le(Location, SymVA + Addend - (BaseAddr + Offset));
break;
case R_386_32:
support::endian::write32le(Location, SymVA + Addend);
break;
default:
error(Twine("unrecognized reloc ") + Twine(Type));
break;
}
}
X86_64TargetInfo::X86_64TargetInfo() { PCRelReloc = R_X86_64_PC32; } X86_64TargetInfo::X86_64TargetInfo() { PCRelReloc = R_X86_64_PC32; }
void X86_64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr, void X86_64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
@ -96,5 +120,48 @@ bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type) const {
return true; return true;
} }
} }
void X86_64TargetInfo::relocateOne(uint8_t *Buf, const void *RelP,
uint32_t Type, uint64_t BaseAddr,
uint64_t SymVA) const {
typedef ELFFile<ELF64LE>::Elf_Rela Elf_Rela;
auto &Rel = *reinterpret_cast<const Elf_Rela *>(RelP);
uint64_t Offset = Rel.r_offset;
uint8_t *Location = Buf + Offset;
switch (Type) {
case R_X86_64_PC32:
support::endian::write32le(Location,
SymVA + Rel.r_addend - (BaseAddr + Offset));
break;
case R_X86_64_64:
support::endian::write64le(Location, SymVA + Rel.r_addend);
break;
case R_X86_64_32: {
case R_X86_64_32S:
uint64_t VA = SymVA + Rel.r_addend;
if (Type == R_X86_64_32 && !isUInt<32>(VA))
error("R_X86_64_32 out of range");
else if (!isInt<32>(VA))
error("R_X86_64_32S out of range");
support::endian::write32le(Location, VA);
break;
}
default:
error(Twine("unrecognized reloc ") + Twine(Type));
break;
}
}
PPC64TargetInfo::PPC64TargetInfo() {
// PCRelReloc = FIXME
}
void PPC64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const {}
bool PPC64TargetInfo::relocNeedsGot(uint32_t Type) const { return false; }
bool PPC64TargetInfo::relocNeedsPlt(uint32_t Type) const { return false; }
void PPC64TargetInfo::relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
uint64_t BaseAddr, uint64_t SymVA) const {}
} }
} }

View File

@ -23,6 +23,9 @@ public:
uint64_t PltEntryAddr) const = 0; uint64_t PltEntryAddr) const = 0;
virtual bool relocNeedsGot(uint32_t Type) const = 0; virtual bool relocNeedsGot(uint32_t Type) const = 0;
virtual bool relocNeedsPlt(uint32_t Type) const = 0; virtual bool relocNeedsPlt(uint32_t Type) const = 0;
virtual void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
uint64_t BaseAddr, uint64_t SymVA) const = 0;
virtual ~TargetInfo(); virtual ~TargetInfo();
protected: protected:
@ -36,6 +39,8 @@ public:
uint64_t PltEntryAddr) const override; uint64_t PltEntryAddr) const override;
bool relocNeedsGot(uint32_t Type) const override; bool relocNeedsGot(uint32_t Type) const override;
bool relocNeedsPlt(uint32_t Type) const override; bool relocNeedsPlt(uint32_t Type) const override;
void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
uint64_t BaseAddr, uint64_t SymVA) const override;
}; };
class X86_64TargetInfo final : public TargetInfo { class X86_64TargetInfo final : public TargetInfo {
@ -45,6 +50,19 @@ public:
uint64_t PltEntryAddr) const override; uint64_t PltEntryAddr) const override;
bool relocNeedsGot(uint32_t Type) const override; bool relocNeedsGot(uint32_t Type) const override;
bool relocNeedsPlt(uint32_t Type) const override; bool relocNeedsPlt(uint32_t Type) const override;
void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
uint64_t BaseAddr, uint64_t SymVA) const override;
};
class PPC64TargetInfo final : public TargetInfo {
public:
PPC64TargetInfo();
void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
bool relocNeedsGot(uint32_t Type) const override;
bool relocNeedsPlt(uint32_t Type) const override;
void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
uint64_t BaseAddr, uint64_t SymVA) const override;
}; };
extern std::unique_ptr<TargetInfo> Target; extern std::unique_ptr<TargetInfo> Target;