diff options
author | Simon Atanasyan <simon@atanasyan.com> | 2021-12-13 17:53:30 +0300 |
---|---|---|
committer | Simon Atanasyan <simon@atanasyan.com> | 2021-12-14 17:21:27 +0300 |
commit | d5d8b1c972bca995133f358f01ce474fb8d0b669 (patch) | |
tree | d7f9f339084f4f8f6ec52f040beaed4bebe16ccf /llvm/tools/llvm-objcopy/ELF/Object.cpp | |
parent | bd053769867f988500dc1b451c6439eefcf7643f (diff) | |
download | llvm-d5d8b1c972bca995133f358f01ce474fb8d0b669.zip llvm-d5d8b1c972bca995133f358f01ce474fb8d0b669.tar.gz llvm-d5d8b1c972bca995133f358f01ce474fb8d0b669.tar.bz2 |
[llvm-objcopy] Fix handling of MIPS64 little endian files
MIPS64 little endian target has a "special" encoding of `r_info`
relocation record field. Instead of one 64-bit little endian number, it
is a little endian 32-bit number followed by a 32-bit big endian number.
For correct reading and writing such fields we must provide information
about target machine into the corresponding routine. This patch does
this for the `llvm-objcopy` tool and fix handling of MIPS64 little
endian files.
The bug was reported in the issue #52647.
Differential Revision: https://reviews.llvm.org/D115635
Diffstat (limited to 'llvm/tools/llvm-objcopy/ELF/Object.cpp')
-rw-r--r-- | llvm/tools/llvm-objcopy/ELF/Object.cpp | 36 |
1 files changed, 23 insertions, 13 deletions
diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp index 3db5028e..659e12b 100644 --- a/llvm/tools/llvm-objcopy/ELF/Object.cpp +++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp @@ -978,12 +978,12 @@ static void setAddend(Elf_Rel_Impl<ELFT, true> &Rela, uint64_t Addend) { } template <class RelRange, class T> -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 @@ template <class ELFT> Error ELFSectionWriter<ELFT>::visit(const RelocationSection &Sec) { uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset; if (Sec.Type == SHT_REL) - writeRel(Sec.Relocations, reinterpret_cast<Elf_Rel *>(Buf)); + writeRel(Sec.Relocations, reinterpret_cast<Elf_Rel *>(Buf), + Sec.getObject().IsMips64EL); else - writeRel(Sec.Relocations, reinterpret_cast<Elf_Rela *>(Buf)); + writeRel(Sec.Relocations, reinterpret_cast<Elf_Rela *>(Buf), + Sec.getObject().IsMips64EL); return Error::success(); } @@ -1398,6 +1400,14 @@ Expected<std::unique_ptr<Object>> IHexELFBuilder::build() { return std::move(Obj); } +template <class ELFT> +ELFBuilder<ELFT>::ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj, + Optional<StringRef> ExtractPartition) + : ElfFile(ElfObj.getELFFile()), Obj(Obj), + ExtractPartition(ExtractPartition) { + Obj.IsMips64EL = ElfFile.isMips64EL(); +} + template <class ELFT> void ELFBuilder<ELFT>::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 @@ static void getAddend(uint64_t &ToSet, const Elf_Rel_Impl<ELFT, true> &Rela) { } template <class T> -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<Symbol *> SymByIndex = SymbolTable->getSymbolByIndex(Sym); + Expected<Symbol *> SymByIndex = + Relocs->getObject().SymbolTable->getSymbolByIndex(Sym); if (!SymByIndex) return SymByIndex.takeError(); @@ -1698,7 +1708,7 @@ Expected<SectionBase &> ELFBuilder<ELFT>::makeSection(const Elf_Shdr &Shdr) { else return Data.takeError(); } - return Obj.addSection<RelocationSection>(); + return Obj.addSection<RelocationSection>(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 @@ template <class ELFT> Error ELFBuilder<ELFT>::readSections(bool EnsureSymtab) { if (!Rels) return Rels.takeError(); - if (Error Err = initRelocations(RelSec, Obj.SymbolTable, *Rels)) + if (Error Err = initRelocations(RelSec, *Rels)) return Err; } else { Expected<typename ELFFile<ELFT>::Elf_Rela_Range> Relas = @@ -1887,7 +1897,7 @@ template <class ELFT> Error ELFBuilder<ELFT>::readSections(bool EnsureSymtab) { 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<GroupSection>(&Sec)) { |