Index: test/tools/llvm-objcopy/ELF/globalize.test =================================================================== --- test/tools/llvm-objcopy/ELF/globalize.test +++ test/tools/llvm-objcopy/ELF/globalize.test @@ -4,6 +4,8 @@ # RUN: --globalize-symbol Weak \ # RUN: --globalize-symbol WeakUndef %t %t2 # RUN: llvm-readobj --symbols %t2 | FileCheck %s +# RUN: llvm-objcopy -w --globalize-symbol '[.]*' %t %t3 +# RUN: llvm-readobj --symbols %t3 | FileCheck %s !ELF FileHeader: Index: test/tools/llvm-objcopy/ELF/keep-global-symbols.test =================================================================== --- test/tools/llvm-objcopy/ELF/keep-global-symbols.test +++ test/tools/llvm-objcopy/ELF/keep-global-symbols.test @@ -28,6 +28,7 @@ # RUN: echo "Unknown" >> %t-globals2.txt # RUN: echo " " >> %t-globals2.txt # RUN: echo "# File with no symbols" > %t-globals3.txt +# RUN: echo "^Global[0-9]+([[:space:]]Global6)*$" > %t-globals-regexp.txt # RUN: llvm-objcopy \ # RUN: -G Global1 \ @@ -41,6 +42,9 @@ # RUN: %t.o %t.2.o # RUN: llvm-readobj --elf-output-style=GNU --symbols %t.2.o | FileCheck %s +# RUN: llvm-objcopy -w --keep-global-symbols %t-globals-regexp.txt %t.o %t.3.o +# RUN: llvm-readobj --elf-output-style=GNU --symbols %t.3.o | FileCheck %s --check-prefix=REGEXP + !ELF FileHeader: Class: ELFCLASS64 @@ -97,3 +101,12 @@ # CHECK-NEXT: 11: {{.*}} GLOBAL {{.*}} UND Global7 # CHECK-NEXT: 12: {{.*}} WEAK {{.*}} Weak1 # CHECK-NEXT: 13: {{.*}} GLOBAL {{.*}} Weak2 + +# REGEXP: 6: {{.*}} GLOBAL {{.*}} Global1 +# REGEXP-NEXT: 7: {{.*}} GLOBAL {{.*}} Global2 +# REGEXP-NEXT: 8: {{.*}} GLOBAL {{.*}} Global3 +# REGEXP-NEXT: 9: {{.*}} GLOBAL {{.*}} Global4 +# REGEXP-NEXT: 10: {{.*}} GLOBAL {{.*}} Global5 +# REGEXP-NEXT: 11: {{.*}} GLOBAL {{.*}} Global6 +# REGEXP-NEXT: 12: {{.*}} GLOBAL {{.*}} Global5 Global6 +# REGEXP-NEXT: 13: {{.*}} GLOBAL {{.*}} UND Global7 Index: test/tools/llvm-objcopy/ELF/keep-many.test =================================================================== --- test/tools/llvm-objcopy/ELF/keep-many.test +++ test/tools/llvm-objcopy/ELF/keep-many.test @@ -1,6 +1,8 @@ # RUN: yaml2obj %s > %t # RUN: llvm-objcopy --strip-non-alloc --keep-section=.test --keep-section=.test3 %t %t2 +# RUN: llvm-objcopy --strip-non-alloc -regex --keep-section='^.test[0-9]+$' %t %t3 # RUN: llvm-readobj --file-headers --sections %t2 | FileCheck %s +# RUN: llvm-readobj --file-headers --sections %t3 | FileCheck %s --check-prefix=REGEX !ELF FileHeader: @@ -25,3 +27,8 @@ # CHECK: Name: .test # CHECK: Name: .test3 # CHECK: Name: .shstrtab + +# REGEX: SectionHeaderCount: 4 +# REGEX: Name: .test2 +# REGEX: Name: .test3 +# REGEX: Name: .shstrtab Index: test/tools/llvm-objcopy/ELF/keep-only-section.test =================================================================== --- test/tools/llvm-objcopy/ELF/keep-only-section.test +++ test/tools/llvm-objcopy/ELF/keep-only-section.test @@ -3,6 +3,8 @@ # RUN: llvm-objcopy -j .test --keep-section=.test2 %t %t3 # RUN: llvm-readobj --file-headers --sections %t2 | FileCheck %s # RUN: diff %t2 %t3 +# RUN: llvm-objcopy -w --keep-section='^.test$' --only-section='^.test[2-3]+$' %t %t4 +# RUN: llvm-readobj --file-headers --sections %t4 | FileCheck %s --check-prefix=REGEX !ELF FileHeader: @@ -25,3 +27,12 @@ # CHECK: Name: .symtab # CHECK: Name: .strtab # CHECK: Name: .shstrtab + +# REGEX: SectionHeaderCount: 7 + +# REGEX: Name: .test +# REGEX: Name: .test2 +# REGEX: Name: .test3 +# REGEX: Name: .symtab +# REGEX: Name: .strtab +# REGEX: Name: .shstrtab Index: test/tools/llvm-objcopy/ELF/keep-symbol.test =================================================================== --- test/tools/llvm-objcopy/ELF/keep-symbol.test +++ test/tools/llvm-objcopy/ELF/keep-symbol.test @@ -1,8 +1,10 @@ # RUN: yaml2obj %s > %t # RUN: llvm-objcopy --discard-all -K foo --keep-symbol bar %t %t2 # RUN: llvm-objcopy -K foo -N foo -N bar --keep-symbol bar -N baz %t %t3 +# RUN: llvm-objcopy --discard-all -w -K '^ba[.]*' %t %t4 # RUN: llvm-readobj --symbols %t2 | FileCheck %s # RUN: llvm-readobj --symbols %t3 | FileCheck %s +# RUN: llvm-readobj --symbols %t4 | FileCheck %s --check-prefix=REGEX !ELF FileHeader: @@ -64,3 +66,9 @@ #CHECK-NEXT: Section: .text #CHECK-NEXT: } #CHECK-NEXT:] + +#REGEX: Symbols [ +#REGEX-NOT: foo +#REGEX: Name: bar +#REGEX: Name: baz +#REGEX: ] Index: test/tools/llvm-objcopy/ELF/localize.test =================================================================== --- test/tools/llvm-objcopy/ELF/localize.test +++ test/tools/llvm-objcopy/ELF/localize.test @@ -6,6 +6,8 @@ # RUN: -L GlobalCommon \ # RUN: %t %t2 # RUN: llvm-readobj --symbols %t2 | FileCheck %s +# RUN: llvm-objcopy -w -L '[.]*' %t %t3 +# RUN: llvm-readobj --symbols %t3 | FileCheck %s !ELF FileHeader: Index: test/tools/llvm-objcopy/ELF/remove-section.test =================================================================== --- test/tools/llvm-objcopy/ELF/remove-section.test +++ test/tools/llvm-objcopy/ELF/remove-section.test @@ -11,6 +11,10 @@ # RUN: llvm-objcopy --remove-section=.test2 %t1 %t3 # RUN: cmp %t2 %t3 +# RUN: llvm-objcopy -w --remove-section='.test[0-9]+' %t %t4 +# RUN: llvm-readobj --file-headers --sections %t4 | FileCheck %s --check-prefix=REGEX + + !ELF FileHeader: Class: ELFCLASS64 @@ -116,3 +120,7 @@ # CHECK: EntrySize: 0 # CHECK: } # CHECK: ] + +# REGEX: SectionHeaderCount: 4 +# REGEX: Sections [ +# REGEX-NOT: test \ No newline at end of file Index: test/tools/llvm-objcopy/ELF/strip-symbol.test =================================================================== --- test/tools/llvm-objcopy/ELF/strip-symbol.test +++ test/tools/llvm-objcopy/ELF/strip-symbol.test @@ -3,6 +3,8 @@ # RUN: llvm-readobj --symbols --sections %t2 | FileCheck %s # RUN: llvm-strip --strip-symbol baz -N bar %t -o %t3 # RUN: llvm-readobj --symbols --sections %t3 | FileCheck %s +# RUN: llvm-strip -w --strip-symbol '^b[.]*' -N bar %t -o %t4 +# RUN: llvm-readobj --symbols --sections %t4 | FileCheck %s !ELF FileHeader: Index: test/tools/llvm-objcopy/ELF/weaken.test =================================================================== --- test/tools/llvm-objcopy/ELF/weaken.test +++ test/tools/llvm-objcopy/ELF/weaken.test @@ -1,6 +1,8 @@ # RUN: yaml2obj %s > %t # RUN: llvm-objcopy --weaken-symbol Global -W Local -W Weak %t %t2 # RUN: llvm-readobj --symbols %t2 | FileCheck %s +# RUN: llvm-objcopy -w --weaken-symbol '[.]*' %t %t3 +# RUN: llvm-readobj --symbols %t3 | FileCheck %s !ELF FileHeader: Index: tools/llvm-objcopy/CopyConfig.h =================================================================== --- tools/llvm-objcopy/CopyConfig.h +++ tools/llvm-objcopy/CopyConfig.h @@ -14,6 +14,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Regex.h" // Necessary for llvm::DebugCompressionType::None #include "llvm/Target/TargetOptions.h" #include @@ -48,6 +49,22 @@ Locals, // --discard-locals (-X) }; +template class NameOrRegex { + NameTy Name; + // Regex is shared between mumltiple CopyConfig instances. + std::shared_ptr R; + +public: + NameOrRegex(const NameTy &Pattern, bool IsRegex) { + if (IsRegex) + R = std::make_shared(Pattern); + else + Name = Pattern; + } + bool operator==(StringRef S) const { return R ? R->match(S) : Name == S; } + bool operator!=(StringRef S) const { return !operator==(S); } +}; + // Configuration for copying/stripping a single file. struct CopyConfig { // Main input/output options @@ -73,15 +90,15 @@ // Repeated options std::vector AddSection; std::vector DumpSection; - std::vector KeepSection; - std::vector OnlySection; - std::vector SymbolsToGlobalize; - std::vector SymbolsToKeep; - std::vector SymbolsToLocalize; - std::vector SymbolsToRemove; - std::vector SymbolsToWeaken; - std::vector ToRemove; - std::vector SymbolsToKeepGlobal; + std::vector> KeepSection; + std::vector> OnlySection; + std::vector> SymbolsToGlobalize; + std::vector> SymbolsToKeep; + std::vector> SymbolsToLocalize; + std::vector> SymbolsToRemove; + std::vector> SymbolsToWeaken; + std::vector> ToRemove; + std::vector> SymbolsToKeepGlobal; // Map options StringMap SectionsToRename; Index: tools/llvm-objcopy/CopyConfig.cpp =================================================================== --- tools/llvm-objcopy/CopyConfig.cpp +++ tools/llvm-objcopy/CopyConfig.cpp @@ -225,8 +225,9 @@ return Iter->getValue(); } -static void addGlobalSymbolsFromFile(std::vector &Symbols, - StringRef Filename) { +static void +addGlobalSymbolsFromFile(std::vector> &Symbols, + StringRef Filename, bool UseRegexp) { SmallVector Lines; auto BufOrErr = MemoryBuffer::getFile(Filename); if (!BufOrErr) @@ -238,7 +239,7 @@ // it's not empty. auto TrimmedLine = Line.split('#').first.trim(); if (!TrimmedLine.empty()) - Symbols.push_back(TrimmedLine.str()); + Symbols.emplace_back(TrimmedLine.str(), UseRegexp); } } @@ -289,6 +290,7 @@ InputArgs.hasArg(OBJCOPY_output_target))) error("--target cannot be used with --input-target or --output-target"); + bool UseRegexp = InputArgs.hasArg(OBJCOPY_regex); if (InputArgs.hasArg(OBJCOPY_target)) { Config.InputFormat = InputArgs.getLastArgValue(OBJCOPY_target); Config.OutputFormat = InputArgs.getLastArgValue(OBJCOPY_target); @@ -368,11 +370,11 @@ } for (auto Arg : InputArgs.filtered(OBJCOPY_remove_section)) - Config.ToRemove.push_back(Arg->getValue()); + Config.ToRemove.emplace_back(Arg->getValue(), UseRegexp); for (auto Arg : InputArgs.filtered(OBJCOPY_keep_section)) - Config.KeepSection.push_back(Arg->getValue()); + Config.KeepSection.emplace_back(Arg->getValue(), UseRegexp); for (auto Arg : InputArgs.filtered(OBJCOPY_only_section)) - Config.OnlySection.push_back(Arg->getValue()); + Config.OnlySection.emplace_back(Arg->getValue(), UseRegexp); for (auto Arg : InputArgs.filtered(OBJCOPY_add_section)) Config.AddSection.push_back(Arg->getValue()); for (auto Arg : InputArgs.filtered(OBJCOPY_dump_section)) @@ -397,19 +399,20 @@ Config.DecompressDebugSections = InputArgs.hasArg(OBJCOPY_decompress_debug_sections); for (auto Arg : InputArgs.filtered(OBJCOPY_localize_symbol)) - Config.SymbolsToLocalize.push_back(Arg->getValue()); + Config.SymbolsToLocalize.emplace_back(Arg->getValue(), UseRegexp); for (auto Arg : InputArgs.filtered(OBJCOPY_keep_global_symbol)) - Config.SymbolsToKeepGlobal.push_back(Arg->getValue()); + Config.SymbolsToKeepGlobal.emplace_back(Arg->getValue(), UseRegexp); for (auto Arg : InputArgs.filtered(OBJCOPY_keep_global_symbols)) - addGlobalSymbolsFromFile(Config.SymbolsToKeepGlobal, Arg->getValue()); + addGlobalSymbolsFromFile(Config.SymbolsToKeepGlobal, Arg->getValue(), + UseRegexp); for (auto Arg : InputArgs.filtered(OBJCOPY_globalize_symbol)) - Config.SymbolsToGlobalize.push_back(Arg->getValue()); + Config.SymbolsToGlobalize.emplace_back(Arg->getValue(), UseRegexp); for (auto Arg : InputArgs.filtered(OBJCOPY_weaken_symbol)) - Config.SymbolsToWeaken.push_back(Arg->getValue()); + Config.SymbolsToWeaken.emplace_back(Arg->getValue(), UseRegexp); for (auto Arg : InputArgs.filtered(OBJCOPY_strip_symbol)) - Config.SymbolsToRemove.push_back(Arg->getValue()); + Config.SymbolsToRemove.emplace_back(Arg->getValue(), UseRegexp); for (auto Arg : InputArgs.filtered(OBJCOPY_keep_symbol)) - Config.SymbolsToKeep.push_back(Arg->getValue()); + Config.SymbolsToKeep.emplace_back(Arg->getValue(), UseRegexp); Config.DeterministicArchives = InputArgs.hasFlag( OBJCOPY_enable_deterministic_archives, @@ -469,6 +472,7 @@ error("Multiple input files cannot be used in combination with -o"); CopyConfig Config; + bool UseRegexp = InputArgs.hasArg(STRIP_regex); Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug); if (InputArgs.hasArg(STRIP_discard_all, STRIP_discard_locals)) @@ -481,16 +485,16 @@ Config.StripAllGNU = InputArgs.hasArg(STRIP_strip_all_gnu); for (auto Arg : InputArgs.filtered(STRIP_keep_section)) - Config.KeepSection.push_back(Arg->getValue()); + Config.KeepSection.emplace_back(Arg->getValue(), UseRegexp); for (auto Arg : InputArgs.filtered(STRIP_remove_section)) - Config.ToRemove.push_back(Arg->getValue()); + Config.ToRemove.emplace_back(Arg->getValue(), UseRegexp); for (auto Arg : InputArgs.filtered(STRIP_strip_symbol)) - Config.SymbolsToRemove.push_back(Arg->getValue()); + Config.SymbolsToRemove.emplace_back(Arg->getValue(), UseRegexp); for (auto Arg : InputArgs.filtered(STRIP_keep_symbol)) - Config.SymbolsToKeep.push_back(Arg->getValue()); + Config.SymbolsToKeep.emplace_back(Arg->getValue(), UseRegexp); if (!Config.StripDebug && !Config.StripUnneeded && Config.DiscardMode == DiscardType::None && !Config.StripAllGNU && Config.SymbolsToRemove.empty()) Index: tools/llvm-objcopy/ObjcopyOpts.td =================================================================== --- tools/llvm-objcopy/ObjcopyOpts.td +++ tools/llvm-objcopy/ObjcopyOpts.td @@ -193,3 +193,8 @@ : Eq<"build-id-link-output", "Hard-link the output to /xx/xxx " "name derived from hex build ID">, MetaVarName<"suffix">; + +def regex + : Flag<["-", "--"], "regex">, + HelpText<"Permit regular expressions in name comparison">; +def w : Flag<["-"], "w">, Alias; Index: tools/llvm-objcopy/StripOpts.td =================================================================== --- tools/llvm-objcopy/StripOpts.td +++ tools/llvm-objcopy/StripOpts.td @@ -71,6 +71,11 @@ HelpText<"Remove all local symbols except file and section symbols">; def x : Flag<["-"], "x">, Alias; +def regex + : Flag<["-", "--"], "regex">, + HelpText<"Permit regular expressions in name comparison">; +def w : Flag<["-"], "w">, Alias; + def version : Flag<["-", "--"], "version">, HelpText<"Print the version and exit.">; def V : Flag<["-"], "V">, Alias;