Index: test/tools/llvm-objcopy/strip-all-and-keep-symbol.test =================================================================== --- test/tools/llvm-objcopy/strip-all-and-keep-symbol.test +++ test/tools/llvm-objcopy/strip-all-and-keep-symbol.test @@ -0,0 +1,66 @@ +# RUN: yaml2obj %s > %t +# RUN: llvm-objcopy --strip-all --keep-symbol foo %t %t2 +# RUN: llvm-readobj -sections -symbols %t2 | FileCheck %s + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x1000 + AddressAlign: 0x0000000000000010 + Size: 64 + - Name: .gnu.warning.foo + Type: SHT_PROGBITS + - Name: .debug_bar + Type: SHT_PROGBITS +Symbols: + Local: + - 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 + +# CHECK: Name: .text +# CHECK: Name: .gnu.warning.foo +# CHECK: Name: .symtab +# CHECK: Name: .strtab +# CHECK: Name: .shstrtab +# CHECK-NOT: Name: .debug_bar + +#CHECK: Symbols [ +#CHECK-NEXT: Symbol { +#CHECK-NEXT: Name: +#CHECK-NEXT: Value: 0x0 +#CHECK-NEXT: Size: 0 +#CHECK-NEXT: Binding: Local +#CHECK-NEXT: Type: None +#CHECK-NEXT: Other: 0 +#CHECK-NEXT: Section: Undefined +#CHECK-NEXT: } +#CHECK-NEXT: Symbol { +#CHECK-NEXT: Name: foo +#CHECK-NEXT: Value: 0x1000 +#CHECK-NEXT: Size: 8 +#CHECK-NEXT: Binding: Local +#CHECK-NEXT: Type: Function +#CHECK-NEXT: Other: 0 +#CHECK-NEXT: Section: .text +#CHECK-NEXT: } +#CHECK-NEXT:] Index: tools/llvm-objcopy/llvm-objcopy.cpp =================================================================== --- tools/llvm-objcopy/llvm-objcopy.cpp +++ tools/llvm-objcopy/llvm-objcopy.cpp @@ -223,6 +223,55 @@ SplitDWOToFile(Config, Reader, Config.SplitDWO, OutputElfType); } + bool KeepSymbolsTable = false; + if (Obj.SymbolTable) { + Obj.SymbolTable->updateSymbols([&](Symbol &Sym) { + if ((Config.LocalizeHidden && + (Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) || + (!Config.SymbolsToLocalize.empty() && + is_contained(Config.SymbolsToLocalize, Sym.Name))) + Sym.Binding = STB_LOCAL; + + if (!Config.SymbolsToGlobalize.empty() && + is_contained(Config.SymbolsToGlobalize, Sym.Name)) + Sym.Binding = STB_GLOBAL; + + if (!Config.SymbolsToWeaken.empty() && + is_contained(Config.SymbolsToWeaken, Sym.Name) && + Sym.Binding == STB_GLOBAL) + Sym.Binding = STB_WEAK; + + if (Config.Weaken && Sym.Binding == STB_GLOBAL && + Sym.getShndx() != SHN_UNDEF) + Sym.Binding = STB_WEAK; + + const auto I = Config.SymbolsToRename.find(Sym.Name); + if (I != Config.SymbolsToRename.end()) + Sym.Name = I->getValue(); + }); + + Obj.removeSymbols([&](const Symbol &Sym) { + if (!Config.SymbolsToKeep.empty() && + is_contained(Config.SymbolsToKeep, Sym.Name)) { + KeepSymbolsTable = true; + return false; + } + + if ((Config.DiscardAll || Config.StripAll || Config.StripAllGNU || + Config.StripNonAlloc) && + Sym.Binding == STB_LOCAL && Sym.getShndx() != SHN_UNDEF && + Sym.Type != STT_FILE && Sym.Type != STT_SECTION) + return true; + + if (!Config.SymbolsToRemove.empty() && + is_contained(Config.SymbolsToRemove, Sym.Name)) { + return true; + } + + return false; + }); + } + SectionPred RemovePred = [](const SectionBase &) { return false; }; // Removes: @@ -244,7 +293,10 @@ }; if (Config.StripAllGNU) - RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { + RemovePred = [RemovePred, &Obj, KeepSymbolsTable](const SectionBase &Sec) { + if (KeepSymbolsTable && + (&Sec == Obj.SymbolTable || &Sec == Obj.SymbolTable->getStrTab())) + return false; if (RemovePred(Sec)) return true; if ((Sec.Flags & SHF_ALLOC) != 0) @@ -274,7 +326,10 @@ } if (Config.StripNonAlloc) - RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { + RemovePred = [RemovePred, KeepSymbolsTable, &Obj](const SectionBase &Sec) { + if (KeepSymbolsTable && + (&Sec == Obj.SymbolTable || &Sec == Obj.SymbolTable->getStrTab())) + return false; if (RemovePred(Sec)) return true; if (&Sec == Obj.SectionNames) @@ -282,8 +337,11 @@ return (Sec.Flags & SHF_ALLOC) == 0; }; - if (Config.StripAll) - RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { + if (Config.StripAll) { + RemovePred = [RemovePred, KeepSymbolsTable, &Obj](const SectionBase &Sec) { + if (KeepSymbolsTable && + (&Sec == Obj.SymbolTable || &Sec == Obj.SymbolTable->getStrTab())) + return false; if (RemovePred(Sec)) return true; if (&Sec == Obj.SectionNames) @@ -292,6 +350,7 @@ return false; return (Sec.Flags & SHF_ALLOC) == 0; }; + } // Explicit copies: if (!Config.OnlyKeep.empty()) { @@ -347,51 +406,6 @@ if (!Config.AddGnuDebugLink.empty()) Obj.addSection(Config.AddGnuDebugLink); - - if (Obj.SymbolTable) { - Obj.SymbolTable->updateSymbols([&](Symbol &Sym) { - if ((Config.LocalizeHidden && - (Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) || - (!Config.SymbolsToLocalize.empty() && - is_contained(Config.SymbolsToLocalize, Sym.Name))) - Sym.Binding = STB_LOCAL; - - if (!Config.SymbolsToGlobalize.empty() && - is_contained(Config.SymbolsToGlobalize, Sym.Name)) - Sym.Binding = STB_GLOBAL; - - if (!Config.SymbolsToWeaken.empty() && - is_contained(Config.SymbolsToWeaken, Sym.Name) && - Sym.Binding == STB_GLOBAL) - Sym.Binding = STB_WEAK; - - if (Config.Weaken && Sym.Binding == STB_GLOBAL && - Sym.getShndx() != SHN_UNDEF) - Sym.Binding = STB_WEAK; - - const auto I = Config.SymbolsToRename.find(Sym.Name); - if (I != Config.SymbolsToRename.end()) - Sym.Name = I->getValue(); - }); - - Obj.removeSymbols([&](const Symbol &Sym) { - if (!Config.SymbolsToKeep.empty() && - is_contained(Config.SymbolsToKeep, Sym.Name)) - return false; - - if (Config.DiscardAll && Sym.Binding == STB_LOCAL && - Sym.getShndx() != SHN_UNDEF && Sym.Type != STT_FILE && - Sym.Type != STT_SECTION) - return true; - - if (!Config.SymbolsToRemove.empty() && - is_contained(Config.SymbolsToRemove, Sym.Name)) { - return true; - } - - return false; - }); - } } std::unique_ptr CreateReader(StringRef InputFilename,