Index: llvm/test/tools/llvm-objcopy/ELF/add-symbol-no-symtab.test =================================================================== --- llvm/test/tools/llvm-objcopy/ELF/add-symbol-no-symtab.test +++ llvm/test/tools/llvm-objcopy/ELF/add-symbol-no-symtab.test @@ -105,3 +105,15 @@ Binding: STB_GLOBAL Symbols: [] ... + +## Show that llvm-objcopy can handle a case when we wanted to remove all symbols +## and add a brand new one. +# RUN: llvm-objcopy --allow-broken-links -R .symtab --add-symbol foo=1234 %t %t2 +# RUN: llvm-readelf --sections %t2 | FileCheck %s --check-prefix=SECTIONS +# +# SECTIONS: There are 4 section headers +# SECTIONS: [Nr] Name Type Address Off Size ES Flg Lk Inf +# SECTIONS-NEXT: [ 0] NULL +# SECTIONS-NEXT: [ 1] .strtab +# SECTIONS-NEXT: [ 2] .shstrtab +# SECTIONS-NEXT: [ 3] .symtab {{.+}} {{.+}} {{.+}} {{.+}} {{.+}} 1 {{.+}} Index: llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp =================================================================== --- llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp +++ llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp @@ -738,6 +738,25 @@ 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()) { + switch (OutputElfType) { + case ELFT_ELF32LE: + ELFBuilder::createSymbolTable(&Obj); + break; + case ELFT_ELF64LE: + ELFBuilder::createSymbolTable(&Obj); + break; + case ELFT_ELF32BE: + ELFBuilder::createSymbolTable(&Obj); + break; + case ELFT_ELF64BE: + ELFBuilder::createSymbolTable(&Obj); + break; + } + } + for (const NewSymbolInfo &SI : Config.ELF->SymbolsToAdd) { SectionBase *Sec = Obj.findSection(SI.SectionName); uint64_t Value = Sec ? Sec->Addr + SI.Value : SI.Value; Index: llvm/tools/llvm-objcopy/ELF/Object.h =================================================================== --- llvm/tools/llvm-objcopy/ELF/Object.h +++ llvm/tools/llvm-objcopy/ELF/Object.h @@ -949,6 +949,7 @@ ExtractPartition(ExtractPartition) {} void build(bool EnsureSymtab); + static void createSymbolTable(Object *Obj); }; class BinaryReader : public Reader { Index: llvm/tools/llvm-objcopy/ELF/Object.cpp =================================================================== --- llvm/tools/llvm-objcopy/ELF/Object.cpp +++ llvm/tools/llvm-objcopy/ELF/Object.cpp @@ -1426,6 +1426,31 @@ } } +template void ELFBuilder::createSymbolTable(Object *Obj) { + // 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; +} + template static void getAddend(uint64_t &ToSet, const Elf_Rel_Impl &Rel) {} @@ -1588,27 +1613,7 @@ 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; + createSymbolTable(&Obj); } // Now that all sections and symbols have been added we can add