From: Georgy Komarov Date: Wed, 1 Jul 2020 07:15:39 +0000 (+0300) Subject: [llvm-objcopy] Fix crash when removing symbol table at same time as adding a symbol X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=afd81a637dfc79d2960ef8add1c697cb81c929ef;p=android-x86%2Fexternal-llvm-project.git [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 --- 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 00000000000..f14625de4f5 --- /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 3e657d09c46..66953f9ef0d 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(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 944bfdf62fa..e15fb24f4c4 100644 --- a/llvm/tools/llvm-objcopy/ELF/Object.cpp +++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp @@ -1588,27 +1588,7 @@ template void ELFBuilder::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(&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(); - - SymbolTableSection &SymTab = Obj.addSection(); - 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 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(&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(); + + SymbolTableSection &SymTab = addSection(); + 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 c7db57708fc..ed89e916b83 100644 --- a/llvm/tools/llvm-objcopy/ELF/Object.h +++ b/llvm/tools/llvm-objcopy/ELF/Object.h @@ -1072,6 +1072,7 @@ public: Ptr->Index = Sections.size(); return *Ptr; } + void addNewSymbolTable(); Segment &addSegment(ArrayRef Data) { Segments.emplace_back(std::make_unique(Data)); return *Segments.back();