[llvm-objcopy] Add --strip-unneeded-symbol(s)
Differential revision: https://reviews.llvm.org/D58027 llvm-svn: 353919
This commit is contained in:
parent
7eb4ec2879
commit
2db1062906
|
@ -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-objcopy --strip-unneeded %t.in.o %t.out.o
|
||||||
RUN: llvm-objdump -t %t.out.o | FileCheck %s --check-prefix=SYMBOLS
|
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: SYMBOL TABLE:
|
||||||
SYMBOLS-NEXT: external
|
SYMBOLS-NEXT: external
|
||||||
SYMBOLS-NEXT: external_undefined
|
SYMBOLS-NEXT: external_undefined
|
||||||
|
|
|
@ -5,6 +5,24 @@
|
||||||
# RUN: cmp %t %t1
|
# RUN: cmp %t %t1
|
||||||
# RUN: llvm-readobj --symbols %t2 | FileCheck %s
|
# 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.
|
# Verify that llvm-strip modifies the symbol table the same way.
|
||||||
# RUN: llvm-strip --strip-unneeded %t
|
# RUN: llvm-strip --strip-unneeded %t
|
||||||
# RUN: cmp %t %t2
|
# RUN: cmp %t %t2
|
||||||
|
@ -141,3 +159,7 @@ Symbols:
|
||||||
#CHECK-NEXT: Section: .text
|
#CHECK-NEXT: Section: .text
|
||||||
#CHECK-NEXT: }
|
#CHECK-NEXT: }
|
||||||
#CHECK-NEXT:]
|
#CHECK-NEXT:]
|
||||||
|
|
||||||
|
#STRIP-BAR-NOT: Name: bar ({{.*}})
|
||||||
|
#REMAIN: Name: foobar
|
||||||
|
#REMAIN: Name: foobaz
|
||||||
|
|
|
@ -151,10 +151,13 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
|
||||||
if (!Sym.Referenced) {
|
if (!Sym.Referenced) {
|
||||||
// With --strip-unneeded, GNU objcopy removes all unreferenced local
|
// With --strip-unneeded, GNU objcopy removes all unreferenced local
|
||||||
// symbols, and any unreferenced undefined external.
|
// symbols, and any unreferenced undefined external.
|
||||||
if (Config.StripUnneeded &&
|
// With --strip-unneeded-symbol we strip only specific unreferenced
|
||||||
(Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC ||
|
// local symbol instead of removing all of such.
|
||||||
Sym.Sym.SectionNumber == 0))
|
if (Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC ||
|
||||||
return true;
|
Sym.Sym.SectionNumber == 0)
|
||||||
|
if (Config.StripUnneeded ||
|
||||||
|
is_contained(Config.UnneededSymbolsToRemove, Sym.Name))
|
||||||
|
return true;
|
||||||
|
|
||||||
// GNU objcopy keeps referenced local symbols and external symbols
|
// GNU objcopy keeps referenced local symbols and external symbols
|
||||||
// if --discard-all is set, similar to what --strip-unneeded does,
|
// if --discard-all is set, similar to what --strip-unneeded does,
|
||||||
|
|
|
@ -468,6 +468,11 @@ DriverConfig parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
|
||||||
for (auto Arg : InputArgs.filtered(OBJCOPY_strip_symbols))
|
for (auto Arg : InputArgs.filtered(OBJCOPY_strip_symbols))
|
||||||
addSymbolsFromFile(Config.SymbolsToRemove, DC.Alloc, Arg->getValue(),
|
addSymbolsFromFile(Config.SymbolsToRemove, DC.Alloc, Arg->getValue(),
|
||||||
UseRegex);
|
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))
|
for (auto Arg : InputArgs.filtered(OBJCOPY_keep_symbol))
|
||||||
Config.SymbolsToKeep.emplace_back(Arg->getValue(), UseRegex);
|
Config.SymbolsToKeep.emplace_back(Arg->getValue(), UseRegex);
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,7 @@ struct CopyConfig {
|
||||||
std::vector<NameOrRegex> SymbolsToKeep;
|
std::vector<NameOrRegex> SymbolsToKeep;
|
||||||
std::vector<NameOrRegex> SymbolsToLocalize;
|
std::vector<NameOrRegex> SymbolsToLocalize;
|
||||||
std::vector<NameOrRegex> SymbolsToRemove;
|
std::vector<NameOrRegex> SymbolsToRemove;
|
||||||
|
std::vector<NameOrRegex> UnneededSymbolsToRemove;
|
||||||
std::vector<NameOrRegex> SymbolsToWeaken;
|
std::vector<NameOrRegex> SymbolsToWeaken;
|
||||||
std::vector<NameOrRegex> ToRemove;
|
std::vector<NameOrRegex> ToRemove;
|
||||||
std::vector<NameOrRegex> SymbolsToKeepGlobal;
|
std::vector<NameOrRegex> SymbolsToKeepGlobal;
|
||||||
|
|
|
@ -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
|
// This function handles the high level operations of GNU objcopy including
|
||||||
// handling command line options. It's important to outline certain properties
|
// handling command line options. It's important to outline certain properties
|
||||||
// we expect to hold of the command line operations. Any operation that "keeps"
|
// 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
|
// The purpose of this loop is to mark symbols referenced by sections
|
||||||
// (like GroupSection or RelocationSection). This way, we know which
|
// (like GroupSection or RelocationSection). This way, we know which
|
||||||
// symbols are still 'needed' and which are not.
|
// symbols are still 'needed' and which are not.
|
||||||
if (Config.StripUnneeded) {
|
if (Config.StripUnneeded || !Config.UnneededSymbolsToRemove.empty()) {
|
||||||
for (auto &Section : Obj.sections())
|
for (auto &Section : Obj.sections())
|
||||||
Section.markSymbols();
|
Section.markSymbols();
|
||||||
}
|
}
|
||||||
|
@ -359,9 +365,9 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj,
|
||||||
if (is_contained(Config.SymbolsToRemove, Sym.Name))
|
if (is_contained(Config.SymbolsToRemove, Sym.Name))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (Config.StripUnneeded && !Sym.Referenced &&
|
if ((Config.StripUnneeded ||
|
||||||
(Sym.Binding == STB_LOCAL || Sym.getShndx() == SHN_UNDEF) &&
|
is_contained(Config.UnneededSymbolsToRemove, Sym.Name)) &&
|
||||||
Sym.Type != STT_FILE && Sym.Type != STT_SECTION)
|
isUnneededSymbol(Sym))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -122,6 +122,15 @@ def strip_non_alloc : Flag<["-", "--"], "strip-non-alloc">,
|
||||||
HelpText<"Remove all non-allocated sections">;
|
HelpText<"Remove all non-allocated sections">;
|
||||||
def strip_unneeded : Flag<["-", "--"], "strip-unneeded">,
|
def strip_unneeded : Flag<["-", "--"], "strip-unneeded">,
|
||||||
HelpText<"Remove all symbols not needed by relocations">;
|
HelpText<"Remove all symbols not needed by relocations">;
|
||||||
|
defm strip_unneeded_symbol
|
||||||
|
: Eq<"strip-unneeded-symbol",
|
||||||
|
"Remove symbol <symbol> if it is not needed by relocations">,
|
||||||
|
MetaVarName<"symbol">;
|
||||||
|
defm strip_unneeded_symbols
|
||||||
|
: Eq<"strip-unneeded-symbols",
|
||||||
|
"Reads a list of symbols from <filename> and removes them "
|
||||||
|
"if they are not needed by relocations">,
|
||||||
|
MetaVarName<"filename">;
|
||||||
|
|
||||||
def extract_dwo
|
def extract_dwo
|
||||||
: Flag<["-", "--"], "extract-dwo">,
|
: Flag<["-", "--"], "extract-dwo">,
|
||||||
|
|
Loading…
Reference in New Issue