[llvm] afd81a6 - [llvm-objcopy] Fix crash when removing symbol table at same time as adding a symbol

Georgy Komarov via llvm-commits llvm-commits at lists.llvm.org
Sat Jul 4 19:20:37 PDT 2020


Author: Georgy Komarov
Date: 2020-07-05T05:14:00+03:00
New Revision: afd81a637dfc79d2960ef8add1c697cb81c929ef

URL: https://github.com/llvm/llvm-project/commit/afd81a637dfc79d2960ef8add1c697cb81c929ef
DIFF: https://github.com/llvm/llvm-project/commit/afd81a637dfc79d2960ef8add1c697cb81c929ef.diff

LOG: [llvm-objcopy] Fix crash when removing symbol table at same time as adding a symbol

This patch resolves crash that occurs when user wanted to remove all
symbols and add a brand new one using:

```
llvm-objcopy -R .symtab --add-symbol foo=1234 in.o out.o
```

Before these changes the symbol table internally being null when adding
new symbols. For now we will regenerate symtab in this case.

This fixes: https://bugs.llvm.org/show_bug.cgi?id=43930

Reviewed By: jhenderson

Differential Revision: https://reviews.llvm.org/D82935

Added: 
    llvm/test/tools/llvm-objcopy/ELF/add-symbol-new-symtab.test

Modified: 
    llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
    llvm/tools/llvm-objcopy/ELF/Object.cpp
    llvm/tools/llvm-objcopy/ELF/Object.h

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-objcopy/ELF/add-symbol-new-symtab.test b/llvm/test/tools/llvm-objcopy/ELF/add-symbol-new-symtab.test
new file mode 100644
index 000000000000..f14625de4f58
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/add-symbol-new-symtab.test
@@ -0,0 +1,50 @@
+## Show that llvm-objcopy can replace the symbol table with a new one.
+
+# RUN: yaml2obj %s -o %t
+
+# RUN: llvm-objcopy -R .symtab --add-symbol newsym=1234 %t %t2
+# RUN: llvm-readelf -S -s %t2 | FileCheck %s --match-full-lines
+
+# CHECK: There are 5 section headers, starting at offset {{.+}}:
+# CHECK:      [Nr] Name      Type     Address          Off    Size   ES  Flg Lk Inf Al
+# CHECK-NEXT: [ 0]           NULL     0000000000000000 {{.+}} 000000 00      0  0   0
+# CHECK-NEXT: [ 1] .text     PROGBITS 0000000000001000 {{.+}} 000040 00  AX  0  0   16
+# CHECK-NEXT: [ 2] .strtab   STRTAB   0000000000000000 {{.+}} 000001 00      0  0   1
+# CHECK-NEXT: [ 3] .shstrtab STRTAB   0000000000000000 {{.+}} 000028 00      0  0   1
+# CHECK-NEXT: [ 4] .symtab   SYMTAB   0000000000000000 {{.+}} 000030 18      3  1   8
+
+# CHECK: Symbol table '.symtab' contains 2 entries:
+# CHECK-NEXT:   Num:    Value          Size Type    Bind   Vis       Ndx Name
+# CHECK-NEXT:     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT   UND
+# CHECK-NEXT:     1: 00000000000004d2     0 NOTYPE  GLOBAL DEFAULT   ABS newsym
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_X86_64
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x1000
+    AddressAlign:    0x0000000000000010
+    Size:            64
+Symbols:
+  - Name:     foo
+    Type:     STT_FUNC
+    Section:  .text
+    Value:    0x1000
+    Size:     8
+  - Name:     bar
+    Type:     STT_FUNC
+    Section:  .text
+    Value:    0x1008
+    Size:     8
+  - Name:     baz
+    Type:     STT_FUNC
+    Section:  .text
+    Value:    0x1010
+    Size:     8
+

diff  --git a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
index 3e657d09c469..66953f9ef0d5 100644
--- a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
+++ b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
@@ -738,6 +738,12 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj,
     Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink,
                                         Config.GnuDebugLinkCRC32);
 
