Skip to content

Commit 4946cc3

Browse files
authored
[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.
1 parent 2699072 commit 4946cc3

File tree

8 files changed

+148
-4
lines changed

8 files changed

+148
-4
lines changed

llvm/docs/CommandGuide/llvm-objcopy.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,19 @@ them.
464464
Read a list of symbols from <filename> and change their visibility to the
465465
specified value. Visibility values: default, internal, hidden, protected.
466466

467+
.. option:: --skip-symbol <symbol>
468+
469+
Do not change the parameters of symbol ``<symbol>`` when executing other
470+
options that can change the symbol's name, binding or visibility.
471+
472+
.. option:: --skip-symbols <filename>
473+
474+
Do not change the parameters of symbols named in the file ``<filename>`` when
475+
executing other options that can change the symbol's name, binding or
476+
visibility. In the file, each line represents a single symbol, with leading
477+
and trailing whitespace ignored, as is anything following a '#'.
478+
Can be specified multiple times to read names from multiple files.
479+
467480
.. option:: --split-dwo <dwo-file>
468481

469482
Equivalent to running :program:`llvm-objcopy` with :option:`--extract-dwo` and

llvm/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ Changes to the LLVM tools
175175
``--set-symbols-visibility`` options for ELF input to change the
176176
visibility of symbols.
177177

178+
* llvm-objcopy now supports ``--skip-symbol`` and ``--skip-symbols`` options
179+
for ELF input to skip the specified symbols when executing other options
180+
that can change a symbol's name, binding or visibility.
181+
178182
Changes to LLDB
179183
---------------------------------
180184

llvm/include/llvm/ObjCopy/CommonConfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ struct CommonConfig {
233233
NameMatcher UnneededSymbolsToRemove;
234234
NameMatcher SymbolsToWeaken;
235235
NameMatcher SymbolsToKeepGlobal;
236+
NameMatcher SymbolsToSkip;
236237

237238
// Map options
238239
StringMap<SectionRename> SectionsToRename;

llvm/lib/ObjCopy/ConfigManager.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace objcopy {
1515

1616
Expected<const COFFConfig &> ConfigManager::getCOFFConfig() const {
1717
if (!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
18-
!Common.SymbolsPrefixRemove.empty() ||
18+
!Common.SymbolsPrefixRemove.empty() || !Common.SymbolsToSkip.empty() ||
1919
!Common.AllocSectionsPrefix.empty() || !Common.KeepSection.empty() ||
2020
!Common.SymbolsToGlobalize.empty() || !Common.SymbolsToKeep.empty() ||
2121
!Common.SymbolsToLocalize.empty() || !Common.SymbolsToWeaken.empty() ||
@@ -34,7 +34,7 @@ Expected<const COFFConfig &> ConfigManager::getCOFFConfig() const {
3434

3535
Expected<const MachOConfig &> ConfigManager::getMachOConfig() const {
3636
if (!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
37-
!Common.SymbolsPrefixRemove.empty() ||
37+
!Common.SymbolsPrefixRemove.empty() || !Common.SymbolsToSkip.empty() ||
3838
!Common.AllocSectionsPrefix.empty() || !Common.KeepSection.empty() ||
3939
!Common.SymbolsToGlobalize.empty() || !Common.SymbolsToKeep.empty() ||
4040
!Common.SymbolsToLocalize.empty() ||
@@ -56,7 +56,7 @@ Expected<const MachOConfig &> ConfigManager::getMachOConfig() const {
5656
Expected<const WasmConfig &> ConfigManager::getWasmConfig() const {
5757
if (!Common.AddGnuDebugLink.empty() || Common.ExtractPartition ||
5858
!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
59-
!Common.SymbolsPrefixRemove.empty() ||
59+
!Common.SymbolsPrefixRemove.empty() || !Common.SymbolsToSkip.empty() ||
6060
!Common.AllocSectionsPrefix.empty() ||
6161
Common.DiscardMode != DiscardType::None || !Common.SymbolsToAdd.empty() ||
6262
!Common.SymbolsToGlobalize.empty() || !Common.SymbolsToLocalize.empty() ||
@@ -77,7 +77,7 @@ Expected<const WasmConfig &> ConfigManager::getWasmConfig() const {
7777
Expected<const XCOFFConfig &> ConfigManager::getXCOFFConfig() const {
7878
if (!Common.AddGnuDebugLink.empty() || Common.ExtractPartition ||
7979
!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
80-
!Common.SymbolsPrefixRemove.empty() ||
80+
!Common.SymbolsPrefixRemove.empty() || !Common.SymbolsToSkip.empty() ||
8181
!Common.AllocSectionsPrefix.empty() ||
8282
Common.DiscardMode != DiscardType::None || !Common.AddSection.empty() ||
8383
!Common.DumpSection.empty() || !Common.SymbolsToAdd.empty() ||

llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,9 @@ static Error updateAndRemoveSymbols(const CommonConfig &Config,
291291
return Error::success();
292292

293293
Obj.SymbolTable->updateSymbols([&](Symbol &Sym) {
294+
if (Config.SymbolsToSkip.matches(Sym.Name))
295+
return;
296+
294297
// Common and undefined symbols don't make sense as local symbols, and can
295298
// even cause crashes if we localize those, so skip them.
296299
if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF &&
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
## This test checks the functionality of options --skip-symbol and --skip-symbols.
2+
# RUN: yaml2obj %s -o %t.o
3+
# RUN: echo 'foo[2-3]' > %t.skip.regex
4+
5+
## Check --skip-symbol functionality when changing symbol bindings.
6+
# RUN: llvm-objcopy %t.o %t2.o --localize-hidden --skip-symbol=foo3
7+
# RUN: llvm-readelf -s %t2.o | FileCheck %s --check-prefix=LH-SYM
8+
# LH-SYM-DAG: LOCAL HIDDEN 1 foo1
9+
# LH-SYM-DAG: LOCAL HIDDEN 1 foo2
10+
# LH-SYM-DAG: GLOBAL HIDDEN 1 foo3
11+
# LH-SYM-DAG: LOCAL HIDDEN 1 foo4
12+
# LH-SYM-DAG: LOCAL HIDDEN 1 foo5
13+
14+
## Check --skip-symbols functionality when changing symbol bindings.
15+
# RUN: llvm-objcopy %t.o %t1.o --localize-hidden --skip-symbols=%t.skip.regex --regex
16+
# RUN: llvm-readelf -s %t1.o | FileCheck %s --check-prefix=LH-SYMS
17+
# LH-SYMS-DAG: LOCAL HIDDEN 1 foo1
18+
# LH-SYMS-DAG: GLOBAL HIDDEN 1 foo2
19+
# LH-SYMS-DAG: GLOBAL HIDDEN 1 foo3
20+
# LH-SYMS-DAG: LOCAL HIDDEN 1 foo4
21+
# LH-SYMS-DAG: LOCAL HIDDEN 1 foo5
22+
23+
## Check --skip-symbol functionality when changing symbol names.
24+
# RUN: echo -e "foo1 bar1\nfoo2 bar2" > %t.renames.list
25+
# RUN: llvm-objcopy %t.o %t4.o --redefine-syms=%t.renames.list \
26+
# RUN: --skip-symbol='fo*' --wildcard
27+
# RUN: llvm-readelf -s %t4.o | FileCheck %s --check-prefix=RS-SYM
28+
# RS-SYM-DAG: foo1
29+
# RS-SYM-DAG: foo2
30+
# RS-SYM-DAG: foo3
31+
# RS-SYM-DAG: foo4
32+
# RS-SYM-DAG: foo5
33+
34+
## Check --skip-symbols functionality when changing symbol names.
35+
# RUN: llvm-objcopy %t.o %t3.o --redefine-syms=%t.renames.list \
36+
# RUN: --skip-symbols=%t.skip.regex --regex
37+
# RUN: llvm-readelf -s %t3.o | FileCheck %s --check-prefix=RS-SYMS
38+
# RS-SYMS-DAG: bar1
39+
# RS-SYMS-DAG: foo2
40+
# RS-SYMS-DAG: foo3
41+
# RS-SYMS-DAG: foo4
42+
# RS-SYMS-DAG: foo5
43+
44+
## Check the functionality when using skip options multiple times.
45+
# RUN: echo "foo3" > %t.symbol0.list
46+
# RUN: echo "foo4" > %t.symbol1.list
47+
# RUN: llvm-objcopy %t.o %t5.o --set-symbol-visibility='foo*'=internal --wildcard \
48+
# RUN: --skip-symbol=foo1 --skip-symbol=foo2 \
49+
# RUN: --skip-symbols=%t.symbol0.list --skip-symbols=%t.symbol1.list
50+
# RUN: llvm-readelf -s %t5.o | FileCheck %s --check-prefix=BOTH
51+
# BOTH-DAG: GLOBAL HIDDEN 1 foo1
52+
# BOTH-DAG: GLOBAL HIDDEN 1 foo2
53+
# BOTH-DAG: GLOBAL HIDDEN 1 foo3
54+
# BOTH-DAG: GLOBAL HIDDEN 1 foo4
55+
## Only foo5 is not skipped.
56+
# BOTH-DAG: GLOBAL INTERNAL 1 foo5
57+
58+
## Check that using an invalid symbol name regex generates an error.
59+
# RUN: echo '*.' > %t.symbols.regex
60+
# RUN: not llvm-objcopy %t.o --skip-symbols=%t.symbols.regex --regex 2>&1 | \
61+
# RUN: FileCheck %s --check-prefix=SYMBOL
62+
# RUN: not llvm-objcopy %t.o --skip-symbol='*.' --regex 2>&1 | \
63+
# RUN: FileCheck %s --check-prefix=SYMBOL
64+
# SYMBOL: error: cannot compile regular expression '*.': repetition-operator operand invalid
65+
66+
## Check passing an invalid filename generates an error.
67+
# RUN: not llvm-objcopy %t.o --skip-symbols=no_file 2>&1 | \
68+
# RUN: FileCheck %s --check-prefix=FILE -DMSG=%errc_ENOENT
69+
# FILE: error: 'no_file': [[MSG]]
70+
71+
!ELF
72+
FileHeader:
73+
Class: ELFCLASS64
74+
Data: ELFDATA2LSB
75+
Type: ET_REL
76+
Machine: EM_X86_64
77+
Sections:
78+
- Name: .text
79+
Type: SHT_PROGBITS
80+
Symbols:
81+
- Name: foo1
82+
Section: .text
83+
Binding: STB_GLOBAL
84+
Other: [ STV_HIDDEN ]
85+
- Name: foo2
86+
Section: .text
87+
Binding: STB_GLOBAL
88+
Other: [ STV_HIDDEN ]
89+
- Name: foo3
90+
Section: .text
91+
Binding: STB_GLOBAL
92+
Other: [ STV_HIDDEN ]
93+
- Name: foo4
94+
Section: .text
95+
Binding: STB_GLOBAL
96+
Other: [ STV_HIDDEN ]
97+
- Name: foo5
98+
Section: .text
99+
Binding: STB_GLOBAL
100+
Other: [ STV_HIDDEN ]

llvm/tools/llvm-objcopy/ObjcopyOptions.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,15 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
978978
addSymbolsFromFile(Config.SymbolsToKeep, DC.Alloc, Arg->getValue(),
979979
SymbolMatchStyle, ErrorCallback))
980980
return std::move(E);
981+
for (auto *Arg : InputArgs.filtered(OBJCOPY_skip_symbol))
982+
if (Error E = Config.SymbolsToSkip.addMatcher(NameOrPattern::create(
983+
Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
984+
return std::move(E);
985+
for (auto *Arg : InputArgs.filtered(OBJCOPY_skip_symbols))
986+
if (Error E =
987+
addSymbolsFromFile(Config.SymbolsToSkip, DC.Alloc, Arg->getValue(),
988+
SymbolMatchStyle, ErrorCallback))
989+
return std::move(E);
981990
for (auto *Arg : InputArgs.filtered(OBJCOPY_add_symbol)) {
982991
Expected<NewSymbolInfo> SymInfo = parseNewSymbolInfo(Arg->getValue());
983992
if (!SymInfo)

llvm/tools/llvm-objcopy/ObjcopyOpts.td

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,20 @@ defm keep_symbols
206206
"be repeated to read symbols from many files">,
207207
MetaVarName<"filename">;
208208

209+
defm skip_symbol : Eq<"skip-symbol", "Do not change parameters of symbol <symbol> "
210+
"when executing other options that can change the symbol's "
211+
"name, binding or visibility">,
212+
MetaVarName<"symbol">;
213+
214+
defm skip_symbols
215+
: Eq<"skip-symbols",
216+
"Read a list of symbols from <filename> and run as if "
217+
"--skip-symbol=<symbol> is set for each one. <filename> "
218+
"contains one symbol per line and may contain comments beginning with "
219+
"'#'. Leading and trailing whitespace is stripped from each line. May "
220+
"be repeated to read symbols from many files">,
221+
MetaVarName<"filename">;
222+
209223
defm dump_section
210224
: Eq<"dump-section",
211225
"Dump contents of section named <section> into file <file>">,

0 commit comments

Comments
 (0)