[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