diff --git a/llvm/test/tools/llvm-objcopy/ELF/mips64.test b/llvm/test/tools/llvm-objcopy/ELF/mips64.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/ELF/mips64.test @@ -0,0 +1,36 @@ +# mips64el has a special encoding of the r_info relocation field. +# Test that we support both endianness. + +# RUN: yaml2obj %s -DENDIANNESS=ELFDATA2LSB -o %t1-le +# RUN: llvm-objcopy %t1-le %t2-le +# RUN: llvm-readobj --relocations %t2-le | FileCheck %s + +# RUN: yaml2obj %s -DENDIANNESS=ELFDATA2MSB -o %t1-be +# RUN: llvm-objcopy %t1-be %t2-be +# RUN: llvm-readobj --relocations %t2-be | FileCheck %s + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: [[ENDIANNESS]] + Type: ET_REL + Machine: EM_MIPS +Sections: + - Name: .text + Type: SHT_PROGBITS + - Name: .rela.text + Type: SHT_RELA + Relocations: + - Offset: 8 + Symbol: foo + Type: R_MIPS_JALR +Symbols: + - Name: foo + Type: STT_FUNC + Section: .text + +# CHECK: Relocations [ +# CHECK-NEXT: Section (2) .rela.text { +# CHECK-NEXT: 0x8 R_MIPS_JALR/R_MIPS_NONE/R_MIPS_NONE foo 0x0 +# CHECK-NEXT: } +# CHECK-NEXT: ] diff --git a/llvm/tools/llvm-objcopy/ELF/Object.h b/llvm/tools/llvm-objcopy/ELF/Object.h --- a/llvm/tools/llvm-objcopy/ELF/Object.h +++ b/llvm/tools/llvm-objcopy/ELF/Object.h @@ -783,8 +783,10 @@ MAKE_SEC_WRITER_FRIEND std::vector Relocations; + const Object &Obj; public: + RelocationSection(const Object &O) : Obj(O) {} void addRelocation(Relocation Rel) { Relocations.push_back(Rel); } Error accept(SectionVisitor &Visitor) const override; Error accept(MutableSectionVisitor &Visitor) override; @@ -795,6 +797,7 @@ void markSymbols() override; void replaceSectionReferences( const DenseMap &FromTo) override; + const Object &getObject() const { return Obj; } static bool classof(const SectionBase *S) { if (S->OriginalFlags & ELF::SHF_ALLOC) @@ -971,9 +974,7 @@ public: ELFBuilder(const ELFObjectFile &ElfObj, Object &Obj, - Optional ExtractPartition) - : ElfFile(ElfObj.getELFFile()), Obj(Obj), - ExtractPartition(ExtractPartition) {} + Optional ExtractPartition); Error build(bool EnsureSymtab); }; @@ -1063,6 +1064,8 @@ SymbolTableSection *SymbolTable = nullptr; SectionIndexSection *SectionIndexTable = nullptr; + bool IsMips64EL = false; + SectionTableRef sections() const { return SectionTableRef(Sections); } iterator_range< filter_iterator::const_iterator>, diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp --- a/llvm/tools/llvm-objcopy/ELF/Object.cpp +++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp @@ -978,12 +978,12 @@ } template -static void writeRel(const RelRange &Relocations, T *Buf) { +static void writeRel(const RelRange &Relocations, T *Buf, bool IsMips64EL) { for (const auto &Reloc : Relocations) { Buf->r_offset = Reloc.Offset; setAddend(*Buf, Reloc.Addend); Buf->setSymbolAndType(Reloc.RelocSymbol ? Reloc.RelocSymbol->Index : 0, - Reloc.Type, false); + Reloc.Type, IsMips64EL); ++Buf; } } @@ -992,9 +992,11 @@ Error ELFSectionWriter::visit(const RelocationSection &Sec) { uint8_t *Buf = reinterpret_cast(Out.getBufferStart()) + Sec.Offset; if (Sec.Type == SHT_REL) - writeRel(Sec.Relocations, reinterpret_cast(Buf)); + writeRel(Sec.Relocations, reinterpret_cast(Buf), + Sec.getObject().IsMips64EL); else - writeRel(Sec.Relocations, reinterpret_cast(Buf)); + writeRel(Sec.Relocations, reinterpret_cast(Buf), + Sec.getObject().IsMips64EL); return Error::success(); } @@ -1398,6 +1400,14 @@ return std::move(Obj); } +template +ELFBuilder::ELFBuilder(const ELFObjectFile &ElfObj, Object &Obj, + Optional ExtractPartition) + : ElfFile(ElfObj.getELFFile()), Obj(Obj), + ExtractPartition(ExtractPartition) { + Obj.IsMips64EL = ElfFile.isMips64EL(); +} + template void ELFBuilder::setParentSegment(Segment &Child) { for (Segment &Parent : Obj.segments()) { // Every segment will overlap with itself but we don't want a segment to @@ -1639,21 +1649,21 @@ } template -static Error initRelocations(RelocationSection *Relocs, - SymbolTableSection *SymbolTable, T RelRange) { +static Error initRelocations(RelocationSection *Relocs, T RelRange) { for (const auto &Rel : RelRange) { Relocation ToAdd; ToAdd.Offset = Rel.r_offset; getAddend(ToAdd.Addend, Rel); - ToAdd.Type = Rel.getType(false); + ToAdd.Type = Rel.getType(Relocs->getObject().IsMips64EL); - if (uint32_t Sym = Rel.getSymbol(false)) { - if (!SymbolTable) + if (uint32_t Sym = Rel.getSymbol(Relocs->getObject().IsMips64EL)) { + if (!Relocs->getObject().SymbolTable) return createStringError( errc::invalid_argument, "'" + Relocs->Name + "': relocation references symbol with index " + Twine(Sym) + ", but there is no symbol table"); - Expected SymByIndex = SymbolTable->getSymbolByIndex(Sym); + Expected SymByIndex = + Relocs->getObject().SymbolTable->getSymbolByIndex(Sym); if (!SymByIndex) return SymByIndex.takeError(); @@ -1698,7 +1708,7 @@ else return Data.takeError(); } - return Obj.addSection(); + return Obj.addSection(Obj); case SHT_STRTAB: // If a string table is allocated we don't want to mess with it. That would // mean altering the memory image. There are no special link types or @@ -1879,7 +1889,7 @@ if (!Rels) return Rels.takeError(); - if (Error Err = initRelocations(RelSec, Obj.SymbolTable, *Rels)) + if (Error Err = initRelocations(RelSec, *Rels)) return Err; } else { Expected::Elf_Rela_Range> Relas = @@ -1887,7 +1897,7 @@ if (!Relas) return Relas.takeError(); - if (Error Err = initRelocations(RelSec, Obj.SymbolTable, *Relas)) + if (Error Err = initRelocations(RelSec, *Relas)) return Err; } } else if (auto GroupSec = dyn_cast(&Sec)) {