[llvm] 4946cc3 - [llvm-objcopy] Add --skip-symbol and --skip-symbols options (#80873)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 21 05:05:39 PDT 2024
Author: Ilia Kuklin
Date: 2024-03-21T17:05:35+05:00
New Revision: 4946cc37f4865b89fbebcfa0120183a11ae8d4ab
URL: https://github.com/llvm/llvm-project/commit/4946cc37f4865b89fbebcfa0120183a11ae8d4ab
DIFF: https://github.com/llvm/llvm-project/commit/4946cc37f4865b89fbebcfa0120183a11ae8d4ab.diff
LOG: [llvm-objcopy] Add --skip-symbol and --skip-symbols options (#80873)
Add --skip-symbol and --skip-symbols options that allow to skip symbols
when executing other options that can change the symbol's name, binding
or visibility, similar to an existing option --keep-symbol that keeps a
symbol from being removed by other options.
Added:
llvm/test/tools/llvm-objcopy/ELF/skip-symbol.test
Modified:
llvm/docs/CommandGuide/llvm-objcopy.rst
llvm/docs/ReleaseNotes.rst
llvm/include/llvm/ObjCopy/CommonConfig.h
llvm/lib/ObjCopy/ConfigManager.cpp
llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
llvm/tools/llvm-objcopy/ObjcopyOpts.td
Removed:
################################################################################
diff --git a/llvm/docs/CommandGuide/llvm-objcopy.rst b/llvm/docs/CommandGuide/llvm-objcopy.rst
index 9d0cb7ad119589..985d16eb11cfb6 100644
--- a/llvm/docs/CommandGuide/llvm-objcopy.rst
+++ b/llvm/docs/CommandGuide/llvm-objcopy.rst
@@ -464,6 +464,19 @@ them.
Read a list of symbols from <filename> and change their visibility to the
specified value. Visibility values: default, internal, hidden, protected.
+.. option:: --skip-symbol <symbol>
+
+ Do not change the parameters of symbol ``<symbol>`` when executing other
+ options that can change the symbol's name, binding or visibility.
+
+.. option:: --skip-symbols <filename>
+
+ Do not change the parameters of symbols named in the file ``<filename>`` when
+ executing other options that can change the symbol's name, binding or
+ visibility. In the file, each line represents a single symbol, with leading
+ and trailing whitespace ignored, as is anything following a '#'.
+ Can be specified multiple times to read names from multiple files.
+
.. option:: --split-dwo <dwo-file>
Equivalent to running :program:`llvm-objcopy` with :option:`--extract-dwo` and
diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 03691efe836fe8..01ecbdba5060b0 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -175,6 +175,10 @@ Changes to the LLVM tools
``--set-symbols-visibility`` options for ELF input to change the
visibility of symbols.
+* llvm-objcopy now supports ``--skip-symbol`` and ``--skip-symbols`` options
+ for ELF input to skip the specified symbols when executing other options
+ that can change a symbol's name, binding or visibility.
+
Changes to LLDB
---------------------------------
diff --git a/llvm/include/llvm/ObjCopy/CommonConfig.h b/llvm/include/llvm/ObjCopy/CommonConfig.h
index 8f69c9fbeaf5ef..9d6d5fb23b18e7 100644
--- a/llvm/include/llvm/ObjCopy/CommonConfig.h
+++ b/llvm/include/llvm/ObjCopy/CommonConfig.h
@@ -233,6 +233,7 @@ struct CommonConfig {
NameMatcher UnneededSymbolsToRemove;
NameMatcher SymbolsToWeaken;
NameMatcher SymbolsToKeepGlobal;
+ NameMatcher SymbolsToSkip;
// Map options
StringMap<SectionRename> SectionsToRename;
diff --git a/llvm/lib/ObjCopy/ConfigManager.cpp b/llvm/lib/ObjCopy/ConfigManager.cpp
index e46b595a56dc44..6442f1b958fb4d 100644
--- a/llvm/lib/ObjCopy/ConfigManager.cpp
+++ b/llvm/lib/ObjCopy/ConfigManager.cpp
@@ -15,7 +15,7 @@ namespace objcopy {
Expected<const COFFConfig &> ConfigManager::getCOFFConfig() const {
if (!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
- !Common.SymbolsPrefixRemove.empty() ||
+ !Common.SymbolsPrefixRemove.empty() || !Common.SymbolsToSkip.empty() ||
!Common.AllocSectionsPrefix.empty() || !Common.KeepSection.empty() ||
!Common.SymbolsToGlobalize.empty() || !Common.SymbolsToKeep.empty() ||
!Common.SymbolsToLocalize.empty() || !Common.SymbolsToWeaken.empty() ||
@@ -34,7 +34,7 @@ Expected<const COFFConfig &> ConfigManager::getCOFFConfig() const {
Expected<const MachOConfig &> ConfigManager::getMachOConfig() const {
if (!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
- !Common.SymbolsPrefixRemove.empty() ||
+ !Common.SymbolsPrefixRemove.empty() || !Common.SymbolsToSkip.empty() ||
!Common.AllocSectionsPrefix.empty() || !Common.KeepSection.empty() ||
!Common.SymbolsToGlobalize.empty() || !Common.SymbolsToKeep.empty() ||
!Common.SymbolsToLocalize.empty() ||
@@ -56,7 +56,7 @@ Expected<const MachOConfig &> ConfigManager::getMachOConfig() const {
Expected<const WasmConfig &> ConfigManager::getWasmConfig() const {
if (!Common.AddGnuDebugLink.empty() || Common.ExtractPartition ||
!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
- !Common.SymbolsPrefixRemove.empty() ||
+ !Common.SymbolsPrefixRemove.empty() || !Common.SymbolsToSkip.empty() ||
!Common.AllocSectionsPrefix.empty() ||
Common.DiscardMode != DiscardType::None || !Common.SymbolsToAdd.empty() ||
!Common.SymbolsToGlobalize.empty() || !Common.SymbolsToLocalize.empty() ||
@@ -77,7 +77,7 @@ Expected<const WasmConfig &> ConfigManager::getWasmConfig() const {
Expected<const XCOFFConfig &> ConfigManager::getXCOFFConfig() const {
if (!Common.AddGnuDebugLink.empty() || Common.ExtractPartition ||
!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
- !Common.SymbolsPrefixRemove.empty() ||
+ !Common.SymbolsPrefixRemove.empty() || !Common.SymbolsToSkip.empty() ||
!Common.AllocSectionsPrefix.empty() ||
Common.DiscardMode != DiscardType::None || !Common.AddSection.empty() ||
!Common.DumpSection.empty() || !Common.SymbolsToAdd.empty() ||
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index e4d6e02f3aa60d..205bc1ef5b1a19 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -291,6 +291,9 @@ static Error updateAndRemoveSymbols(const CommonConfig &Config,
return Error::success();
Obj.SymbolTable->updateSymbols([&](Symbol &Sym) {
+ if (Config.SymbolsToSkip.matches(Sym.Name))
+ return;
+
// Common and undefined symbols don't make sense as local symbols, and can
// even cause crashes if we localize those, so skip them.
if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF &&
diff --git a/llvm/test/tools/llvm-objcopy/ELF/skip-symbol.test b/llvm/test/tools/llvm-objcopy/ELF/skip-symbol.test
new file mode 100644
index 00000000000000..0f3ab808482ba5
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/skip-symbol.test
@@ -0,0 +1,100 @@
+## This test checks the functionality of options --skip-symbol and --skip-symbols.
+# RUN: yaml2obj %s -o %t.o
+# RUN: echo 'foo[2-3]' > %t.skip.regex
+
+## Check --skip-symbol functionality when changing symbol bindings.
+# RUN: llvm-objcopy %t.o %t2.o --localize-hidden --skip-symbol=foo3
+# RUN: llvm-readelf -s %t2.o | FileCheck %s --check-prefix=LH-SYM
+# LH-SYM-DAG: LOCAL HIDDEN 1 foo1
+# LH-SYM-DAG: LOCAL HIDDEN 1 foo2
+# LH-SYM-DAG: GLOBAL HIDDEN 1 foo3
+# LH-SYM-DAG: LOCAL HIDDEN 1 foo4
+# LH-SYM-DAG: LOCAL HIDDEN 1 foo5
+
+## Check --skip-symbols functionality when changing symbol bindings.
+# RUN: llvm-objcopy %t.o %t1.o --localize-hidden --skip-symbols=%t.skip.regex --regex
+# RUN: llvm-readelf -s %t1.o | FileCheck %s --check-prefix=LH-SYMS
+# LH-SYMS-DAG: LOCAL HIDDEN 1 foo1
+# LH-SYMS-DAG: GLOBAL HIDDEN 1 foo2
+# LH-SYMS-DAG: GLOBAL HIDDEN 1 foo3
+# LH-SYMS-DAG: LOCAL HIDDEN 1 foo4
+# LH-SYMS-DAG: LOCAL HIDDEN 1 foo5
+
+## Check --skip-symbol functionality when changing symbol names.
+# RUN: echo -e "foo1 bar1\nfoo2 bar2" > %t.renames.list
+# RUN: llvm-objcopy %t.o %t4.o --redefine-syms=%t.renames.list \
+# RUN: --skip-symbol='fo*' --wildcard
+# RUN: llvm-readelf -s %t4.o | FileCheck %s --check-prefix=RS-SYM
+# RS-SYM-DAG: foo1
+# RS-SYM-DAG: foo2
+# RS-SYM-DAG: foo3
+# RS-SYM-DAG: foo4
+# RS-SYM-DAG: foo5
+
+## Check --skip-symbols functionality when changing symbol names.
+# RUN: llvm-objcopy %t.o %t3.o --redefine-syms=%t.renames.list \
+# RUN: --skip-symbols=%t.skip.regex --regex
+# RUN: llvm-readelf -s %t3.o | FileCheck %s --check-prefix=RS-SYMS
+# RS-SYMS-DAG: bar1
+# RS-SYMS-DAG: foo2
+# RS-SYMS-DAG: foo3
+# RS-SYMS-DAG: foo4
+# RS-SYMS-DAG: foo5
+
+## Check the functionality when using skip options multiple times.
+# RUN: echo "foo3" > %t.symbol0.list
+# RUN: echo "foo4" > %t.symbol1.list
+# RUN: llvm-objcopy %t.o %t5.o --set-symbol-visibility='foo*'=internal --wildcard \
+# RUN: --skip-symbol=foo1 --skip-symbol=foo2 \
+# RUN: --skip-symbols=%t.symbol0.list --skip-symbols=%t.symbol1.list
+# RUN: llvm-readelf -s %t5.o | FileCheck %s --check-prefix=BOTH
+# BOTH-DAG: GLOBAL HIDDEN 1 foo1
+# BOTH-DAG: GLOBAL HIDDEN 1 foo2
+# BOTH-DAG: GLOBAL HIDDEN 1 foo3
+# BOTH-DAG: GLOBAL HIDDEN 1 foo4
+## Only foo5 is not skipped.
+# BOTH-DAG: GLOBAL INTERNAL 1 foo5
+
+## Check that using an invalid symbol name regex generates an error.
+# RUN: echo '*.' > %t.symbols.regex
+# RUN: not llvm-objcopy %t.o --skip-symbols=%t.symbols.regex --regex 2>&1 | \
+# RUN: FileCheck %s --check-prefix=SYMBOL
+# RUN: not llvm-objcopy %t.o --skip-symbol='*.' --regex 2>&1 | \
+# RUN: FileCheck %s --check-prefix=SYMBOL
+# SYMBOL: error: cannot compile regular expression '*.': repetition-operator operand invalid
+
+## Check passing an invalid filename generates an error.
+# RUN: not llvm-objcopy %t.o --skip-symbols=no_file 2>&1 | \
+# RUN: FileCheck %s --check-prefix=FILE -DMSG=%errc_ENOENT
+# FILE: error: 'no_file': [[MSG]]
+
+!ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+Symbols:
+ - Name: foo1
+ Section: .text
+ Binding: STB_GLOBAL
+ Other: [ STV_HIDDEN ]
+ - Name: foo2
+ Section: .text
+ Binding: STB_GLOBAL
+ Other: [ STV_HIDDEN ]
+ - Name: foo3
+ Section: .text
+ Binding: STB_GLOBAL
+ Other: [ STV_HIDDEN ]
+ - Name: foo4
+ Section: .text
+ Binding: STB_GLOBAL
+ Other: [ STV_HIDDEN ]
+ - Name: foo5
+ Section: .text
+ Binding: STB_GLOBAL
+ Other: [ STV_HIDDEN ]
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index a0c6415bf0e6ae..7269c51a08d6b5 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -978,6 +978,15 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
addSymbolsFromFile(Config.SymbolsToKeep, DC.Alloc, Arg->getValue(),
SymbolMatchStyle, ErrorCallback))
return std::move(E);
+ for (auto *Arg : InputArgs.filtered(OBJCOPY_skip_symbol))
+ if (Error E = Config.SymbolsToSkip.addMatcher(NameOrPattern::create(
+ Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
+ return std::move(E);
+ for (auto *Arg : InputArgs.filtered(OBJCOPY_skip_symbols))
+ if (Error E =
+ addSymbolsFromFile(Config.SymbolsToSkip, DC.Alloc, Arg->getValue(),
+ SymbolMatchStyle, ErrorCallback))
+ return std::move(E);
for (auto *Arg : InputArgs.filtered(OBJCOPY_add_symbol)) {
Expected<NewSymbolInfo> SymInfo = parseNewSymbolInfo(Arg->getValue());
if (!SymInfo)
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOpts.td b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
index 3c0e5cd475a36b..be02616e8c68e3 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOpts.td
+++ b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
@@ -206,6 +206,20 @@ defm keep_symbols
"be repeated to read symbols from many files">,
MetaVarName<"filename">;
+defm skip_symbol : Eq<"skip-symbol", "Do not change parameters of symbol <symbol> "
+ "when executing other options that can change the symbol's "
+ "name, binding or visibility">,
+ MetaVarName<"symbol">;
+
+defm skip_symbols
+ : Eq<"skip-symbols",
+ "Read a list of symbols from <filename> and run as if "
+ "--skip-symbol=<symbol> is set for each one. <filename> "
+ "contains one symbol per line and may contain comments beginning with "
+ "'#'. Leading and trailing whitespace is stripped from each line. May "
+ "be repeated to read symbols from many files">,
+ MetaVarName<"filename">;
+
defm dump_section
: Eq<"dump-section",
"Dump contents of section named <section> into file <file>">,
More information about the llvm-commits
mailing list