Index: llvm/test/tools/llvm-objcopy/ELF/add-symbol-new-symtab.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-objcopy/ELF/add-symbol-new-symtab.test @@ -0,0 +1,62 @@ +## Show that llvm-objcopy can handle a case when we wanted to remove all symbols +## and add a brand new one. + +# RUN: yaml2obj %s -o %t + +--- !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 + +# RUN: llvm-readelf -s %t | FileCheck --check-prefix=SYMBOLS %s + +# SYMBOLS: Symbol table '.symtab' contains 4 entries: +# SYMBOLS-NEXT: Num: Value Size Type Bind Vis Ndx Name +# SYMBOLS-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND +# SYMBOLS-NEXT: 1: 0000000000001000 8 FUNC LOCAL DEFAULT 1 foo +# SYMBOLS-NEXT: 2: 0000000000001008 8 FUNC LOCAL DEFAULT 1 bar +# SYMBOLS-NEXT: 3: 0000000000001010 8 FUNC LOCAL DEFAULT 1 baz + +# RUN: llvm-objcopy -R .symtab --add-symbol newsym=1234 %t %t2 + +# RUN: llvm-readelf -s %t2 | FileCheck --check-prefix=UPD-SYMBOLS %s + +# SECTIONS: There are 5 section headers +# SECTIONS: [Nr] Name Type Address Off Size ES Flg Lk Inf +# SECTIONS-NEXT: [ 0] NULL +# SECTIONS-NEXT: [ 1] .text +# SECTIONS-NEXT: [ 2] .strtab +# SECTIONS-NEXT: [ 3] .shstrtab +# SECTIONS-NEXT: [ 4] .symtab {{.+}} {{.+}} {{.+}} {{.+}} {{.+}} 3 {{.+}} + +# RUN: llvm-readelf --sections %t2 | FileCheck %s --check-prefix=SECTIONS + +# UPD-SYMBOLS: Symbol table '.symtab' contains 2 entries: +# UPD-SYMBOLS-NEXT: Num: Value Size Type Bind Vis Ndx Name +# UPD-SYMBOLS-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND +# UPD-SYMBOLS-NEXT: 1: 00000000000004d2 0 NOTYPE GLOBAL DEFAULT ABS newsym 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,12 @@ 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.createSymbolTable(); + } + 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 @@ -1039,6 +1039,8 @@ SymbolTableSection *SymbolTable = nullptr; SectionIndexSection *SectionIndexTable = nullptr; + void createSymbolTable(); + void sortSections(); SectionTableRef sections() { return SectionTableRef(Sections); } ConstRange sections() const { Index: llvm/tools/llvm-objcopy/ELF/Object.cpp =================================================================== --- llvm/tools/llvm-objcopy/ELF/Object.cpp +++ llvm/tools/llvm-objcopy/ELF/Object.cpp @@ -1588,27 +1588,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; + Obj.createSymbolTable(); } // Now that all sections and symbols have been added we can add @@ -1900,6 +1880,31 @@ return Error::success(); } +void Object::createSymbolTable() { + // Reuse an existing SHT_STRTAB section if it exists. + StringTableSection *StrTab = nullptr; + for (auto &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) {