forked from OSchip/llvm-project
Implement the "mips endian" for r_info.
Normally r_info is just a 32 of 64 bit number matching the endian of the rest of the file. Unfortunately, mips 64 bit little endian is special: The top 32 bits are a little endian number and the following 32 are a big endian one. llvm-svn: 178694
This commit is contained in:
parent
13de1566d0
commit
2025e8b820
|
@ -330,6 +330,14 @@ struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, false> {
|
||||||
MaxAlign LLVM_ELF_COMMA false>)
|
MaxAlign LLVM_ELF_COMMA false>)
|
||||||
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
|
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
|
||||||
Elf_Word r_info; // Symbol table index and type of relocation to apply
|
Elf_Word r_info; // Symbol table index and type of relocation to apply
|
||||||
|
|
||||||
|
uint32_t getRInfo(bool isMips64EL) const {
|
||||||
|
assert(!isMips64EL);
|
||||||
|
return r_info;
|
||||||
|
}
|
||||||
|
void setRInfo(uint32_t R) {
|
||||||
|
r_info = R;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<template<endianness, std::size_t, bool> class ELFT,
|
template<template<endianness, std::size_t, bool> class ELFT,
|
||||||
|
@ -339,6 +347,22 @@ struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, false> {
|
||||||
MaxAlign LLVM_ELF_COMMA true>)
|
MaxAlign LLVM_ELF_COMMA true>)
|
||||||
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
|
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
|
||||||
Elf_Xword r_info; // Symbol table index and type of relocation to apply
|
Elf_Xword r_info; // Symbol table index and type of relocation to apply
|
||||||
|
|
||||||
|
uint64_t getRInfo(bool isMips64EL) const {
|
||||||
|
uint64_t t = r_info;
|
||||||
|
if (!isMips64EL)
|
||||||
|
return t;
|
||||||
|
// Mip64 little endian has a "special" encoding of r_info. Instead of one
|
||||||
|
// 64 bit little endian number, it is a little ending 32 bit number followed
|
||||||
|
// by a 32 bit big endian number.
|
||||||
|
return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) |
|
||||||
|
((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff);
|
||||||
|
return r_info;
|
||||||
|
}
|
||||||
|
void setRInfo(uint64_t R) {
|
||||||
|
// FIXME: Add mips64el support.
|
||||||
|
r_info = R;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<template<endianness, std::size_t, bool> class ELFT,
|
template<template<endianness, std::size_t, bool> class ELFT,
|
||||||
|
@ -349,6 +373,14 @@ struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, true> {
|
||||||
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
|
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
|
||||||
Elf_Word r_info; // Symbol table index and type of relocation to apply
|
Elf_Word r_info; // Symbol table index and type of relocation to apply
|
||||||
Elf_Sword r_addend; // Compute value for relocatable field by adding this
|
Elf_Sword r_addend; // Compute value for relocatable field by adding this
|
||||||
|
|
||||||
|
uint32_t getRInfo(bool isMips64EL) const {
|
||||||
|
assert(!isMips64EL);
|
||||||
|
return r_info;
|
||||||
|
}
|
||||||
|
void setRInfo(uint32_t R) {
|
||||||
|
r_info = R;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<template<endianness, std::size_t, bool> class ELFT,
|
template<template<endianness, std::size_t, bool> class ELFT,
|
||||||
|
@ -359,6 +391,21 @@ struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, true> {
|
||||||
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
|
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
|
||||||
Elf_Xword r_info; // Symbol table index and type of relocation to apply
|
Elf_Xword r_info; // Symbol table index and type of relocation to apply
|
||||||
Elf_Sxword r_addend; // Compute value for relocatable field by adding this.
|
Elf_Sxword r_addend; // Compute value for relocatable field by adding this.
|
||||||
|
|
||||||
|
uint64_t getRInfo(bool isMips64EL) const {
|
||||||
|
// Mip64 little endian has a "special" encoding of r_info. Instead of one
|
||||||
|
// 64 bit little endian number, it is a little ending 32 bit number followed
|
||||||
|
// by a 32 bit big endian number.
|
||||||
|
uint64_t t = r_info;
|
||||||
|
if (!isMips64EL)
|
||||||
|
return t;
|
||||||
|
return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) |
|
||||||
|
((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff);
|
||||||
|
}
|
||||||
|
void setRInfo(uint64_t R) {
|
||||||
|
// FIXME: Add mips64el support.
|
||||||
|
r_info = R;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class ELFT, bool isRela>
|
template<class ELFT, bool isRela>
|
||||||
|
@ -368,20 +415,21 @@ template<template<endianness, std::size_t, bool> class ELFT,
|
||||||
endianness TargetEndianness, std::size_t MaxAlign, bool isRela>
|
endianness TargetEndianness, std::size_t MaxAlign, bool isRela>
|
||||||
struct Elf_Rel_Impl<ELFT<TargetEndianness, MaxAlign, true>, isRela>
|
struct Elf_Rel_Impl<ELFT<TargetEndianness, MaxAlign, true>, isRela>
|
||||||
: Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, isRela> {
|
: Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, isRela> {
|
||||||
using Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, isRela>::r_info;
|
|
||||||
LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA
|
LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA
|
||||||
MaxAlign LLVM_ELF_COMMA true>)
|
MaxAlign LLVM_ELF_COMMA true>)
|
||||||
|
|
||||||
// These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE,
|
// These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE,
|
||||||
// and ELF64_R_INFO macros defined in the ELF specification:
|
// and ELF64_R_INFO macros defined in the ELF specification:
|
||||||
uint32_t getSymbol() const { return (uint32_t) (r_info >> 32); }
|
uint32_t getSymbol(bool isMips64EL) const {
|
||||||
uint32_t getType() const {
|
return (uint32_t) (this->getRInfo(isMips64EL) >> 32);
|
||||||
return (uint32_t) (r_info & 0xffffffffL);
|
}
|
||||||
|
uint32_t getType(bool isMips64EL) const {
|
||||||
|
return (uint32_t) (this->getRInfo(isMips64EL) & 0xffffffffL);
|
||||||
}
|
}
|
||||||
void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); }
|
void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); }
|
||||||
void setType(uint32_t t) { setSymbolAndType(getSymbol(), t); }
|
void setType(uint32_t t) { setSymbolAndType(getSymbol(), t); }
|
||||||
void setSymbolAndType(uint32_t s, uint32_t t) {
|
void setSymbolAndType(uint32_t s, uint32_t t) {
|
||||||
r_info = ((uint64_t)s << 32) + (t&0xffffffffL);
|
this->setRInfo(((uint64_t)s << 32) + (t&0xffffffffL));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -389,18 +437,21 @@ template<template<endianness, std::size_t, bool> class ELFT,
|
||||||
endianness TargetEndianness, std::size_t MaxAlign, bool isRela>
|
endianness TargetEndianness, std::size_t MaxAlign, bool isRela>
|
||||||
struct Elf_Rel_Impl<ELFT<TargetEndianness, MaxAlign, false>, isRela>
|
struct Elf_Rel_Impl<ELFT<TargetEndianness, MaxAlign, false>, isRela>
|
||||||
: Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, isRela> {
|
: Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, isRela> {
|
||||||
using Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, isRela>::r_info;
|
|
||||||
LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA
|
LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA
|
||||||
MaxAlign LLVM_ELF_COMMA false>)
|
MaxAlign LLVM_ELF_COMMA false>)
|
||||||
|
|
||||||
// These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE,
|
// These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE,
|
||||||
// and ELF32_R_INFO macros defined in the ELF specification:
|
// and ELF32_R_INFO macros defined in the ELF specification:
|
||||||
uint32_t getSymbol() const { return (r_info >> 8); }
|
uint32_t getSymbol(bool isMips64EL) const {
|
||||||
unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); }
|
return this->getRInfo(isMips64EL) >> 8;
|
||||||
|
}
|
||||||
|
unsigned char getType(bool isMips64EL) const {
|
||||||
|
return (unsigned char) (this->getRInfo(isMips64EL) & 0x0ff);
|
||||||
|
}
|
||||||
void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); }
|
void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); }
|
||||||
void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); }
|
void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); }
|
||||||
void setSymbolAndType(uint32_t s, unsigned char t) {
|
void setSymbolAndType(uint32_t s, unsigned char t) {
|
||||||
r_info = (s << 8) + t;
|
this->setRInfo((s << 8) + t);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -703,6 +754,13 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ELFObjectFile(MemoryBuffer *Object, error_code &ec);
|
ELFObjectFile(MemoryBuffer *Object, error_code &ec);
|
||||||
|
|
||||||
|
bool isMips64EL() const {
|
||||||
|
return Header->e_machine == ELF::EM_MIPS &&
|
||||||
|
Header->getFileClass() == ELF::ELFCLASS64 &&
|
||||||
|
Header->getDataEncoding() == ELF::ELFDATA2LSB;
|
||||||
|
}
|
||||||
|
|
||||||
virtual symbol_iterator begin_symbols() const;
|
virtual symbol_iterator begin_symbols() const;
|
||||||
virtual symbol_iterator end_symbols() const;
|
virtual symbol_iterator end_symbols() const;
|
||||||
|
|
||||||
|
@ -1467,11 +1525,11 @@ error_code ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel,
|
||||||
default :
|
default :
|
||||||
report_fatal_error("Invalid section type in Rel!");
|
report_fatal_error("Invalid section type in Rel!");
|
||||||
case ELF::SHT_REL : {
|
case ELF::SHT_REL : {
|
||||||
symbolIdx = getRel(Rel)->getSymbol();
|
symbolIdx = getRel(Rel)->getSymbol(isMips64EL());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ELF::SHT_RELA : {
|
case ELF::SHT_RELA : {
|
||||||
symbolIdx = getRela(Rel)->getSymbol();
|
symbolIdx = getRela(Rel)->getSymbol(isMips64EL());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1537,11 +1595,11 @@ error_code ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel,
|
||||||
default :
|
default :
|
||||||
report_fatal_error("Invalid section type in Rel!");
|
report_fatal_error("Invalid section type in Rel!");
|
||||||
case ELF::SHT_REL : {
|
case ELF::SHT_REL : {
|
||||||
Result = getRel(Rel)->getType();
|
Result = getRel(Rel)->getType(isMips64EL());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ELF::SHT_RELA : {
|
case ELF::SHT_RELA : {
|
||||||
Result = getRela(Rel)->getType();
|
Result = getRela(Rel)->getType(isMips64EL());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1561,11 +1619,11 @@ error_code ELFObjectFile<ELFT>::getRelocationTypeName(
|
||||||
default :
|
default :
|
||||||
return object_error::parse_failed;
|
return object_error::parse_failed;
|
||||||
case ELF::SHT_REL : {
|
case ELF::SHT_REL : {
|
||||||
type = getRel(Rel)->getType();
|
type = getRel(Rel)->getType(isMips64EL());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ELF::SHT_RELA : {
|
case ELF::SHT_RELA : {
|
||||||
type = getRela(Rel)->getType();
|
type = getRela(Rel)->getType(isMips64EL());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2059,14 +2117,14 @@ error_code ELFObjectFile<ELFT>::getRelocationValueString(
|
||||||
default:
|
default:
|
||||||
return object_error::parse_failed;
|
return object_error::parse_failed;
|
||||||
case ELF::SHT_REL: {
|
case ELF::SHT_REL: {
|
||||||
type = getRel(Rel)->getType();
|
type = getRel(Rel)->getType(isMips64EL());
|
||||||
symbol_index = getRel(Rel)->getSymbol();
|
symbol_index = getRel(Rel)->getSymbol(isMips64EL());
|
||||||
// TODO: Read implicit addend from section data.
|
// TODO: Read implicit addend from section data.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ELF::SHT_RELA: {
|
case ELF::SHT_RELA: {
|
||||||
type = getRela(Rel)->getType();
|
type = getRela(Rel)->getType(isMips64EL());
|
||||||
symbol_index = getRela(Rel)->getSymbol();
|
symbol_index = getRela(Rel)->getSymbol(isMips64EL());
|
||||||
addend = getRela(Rel)->r_addend;
|
addend = getRela(Rel)->r_addend;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,7 @@ func:
|
||||||
|
|
||||||
|
|
||||||
// MIPS64EL: RELOCATION RECORDS FOR [.eh_frame]:
|
// MIPS64EL: RELOCATION RECORDS FOR [.eh_frame]:
|
||||||
// FIXME: llvm-objdump currently misprints the relocations for mips64el
|
// MIPS64EL-NEXT: R_MIPS_64
|
||||||
// MIPS64EL: Contents of section .eh_frame:
|
// MIPS64EL: Contents of section .eh_frame:
|
||||||
// MIPS64EL-NEXT: 0000
|
// MIPS64EL-NEXT: 0000
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -8,6 +8,8 @@ RUN: llvm-objdump -r %p/Inputs/trivial-object-test.elf-x86-64 \
|
||||||
RUN: | FileCheck %s -check-prefix ELF-x86-64
|
RUN: | FileCheck %s -check-prefix ELF-x86-64
|
||||||
RUN: llvm-objdump -r %p/Inputs/trivial-object-test.elf-hexagon \
|
RUN: llvm-objdump -r %p/Inputs/trivial-object-test.elf-hexagon \
|
||||||
RUN: | FileCheck %s -check-prefix ELF-hexagon
|
RUN: | FileCheck %s -check-prefix ELF-hexagon
|
||||||
|
RUN: llvm-objdump -r %p/Inputs/trivial-object-test.elf-mips64el \
|
||||||
|
RUN: | FileCheck %s -check-prefix ELF-MIPS64EL
|
||||||
|
|
||||||
RUN: llvm-objdump -r %p/Inputs/relocations.elf-x86-64 \
|
RUN: llvm-objdump -r %p/Inputs/relocations.elf-x86-64 \
|
||||||
RUN: | FileCheck %s -check-prefix ELF-complex-x86-64
|
RUN: | FileCheck %s -check-prefix ELF-complex-x86-64
|
||||||
|
@ -40,6 +42,11 @@ ELF-hexagon: R_HEX_LO16 puts
|
||||||
ELF-hexagon: R_HEX_B15_PCREL testf
|
ELF-hexagon: R_HEX_B15_PCREL testf
|
||||||
ELF-hexagon: R_HEX_B22_PCREL puts
|
ELF-hexagon: R_HEX_B22_PCREL puts
|
||||||
|
|
||||||
|
// Note: this file was produced with gas to make sure we don't end up in a
|
||||||
|
// situation where LLVM produces and accepts a broken file.
|
||||||
|
ELF-MIPS64EL: .data
|
||||||
|
ELF-MIPS64EL: R_MIPS_64
|
||||||
|
|
||||||
ELF-complex-x86-64: .text
|
ELF-complex-x86-64: .text
|
||||||
ELF-complex-x86-64-NEXT: R_X86_64_8 .data-4
|
ELF-complex-x86-64-NEXT: R_X86_64_8 .data-4
|
||||||
ELF-complex-x86-64-NEXT: R_X86_64_16 .data-4
|
ELF-complex-x86-64-NEXT: R_X86_64_16 .data-4
|
||||||
|
|
Loading…
Reference in New Issue