Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[llvm-objcopy] Add --skip-symbol and --skip-symbols options #80873

Merged
merged 20 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions llvm/docs/CommandGuide/llvm-objcopy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this mention that this does not prevent removing symbols?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it needs to: it explicitly states the things that it impacts (name/binding/visibility). It's probably harmless to add it though.

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
Expand Down
4 changes: 4 additions & 0 deletions llvm/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,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
---------------------------------

Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/ObjCopy/CommonConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ struct CommonConfig {
NameMatcher UnneededSymbolsToRemove;
NameMatcher SymbolsToWeaken;
NameMatcher SymbolsToKeepGlobal;
NameMatcher SymbolsToSkip;

// Map options
StringMap<SectionRename> SectionsToRename;
Expand Down
8 changes: 4 additions & 4 deletions llvm/lib/ObjCopy/ConfigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() ||
Expand All @@ -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() ||
Expand All @@ -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() ||
Expand All @@ -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() ||
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
jh7370 marked this conversation as resolved.
Show resolved Hide resolved

// 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 &&
Expand Down
100 changes: 100 additions & 0 deletions llvm/test/tools/llvm-objcopy/ELF/skip-symbol.test
Original file line number Diff line number Diff line change
@@ -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: 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: echo -e "foo1 bar1\nfoo2 bar2" > %t.renames.list
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs moving earlier (it might be why the test is failing...).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs moving earlier (it might be why the test is failing...).

You're right, the test didn't fail on my machine because the file still remained from previous runs.

# 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 ]
9 changes: 9 additions & 0 deletions llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
14 changes: 14 additions & 0 deletions llvm/tools/llvm-objcopy/ObjcopyOpts.td
Original file line number Diff line number Diff line change
Expand Up @@ -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>">,
Expand Down
Loading