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:
parent
eb538abfbd
commit
c40108858d
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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<
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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 {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue