[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