From d787a41b118a3724d1df87dc3d38cc3fddb3a145 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 3 Apr 2013 21:02:51 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178694 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/ELF.h | 96 +++++++++++++++++---- test/MC/Mips/eh-frame.s | 2 +- .../Object/Inputs/trivial-object-test.elf-mips64el | Bin 0 -> 1064 bytes test/Object/objdump-relocations.test | 7 ++ 4 files changed, 85 insertions(+), 20 deletions(-) create mode 100644 test/Object/Inputs/trivial-object-test.elf-mips64el diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index ac6f386032e..8ea5e46e09e 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -330,6 +330,14 @@ struct Elf_Rel_Base, false> { MaxAlign LLVM_ELF_COMMA false>) 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 + + uint32_t getRInfo(bool isMips64EL) const { + assert(!isMips64EL); + return r_info; + } + void setRInfo(uint32_t R) { + r_info = R; + } }; template class ELFT, @@ -339,6 +347,22 @@ struct Elf_Rel_Base, false> { MaxAlign LLVM_ELF_COMMA true>) 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 + + 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 class ELFT, @@ -349,6 +373,14 @@ struct Elf_Rel_Base, true> { 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_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 class ELFT, @@ -359,6 +391,21 @@ struct Elf_Rel_Base, true> { 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_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 @@ -368,20 +415,21 @@ template class ELFT, endianness TargetEndianness, std::size_t MaxAlign, bool isRela> struct Elf_Rel_Impl, isRela> : Elf_Rel_Base, isRela> { - using Elf_Rel_Base, isRela>::r_info; LLVM_ELF_IMPORT_TYPES(ELFT) // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, // and ELF64_R_INFO macros defined in the ELF specification: - uint32_t getSymbol() const { return (uint32_t) (r_info >> 32); } - uint32_t getType() const { - return (uint32_t) (r_info & 0xffffffffL); + uint32_t getSymbol(bool isMips64EL) const { + return (uint32_t) (this->getRInfo(isMips64EL) >> 32); + } + uint32_t getType(bool isMips64EL) const { + return (uint32_t) (this->getRInfo(isMips64EL) & 0xffffffffL); } void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } void setType(uint32_t t) { setSymbolAndType(getSymbol(), 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 class ELFT, endianness TargetEndianness, std::size_t MaxAlign, bool isRela> struct Elf_Rel_Impl, isRela> : Elf_Rel_Base, isRela> { - using Elf_Rel_Base, isRela>::r_info; LLVM_ELF_IMPORT_TYPES(ELFT) // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, // and ELF32_R_INFO macros defined in the ELF specification: - uint32_t getSymbol() const { return (r_info >> 8); } - unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); } + uint32_t getSymbol(bool isMips64EL) const { + 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 setType(unsigned char t) { setSymbolAndType(getSymbol(), 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: 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 end_symbols() const; @@ -1467,11 +1525,11 @@ error_code ELFObjectFile::getRelocationSymbol(DataRefImpl Rel, default : report_fatal_error("Invalid section type in Rel!"); case ELF::SHT_REL : { - symbolIdx = getRel(Rel)->getSymbol(); + symbolIdx = getRel(Rel)->getSymbol(isMips64EL()); break; } case ELF::SHT_RELA : { - symbolIdx = getRela(Rel)->getSymbol(); + symbolIdx = getRela(Rel)->getSymbol(isMips64EL()); break; } } @@ -1537,11 +1595,11 @@ error_code ELFObjectFile::getRelocationType(DataRefImpl Rel, default : report_fatal_error("Invalid section type in Rel!"); case ELF::SHT_REL : { - Result = getRel(Rel)->getType(); + Result = getRel(Rel)->getType(isMips64EL()); break; } case ELF::SHT_RELA : { - Result = getRela(Rel)->getType(); + Result = getRela(Rel)->getType(isMips64EL()); break; } } @@ -1561,11 +1619,11 @@ error_code ELFObjectFile::getRelocationTypeName( default : return object_error::parse_failed; case ELF::SHT_REL : { - type = getRel(Rel)->getType(); + type = getRel(Rel)->getType(isMips64EL()); break; } case ELF::SHT_RELA : { - type = getRela(Rel)->getType(); + type = getRela(Rel)->getType(isMips64EL()); break; } } @@ -2059,14 +2117,14 @@ error_code ELFObjectFile::getRelocationValueString( default: return object_error::parse_failed; case ELF::SHT_REL: { - type = getRel(Rel)->getType(); - symbol_index = getRel(Rel)->getSymbol(); + type = getRel(Rel)->getType(isMips64EL()); + symbol_index = getRel(Rel)->getSymbol(isMips64EL()); // TODO: Read implicit addend from section data. break; } case ELF::SHT_RELA: { - type = getRela(Rel)->getType(); - symbol_index = getRela(Rel)->getSymbol(); + type = getRela(Rel)->getType(isMips64EL()); + symbol_index = getRela(Rel)->getSymbol(isMips64EL()); addend = getRela(Rel)->r_addend; break; } diff --git a/test/MC/Mips/eh-frame.s b/test/MC/Mips/eh-frame.s index 67df21365d3..93ff0b8bd27 100644 --- a/test/MC/Mips/eh-frame.s +++ b/test/MC/Mips/eh-frame.s @@ -130,7 +130,7 @@ func: // 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-NEXT: 0000 diff --git a/test/Object/Inputs/trivial-object-test.elf-mips64el b/test/Object/Inputs/trivial-object-test.elf-mips64el new file mode 100644 index 0000000000000000000000000000000000000000..5ad9ba3a0bc0a72e4820a99a6cb96d0d174f6082 GIT binary patch literal 1064 zcmb7DO-lnY5S{J%Q3av(RPdq~=|KYi0&~!Upit;9$g&FxYM0#{su%xSf0{FCh7E6X zaiGkbH*Y?YO@E(WR+FM2wSuNJM9LEF2Y77*wscOX0~=AX98r0~^xvP}Rb+bK9sHXj z-|Re@uK94LcHWVx`ku_|^Lk^pt$*Ksan#mbzVAQTE7r?-PoU01tl>;S^tbG#z69RJ z81)$6u%ITUaRh}_a}UAzJ3(Rr-t*>9O81c r?LkpyH&AM~1i@y=DqZ{PsayxsHCC8XLub_NDTF*^(j} literal 0 HcmV?d00001 diff --git a/test/Object/objdump-relocations.test b/test/Object/objdump-relocations.test index 6d35a2651d7..95c4c4dcaed 100644 --- a/test/Object/objdump-relocations.test +++ b/test/Object/objdump-relocations.test @@ -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: llvm-objdump -r %p/Inputs/trivial-object-test.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: | 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_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-NEXT: R_X86_64_8 .data-4 ELF-complex-x86-64-NEXT: R_X86_64_16 .data-4 -- 2.11.0