mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-12 06:06:32 +00:00
The ELF relocation record format is different for N64
which many Mips 64 ABIs use than for O64 which many if not all other target ABIs use. Most architectures have the following 64 bit relocation record format: typedef struct { Elf64_Addr r_offset; /* Address of reference */ Elf64_Xword r_info; /* Symbol index and type of relocation */ } Elf64_Rel; typedef struct { Elf64_Addr r_offset; Elf64_Xword r_info; Elf64_Sxword r_addend; } Elf64_Rela; Whereas N64 has the following format: typedef struct { Elf64_Addr r_offset;/* Address of reference */ Elf64_Word r_sym; /* Symbol index */ Elf64_Byte r_ssym; /* Special symbol */ Elf64_Byte r_type3; /* Relocation type */ Elf64_Byte r_type2; /* Relocation type */ Elf64_Byte r_type; /* Relocation type */ } Elf64_Rel; typedef struct { Elf64_Addr r_offset;/* Address of reference */ Elf64_Word r_sym; /* Symbol index */ Elf64_Byte r_ssym; /* Special symbol */ Elf64_Byte r_type3; /* Relocation type */ Elf64_Byte r_type2; /* Relocation type */ Elf64_Byte r_type; /* Relocation type */ Elf64_Sxword r_addend; } Elf64_Rela; The structure is the same size, but the r_info data element is now 5 separate elements. Besides the content aspects, endian byte reordering will be different for the area with each element being endianized separately. I treat this as generic and continue to pass r_type as an integer masking and unmasking the byte sized N64 values for N64 mode. I've implemented this and it causes no affect on other current targets. This passes make check. Jack git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@159299 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e2529dc91e
commit
93ee286e8d
@ -54,11 +54,13 @@ class MCELFObjectTargetWriter {
|
||||
const uint16_t EMachine;
|
||||
const unsigned HasRelocationAddend : 1;
|
||||
const unsigned Is64Bit : 1;
|
||||
const unsigned IsN64 : 1;
|
||||
|
||||
protected:
|
||||
|
||||
MCELFObjectTargetWriter(bool Is64Bit_, uint8_t OSABI_,
|
||||
uint16_t EMachine_, bool HasRelocationAddend_);
|
||||
uint16_t EMachine_, bool HasRelocationAddend,
|
||||
bool IsN64=false);
|
||||
|
||||
public:
|
||||
static uint8_t getOSABI(Triple::OSType OSType) {
|
||||
@ -95,7 +97,47 @@ public:
|
||||
uint16_t getEMachine() { return EMachine; }
|
||||
bool hasRelocationAddend() { return HasRelocationAddend; }
|
||||
bool is64Bit() const { return Is64Bit; }
|
||||
bool isN64() const { return IsN64; }
|
||||
/// @}
|
||||
|
||||
// Instead of changing everyone's API we pack the N64 Type fields
|
||||
// into the existing 32 bit data unsigned.
|
||||
#define R_TYPE_SHIFT 0
|
||||
#define R_TYPE_MASK 0xffffff00
|
||||
#define R_TYPE2_SHIFT 8
|
||||
#define R_TYPE2_MASK 0xffff00ff
|
||||
#define R_TYPE3_SHIFT 16
|
||||
#define R_TYPE3_MASK 0xff00ffff
|
||||
#define R_SSYM_SHIFT 24
|
||||
#define R_SSYM_MASK 0x00ffffff
|
||||
|
||||
// N64 relocation type accessors
|
||||
unsigned getRType(uint32_t Type) const {
|
||||
return (unsigned)((Type >> R_TYPE_SHIFT) & 0xff);
|
||||
}
|
||||
unsigned getRType2(uint32_t Type) const {
|
||||
return (unsigned)((Type >> R_TYPE2_SHIFT) & 0xff);
|
||||
}
|
||||
unsigned getRType3(uint32_t Type) const {
|
||||
return (unsigned)((Type >> R_TYPE3_SHIFT) & 0xff);
|
||||
}
|
||||
unsigned getRSsym(uint32_t Type) const {
|
||||
return (unsigned)((Type >> R_SSYM_SHIFT) & 0xff);
|
||||
}
|
||||
|
||||
// N64 relocation type setting
|
||||
unsigned setRType(unsigned Value, unsigned Type) const {
|
||||
return ((Type & R_TYPE_MASK) | ((Value & 0xff) << R_TYPE_SHIFT));
|
||||
}
|
||||
unsigned setRType2(unsigned Value, unsigned Type) const {
|
||||
return (Type & R_TYPE2_MASK) | ((Value & 0xff) << R_TYPE2_SHIFT);
|
||||
}
|
||||
unsigned setRType3(unsigned Value, unsigned Type) const {
|
||||
return (Type & R_TYPE3_MASK) | ((Value & 0xff) << R_TYPE3_SHIFT);
|
||||
}
|
||||
unsigned setRSsym(unsigned Value, unsigned Type) const {
|
||||
return (Type & R_SSYM_MASK) | ((Value & 0xff) << R_SSYM_SHIFT);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Construct a new ELF writer instance.
|
||||
|
@ -1061,11 +1061,19 @@ void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm,
|
||||
entry.Index += LocalSymbolData.size();
|
||||
if (is64Bit()) {
|
||||
String64(*F, entry.r_offset);
|
||||
if (TargetObjectWriter->isN64()) {
|
||||
String32(*F, entry.Index);
|
||||
|
||||
struct ELF::Elf64_Rela ERE64;
|
||||
ERE64.setSymbolAndType(entry.Index, entry.Type);
|
||||
String64(*F, ERE64.r_info);
|
||||
|
||||
String8(*F, TargetObjectWriter->getRSsym(entry.Type));
|
||||
String8(*F, TargetObjectWriter->getRType3(entry.Type));
|
||||
String8(*F, TargetObjectWriter->getRType2(entry.Type));
|
||||
String8(*F, TargetObjectWriter->getRType(entry.Type));
|
||||
}
|
||||
else {
|
||||
struct ELF::Elf64_Rela ERE64;
|
||||
ERE64.setSymbolAndType(entry.Index, entry.Type);
|
||||
String64(*F, ERE64.r_info);
|
||||
}
|
||||
if (hasRelocationAddend())
|
||||
String64(*F, entry.r_addend);
|
||||
} else {
|
||||
|
@ -15,9 +15,11 @@ using namespace llvm;
|
||||
MCELFObjectTargetWriter::MCELFObjectTargetWriter(bool Is64Bit_,
|
||||
uint8_t OSABI_,
|
||||
uint16_t EMachine_,
|
||||
bool HasRelocationAddend_)
|
||||
bool HasRelocationAddend_,
|
||||
bool IsN64_)
|
||||
: OSABI(OSABI_), EMachine(EMachine_),
|
||||
HasRelocationAddend(HasRelocationAddend_), Is64Bit(Is64Bit_) {
|
||||
HasRelocationAddend(HasRelocationAddend_), Is64Bit(Is64Bit_),
|
||||
IsN64(IsN64_){
|
||||
}
|
||||
|
||||
/// Default e_flags = 0
|
||||
|
@ -34,7 +34,7 @@ namespace {
|
||||
|
||||
class MipsELFObjectWriter : public MCELFObjectTargetWriter {
|
||||
public:
|
||||
MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI);
|
||||
MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, bool _isN64);
|
||||
|
||||
virtual ~MipsELFObjectWriter();
|
||||
|
||||
@ -52,9 +52,11 @@ namespace {
|
||||
};
|
||||
}
|
||||
|
||||
MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI)
|
||||
MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI,
|
||||
bool _isN64)
|
||||
: MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS,
|
||||
/*HasRelocationAddend*/ false) {}
|
||||
/*HasRelocationAddend*/ false,
|
||||
/*IsN64*/ _isN64) {}
|
||||
|
||||
MipsELFObjectWriter::~MipsELFObjectWriter() {}
|
||||
|
||||
@ -149,7 +151,6 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
|
||||
Type = ELF::R_MIPS_PC16;
|
||||
break;
|
||||
}
|
||||
|
||||
return Type;
|
||||
}
|
||||
|
||||
@ -184,7 +185,7 @@ static int CompareOffset(const RelEntry &R0, const RelEntry &R1) {
|
||||
|
||||
void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm,
|
||||
std::vector<ELFRelocationEntry> &Relocs) {
|
||||
// Call the defualt function first. Relocations are sorted in descending
|
||||
// Call the default function first. Relocations are sorted in descending
|
||||
// order of r_offset.
|
||||
MCELFObjectTargetWriter::sortRelocs(Asm, Relocs);
|
||||
|
||||
@ -244,6 +245,7 @@ MCObjectWriter *llvm::createMipsELFObjectWriter(raw_ostream &OS,
|
||||
uint8_t OSABI,
|
||||
bool IsLittleEndian,
|
||||
bool Is64Bit) {
|
||||
MCELFObjectTargetWriter *MOTW = new MipsELFObjectWriter(Is64Bit, OSABI);
|
||||
MCELFObjectTargetWriter *MOTW = new MipsELFObjectWriter(Is64Bit, OSABI,
|
||||
(Is64Bit) ? true : false);
|
||||
return createELFObjectWriter(MOTW, OS, IsLittleEndian);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user