+  // If the symbol table was previously removed, we need to create a new one
+  // before adding new symbols.
+  if (!Obj.SymbolTable && !Config.ELF->SymbolsToAdd.empty()) {
+    Obj.addNewSymbolTable();
+  }
+
   for (const NewSymbolInfo &SI : Config.ELF->SymbolsToAdd) {
     SectionBase *Sec = Obj.findSection(SI.SectionName);
     uint64_t Value = Sec ? Sec->Addr + SI.Value : SI.Value;

diff  --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp
index 944bfdf62fad..e15fb24f4c42 100644
--- a/llvm/tools/llvm-objcopy/ELF/Object.cpp
+++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp
@@ -1588,27 +1588,7 @@ template <class ELFT> void ELFBuilder<ELFT>::readSections(bool EnsureSymtab) {
     Obj.SymbolTable->initialize(Obj.sections());
     initSymbolTable(Obj.SymbolTable);
   } else if (EnsureSymtab) {
-    // Reuse an existing SHT_STRTAB section if it exists.
-    StringTableSection *StrTab = nullptr;
-    for (auto &Sec : Obj.sections()) {
-      if (Sec.Type == ELF::SHT_STRTAB && !(Sec.Flags & SHF_ALLOC)) {
-        StrTab = static_cast<StringTableSection *>(&Sec);
-
-        // Prefer a string table that is not the section header string table, if
-        // such a table exists.
-        if (Obj.SectionNames != &Sec)
-          break;
-      }
-    }
-    if (!StrTab)
-      StrTab = &Obj.addSection<StringTableSection>();
-
-    SymbolTableSection &SymTab = Obj.addSection<SymbolTableSection>();
-    SymTab.Name = ".symtab";
-    SymTab.Link = StrTab->Index;
-    SymTab.initialize(Obj.sections());
-    SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0);
-    Obj.SymbolTable = &SymTab;
+    Obj.addNewSymbolTable();
   }
 
   // Now that all sections and symbols have been added we can add
@@ -1900,6 +1880,33 @@ Error Object::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
   return Error::success();
 }
 
+void Object::addNewSymbolTable() {
+  assert(!SymbolTable && "Object must not has a SymbolTable.");
+
+  // Reuse an existing SHT_STRTAB section if it exists.
+  StringTableSection *StrTab = nullptr;
+  for (SectionBase &Sec : sections()) {
+    if (Sec.Type == ELF::SHT_STRTAB && !(Sec.Flags & SHF_ALLOC)) {
+      StrTab = static_cast<StringTableSection *>(&Sec);
+
+      // Prefer a string table that is not the section header string table, if
+      // such a table exists.
+      if (SectionNames != &Sec)
+        break;
+    }
+  }
+  if (!StrTab)
+    StrTab = &addSection<StringTableSection>();
+
+  SymbolTableSection &SymTab = addSection<SymbolTableSection>();
+  SymTab.Name = ".symtab";
+  SymTab.Link = StrTab->Index;
+  SymTab.initialize(sections());
+  SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0);
+
+  SymbolTable = &SymTab;
+}
+
 void Object::sortSections() {
   // Use stable_sort to maintain the original ordering as closely as possible.
   llvm::stable_sort(Sections, [](const SecPtr &A, const SecPtr &B) {

diff  --git a/llvm/tools/llvm-objcopy/ELF/Object.h b/llvm/tools/llvm-objcopy/ELF/Object.h
index c7db57708fc3..ed89e916b838 100644
--- a/llvm/tools/llvm-objcopy/ELF/Object.h
+++ b/llvm/tools/llvm-objcopy/ELF/Object.h
@@ -1072,6 +1072,7 @@ class Object {
     Ptr->Index = Sections.size();
     return *Ptr;
   }
+  void addNewSymbolTable();
   Segment &addSegment(ArrayRef<uint8_t> Data) {
     Segments.emplace_back(std::make_unique<Segment>(Data));
     return *Segments.back();


        


More information about the llvm-commits mailing list