From: Eugene Leviant Date: Wed, 13 Feb 2019 07:34:54 +0000 (+0000) Subject: [llvm-objcopy] Add --strip-unneeded-symbol(s) X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cb9edfda6caef0cb56568663e3dca8a9c3368f1e;p=llvm [llvm-objcopy] Add --strip-unneeded-symbol(s) Differential revision: https://reviews.llvm.org/D58027 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@353919 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/test/tools/llvm-objcopy/COFF/strip-unneeded.test b/test/tools/llvm-objcopy/COFF/strip-unneeded.test index 569bc8aed2f..ca3efe4a313 100644 --- a/test/tools/llvm-objcopy/COFF/strip-unneeded.test +++ b/test/tools/llvm-objcopy/COFF/strip-unneeded.test @@ -5,6 +5,13 @@ RUN: llvm-objdump -t %t.in.o | FileCheck %s --check-prefixes=SYMBOLS,SYMBOLS-PRE RUN: llvm-objcopy --strip-unneeded %t.in.o %t.out.o RUN: llvm-objdump -t %t.out.o | FileCheck %s --check-prefix=SYMBOLS +RUN: llvm-objcopy --strip-unneeded-symbol=external_undefined_unreferenced \ +RUN: --strip-unneeded-symbol=local_unreferenced \ +RUN: --strip-unneeded-symbol=local_undefined_unreferenced \ +RUN: --strip-unneeded-symbol='@feat.00' \ +RUN: %t.in.o %t.out2.o +RUN: cmp %t.out.o %t.out2.o + SYMBOLS: SYMBOL TABLE: SYMBOLS-NEXT: external SYMBOLS-NEXT: external_undefined diff --git a/test/tools/llvm-objcopy/ELF/strip-unneeded.test b/test/tools/llvm-objcopy/ELF/strip-unneeded.test index 6d5682f2861..60d83884715 100644 --- a/test/tools/llvm-objcopy/ELF/strip-unneeded.test +++ b/test/tools/llvm-objcopy/ELF/strip-unneeded.test @@ -5,6 +5,24 @@ # RUN: cmp %t %t1 # RUN: llvm-readobj --symbols %t2 | FileCheck %s +# RUN: llvm-objcopy --strip-unneeded-symbol=bar \ +# RUN: %t %t3 +# RUN: llvm-readobj --symbols %t3 | FileCheck %s --check-prefixes=STRIP-BAR,REMAIN + +# RUN: llvm-objcopy --regex --strip-unneeded-symbol='.*' %t %t4 +# RUN: cmp %t2 %t4 + +# RUN: echo " bar # bar " > %t.list.txt +# RUN: echo "foobar" >> %t.list.txt +# RUN: echo "foobaz" >> %t.list.txt +# RUN: echo " # comment " >> %t.list.txt +# RUN: llvm-objcopy --strip-unneeded-symbols %t.list.txt %t %t5 +# RUN: cmp %t2 %t5 + +# RUN: echo " .* # * - remove all " > %t.list2.txt +# RUN: llvm-objcopy --regex --strip-unneeded-symbols %t.list2.txt %t %t6 +# RUN: cmp %t2 %t6 + # Verify that llvm-strip modifies the symbol table the same way. # RUN: llvm-strip --strip-unneeded %t # RUN: cmp %t %t2 @@ -141,3 +159,7 @@ Symbols: #CHECK-NEXT: Section: .text #CHECK-NEXT: } #CHECK-NEXT:] + +#STRIP-BAR-NOT: Name: bar ({{.*}}) +#REMAIN: Name: foobar +#REMAIN: Name: foobaz diff --git a/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/tools/llvm-objcopy/COFF/COFFObjcopy.cpp index 72161e1c4d7..7923ef22fbe 100644 --- a/tools/llvm-objcopy/COFF/COFFObjcopy.cpp +++ b/tools/llvm-objcopy/COFF/COFFObjcopy.cpp @@ -151,10 +151,13 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) { if (!Sym.Referenced) { // With --strip-unneeded, GNU objcopy removes all unreferenced local // symbols, and any unreferenced undefined external. - if (Config.StripUnneeded && - (Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC || - Sym.Sym.SectionNumber == 0)) - return true; + // With --strip-unneeded-symbol we strip only specific unreferenced + // local symbol instead of removing all of such. + if (Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC || + Sym.Sym.SectionNumber == 0) + if (Config.StripUnneeded || + is_contained(Config.UnneededSymbolsToRemove, Sym.Name)) + return true; // GNU objcopy keeps referenced local symbols and external symbols // if --discard-all is set, similar to what --strip-unneeded does, diff --git a/tools/llvm-objcopy/CopyConfig.cpp b/tools/llvm-objcopy/CopyConfig.cpp index f643cb449a6..811f8b753e0 100644 --- a/tools/llvm-objcopy/CopyConfig.cpp +++ b/tools/llvm-objcopy/CopyConfig.cpp @@ -468,6 +468,11 @@ DriverConfig parseObjcopyOptions(ArrayRef ArgsArr) { for (auto Arg : InputArgs.filtered(OBJCOPY_strip_symbols)) addSymbolsFromFile(Config.SymbolsToRemove, DC.Alloc, Arg->getValue(), UseRegex); + for (auto Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbol)) + Config.UnneededSymbolsToRemove.emplace_back(Arg->getValue(), UseRegex); + for (auto Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbols)) + addSymbolsFromFile(Config.UnneededSymbolsToRemove, DC.Alloc, + Arg->getValue(), UseRegex); for (auto Arg : InputArgs.filtered(OBJCOPY_keep_symbol)) Config.SymbolsToKeep.emplace_back(Arg->getValue(), UseRegex); diff --git a/tools/llvm-objcopy/CopyConfig.h b/tools/llvm-objcopy/CopyConfig.h index b03860465bd..f1d5cf2c10c 100644 --- a/tools/llvm-objcopy/CopyConfig.h +++ b/tools/llvm-objcopy/CopyConfig.h @@ -91,6 +91,7 @@ struct CopyConfig { std::vector SymbolsToKeep; std::vector SymbolsToLocalize; std::vector SymbolsToRemove; + std::vector UnneededSymbolsToRemove; std::vector SymbolsToWeaken; std::vector ToRemove; std::vector SymbolsToKeepGlobal; diff --git a/tools/llvm-objcopy/ELF/ELFObjcopy.cpp b/tools/llvm-objcopy/ELF/ELFObjcopy.cpp index fc343873075..4d2e78ade99 100644 --- a/tools/llvm-objcopy/ELF/ELFObjcopy.cpp +++ b/tools/llvm-objcopy/ELF/ELFObjcopy.cpp @@ -268,6 +268,12 @@ static void replaceDebugSections( }; } +static bool isUnneededSymbol(const Symbol &Sym) { + return !Sym.Referenced && + (Sym.Binding == STB_LOCAL || Sym.getShndx() == SHN_UNDEF) && + Sym.Type != STT_FILE && Sym.Type != STT_SECTION; +} + // This function handles the high level operations of GNU objcopy including // handling command line options. It's important to outline certain properties // we expect to hold of the command line operations. Any operation that "keeps" @@ -336,7 +342,7 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj, // The purpose of this loop is to mark symbols referenced by sections // (like GroupSection or RelocationSection). This way, we know which // symbols are still 'needed' and which are not. - if (Config.StripUnneeded) { + if (Config.StripUnneeded || !Config.UnneededSymbolsToRemove.empty()) { for (auto &Section : Obj.sections()) Section.markSymbols(); } @@ -359,9 +365,9 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj, if (is_contained(Config.SymbolsToRemove, Sym.Name)) return true; - if (Config.StripUnneeded && !Sym.Referenced && - (Sym.Binding == STB_LOCAL || Sym.getShndx() == SHN_UNDEF) && - Sym.Type != STT_FILE && Sym.Type != STT_SECTION) + if ((Config.StripUnneeded || + is_contained(Config.UnneededSymbolsToRemove, Sym.Name)) && + isUnneededSymbol(Sym)) return true; return false; diff --git a/tools/llvm-objcopy/ObjcopyOpts.td b/tools/llvm-objcopy/ObjcopyOpts.td index 12d619ef8b4..b3172190b04 100644 --- a/tools/llvm-objcopy/ObjcopyOpts.td +++ b/tools/llvm-objcopy/ObjcopyOpts.td @@ -122,6 +122,15 @@ def strip_non_alloc : Flag<["-", "--"], "strip-non-alloc">, HelpText<"Remove all non-allocated sections">; def strip_unneeded : Flag<["-", "--"], "strip-unneeded">, HelpText<"Remove all symbols not needed by relocations">; +defm strip_unneeded_symbol + : Eq<"strip-unneeded-symbol", + "Remove symbol if it is not needed by relocations">, + MetaVarName<"symbol">; +defm strip_unneeded_symbols + : Eq<"strip-unneeded-symbols", + "Reads a list of symbols from and removes them " + "if they are not needed by relocations">, + MetaVarName<"filename">; def extract_dwo : Flag<["-", "--"], "extract-dwo">,