forked from OSchip/llvm-project
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 "Target.h"
|
||||
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::ELF;
|
||||
using namespace llvm::object;
|
||||
|
@ -26,57 +24,6 @@ template <class ELFT>
|
|||
InputSection<ELFT>::InputSection(ObjectFile<ELFT> *F, const Elf_Shdr *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 <bool isRela>
|
||||
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;
|
||||
|
||||
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>
|
||||
void relocate(uint8_t *Buf,
|
||||
llvm::iterator_range<
|
||||
|
|
|
@ -40,7 +40,9 @@ void SymbolTable::addFile(std::unique_ptr<InputFile> File) {
|
|||
}
|
||||
|
||||
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());
|
||||
else
|
||||
Target.reset(new X86TargetInfo());
|
||||
|
|
|
@ -8,12 +8,15 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Target.h"
|
||||
#include "Error.h"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
using namespace llvm::ELF;
|
||||
|
||||
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; }
|
||||
|
||||
void X86_64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
|
||||
|
@ -96,5 +120,48 @@ bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type) const {
|
|||
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;
|
||||
virtual bool relocNeedsGot(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();
|
||||
|
||||
protected:
|
||||
|
@ -36,6 +39,8 @@ public:
|
|||
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;
|
||||
};
|
||||
|
||||
class X86_64TargetInfo final : public TargetInfo {
|
||||
|
@ -45,6 +50,19 @@ public:
|
|||
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;
|
||||
};
|
||||
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue