[llvm] d5d8b1c - [llvm-objcopy] Fix handling of MIPS64 little endian files
Simon Atanasyan via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 14 06:21:51 PST 2021
Author: Simon Atanasyan
Date: 2021-12-14T17:21:27+03:00
New Revision: d5d8b1c972bca995133f358f01ce474fb8d0b669
URL: https://github.com/llvm/llvm-project/commit/d5d8b1c972bca995133f358f01ce474fb8d0b669
DIFF: https://github.com/llvm/llvm-project/commit/d5d8b1c972bca995133f358f01ce474fb8d0b669.diff
LOG: [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
Added:
llvm/test/tools/llvm-objcopy/ELF/mips64.test
Modified:
llvm/tools/llvm-objcopy/ELF/Object.cpp
llvm/tools/llvm-objcopy/ELF/Object.h
Removed:
################################################################################
diff --git a/llvm/test/tools/llvm-objcopy/ELF/mips64.test b/llvm/test/tools/llvm-objcopy/ELF/mips64.test
new file mode 100644
index 0000000000000..ad0cb0354cf01
--- /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.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp
index 3db5028e85f7c..659e12bf0306d 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)) {
diff --git a/llvm/tools/llvm-objcopy/ELF/Object.h b/llvm/tools/llvm-objcopy/ELF/Object.h
index 811af4b51310d..439380fc725b3 100644
--- a/llvm/tools/llvm-objcopy/ELF/Object.h
+++ b/llvm/tools/llvm-objcopy/ELF/Object.h
@@ -783,8 +783,10 @@ class RelocationSection
MAKE_SEC_WRITER_FRIEND
std::vector<Relocation> 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 @@ class RelocationSection
void markSymbols() override;
void replaceSectionReferences(
const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
+ const Object &getObject() const { return Obj; }
static bool classof(const SectionBase *S) {
if (S->OriginalFlags & ELF::SHF_ALLOC)
@@ -971,9 +974,7 @@ template <class ELFT> class ELFBuilder {
public:
ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj,
- Optional<StringRef> ExtractPartition)
- : ElfFile(ElfObj.getELFFile()), Obj(Obj),
- ExtractPartition(ExtractPartition) {}
+ Optional<StringRef> ExtractPartition);
Error build(bool EnsureSymtab);
};
@@ -1063,6 +1064,8 @@ class Object {
SymbolTableSection *SymbolTable = nullptr;
SectionIndexSection *SectionIndexTable = nullptr;
+ bool IsMips64EL = false;
+
SectionTableRef sections() const { return SectionTableRef(Sections); }
iterator_range<
filter_iterator<pointee_iterator<std::vector<SecPtr>::const_iterator>,
More information about the llvm-commits
mailing list