[llvm-objcopy] Support -X|--discard-locals.
Summary:
This adds support for the --discard-locals flag, which acts similarly to --discard-all, except it only applies to compiler-generated symbols (i.e. symbols starting with `.L` in ELF).
I am not sure about COFF local symbols: those appear to also use `.L` in most cases, but also use just `L` in other cases, so for now I am just leaving it unimplemented there.
Fixes PR36160
Reviewers: jhenderson, alexshap, jakehehrlich, mstorsjo, espindola
Reviewed By: jhenderson
Subscribers: llvm-commits, emaste, arichardson
Differential Revision: https://reviews.llvm.org/D57248
llvm-svn: 352626
diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
index c12bb34..72161e1 100644
--- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+++ b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
@@ -97,7 +97,7 @@
return true;
if (Config.StripDebug || Config.StripAll || Config.StripAllGNU ||
- Config.DiscardAll || Config.StripUnneeded) {
+ Config.DiscardMode == DiscardType::All || Config.StripUnneeded) {
if (isDebugSection(Sec) &&
(Sec.Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) != 0)
return true;
@@ -125,7 +125,7 @@
Sec.Relocs.clear();
// If we need to do per-symbol removals, initialize the Referenced field.
- if (Config.StripUnneeded || Config.DiscardAll ||
+ if (Config.StripUnneeded || Config.DiscardMode == DiscardType::All ||
!Config.SymbolsToRemove.empty())
if (Error E = Obj.markSymbols())
return E;
@@ -159,7 +159,8 @@
// GNU objcopy keeps referenced local symbols and external symbols
// if --discard-all is set, similar to what --strip-unneeded does,
// but undefined local symbols are kept when --discard-all is set.
- if (Config.DiscardAll && Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC &&
+ if (Config.DiscardMode == DiscardType::All &&
+ Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC &&
Sym.Sym.SectionNumber != 0)
return true;
}
@@ -180,7 +181,8 @@
!Config.SetSectionFlags.empty() || !Config.SymbolsToRename.empty() ||
Config.ExtractDWO || Config.KeepFileSymbols || Config.LocalizeHidden ||
Config.PreserveDates || Config.StripDWO || Config.StripNonAlloc ||
- Config.StripSections || Config.Weaken || Config.DecompressDebugSections) {
+ Config.StripSections || Config.Weaken || Config.DecompressDebugSections ||
+ Config.DiscardMode == DiscardType::Locals) {
return createStringError(llvm::errc::invalid_argument,
"Option not supported by llvm-objcopy for COFF");
}
diff --git a/llvm/tools/llvm-objcopy/CopyConfig.cpp b/llvm/tools/llvm-objcopy/CopyConfig.cpp
index 9702eb6..e72733a 100644
--- a/llvm/tools/llvm-objcopy/CopyConfig.cpp
+++ b/llvm/tools/llvm-objcopy/CopyConfig.cpp
@@ -387,7 +387,11 @@
Config.ExtractDWO = InputArgs.hasArg(OBJCOPY_extract_dwo);
Config.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden);
Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken);
- Config.DiscardAll = InputArgs.hasArg(OBJCOPY_discard_all);
+ if (InputArgs.hasArg(OBJCOPY_discard_all, OBJCOPY_discard_locals))
+ Config.DiscardMode =
+ InputArgs.hasFlag(OBJCOPY_discard_all, OBJCOPY_discard_locals)
+ ? DiscardType::All
+ : DiscardType::Locals;
Config.OnlyKeepDebug = InputArgs.hasArg(OBJCOPY_only_keep_debug);
Config.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols);
Config.DecompressDebugSections =
@@ -467,13 +471,17 @@
CopyConfig Config;
Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug);
- Config.DiscardAll = InputArgs.hasArg(STRIP_discard_all);
+ if (InputArgs.hasArg(STRIP_discard_all, STRIP_discard_locals))
+ Config.DiscardMode =
+ InputArgs.hasFlag(STRIP_discard_all, STRIP_discard_locals)
+ ? DiscardType::All
+ : DiscardType::Locals;
Config.StripUnneeded = InputArgs.hasArg(STRIP_strip_unneeded);
Config.StripAll = InputArgs.hasArg(STRIP_strip_all);
Config.StripAllGNU = InputArgs.hasArg(STRIP_strip_all_gnu);
- if (!Config.StripDebug && !Config.StripUnneeded && !Config.DiscardAll &&
- !Config.StripAllGNU)
+ if (!Config.StripDebug && !Config.StripUnneeded &&
+ Config.DiscardMode == DiscardType::None && !Config.StripAllGNU)
Config.StripAll = true;
for (auto Arg : InputArgs.filtered(STRIP_keep_section))
diff --git a/llvm/tools/llvm-objcopy/CopyConfig.h b/llvm/tools/llvm-objcopy/CopyConfig.h
index c9af373..9a9a098 100644
--- a/llvm/tools/llvm-objcopy/CopyConfig.h
+++ b/llvm/tools/llvm-objcopy/CopyConfig.h
@@ -42,6 +42,12 @@
uint64_t NewFlags;
};
+enum class DiscardType {
+ None, // Default
+ All, // --discard-all (-x)
+ Locals, // --discard-locals (-X)
+};
+
// Configuration for copying/stripping a single file.
struct CopyConfig {
// Main input/output options
@@ -62,6 +68,7 @@
Optional<StringRef> BuildIdLinkOutput;
StringRef SplitDWO;
StringRef SymbolsPrefix;
+ DiscardType DiscardMode = DiscardType::None;
// Repeated options
std::vector<StringRef> AddSection;
@@ -83,7 +90,6 @@
// Boolean options
bool DeterministicArchives = true;
- bool DiscardAll = false;
bool ExtractDWO = false;
bool KeepFileSymbols = false;
bool LocalizeHidden = false;
diff --git a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
index 7ba8db6..cbdad77 100644
--- a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
+++ b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
@@ -337,9 +337,11 @@
(Config.KeepFileSymbols && Sym.Type == STT_FILE))
return false;
- if (Config.DiscardAll && Sym.Binding == STB_LOCAL &&
- Sym.getShndx() != SHN_UNDEF && Sym.Type != STT_FILE &&
- Sym.Type != STT_SECTION)
+ if ((Config.DiscardMode == DiscardType::All ||
+ (Config.DiscardMode == DiscardType::Locals &&
+ StringRef(Sym.Name).startswith(".L"))) &&
+ Sym.Binding == STB_LOCAL && Sym.getShndx() != SHN_UNDEF &&
+ Sym.Type != STT_FILE && Sym.Type != STT_SECTION)
return true;
if (Config.StripAll || Config.StripAllGNU)
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOpts.td b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
index 9c54ad4..a25d1f3 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOpts.td
+++ b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
@@ -149,6 +149,12 @@
def W : JoinedOrSeparate<["-"], "W">, Alias<weaken_symbol>;
def weaken : Flag<["-", "--"], "weaken">,
HelpText<"Mark all global symbols as weak">;
+
+def discard_locals : Flag<["-", "--"], "discard-locals">,
+ HelpText<"Remove compiler-generated local symbols, (e.g. "
+ "symbols starting with .L)">;
+def X : Flag<["-"], "X">, Alias<discard_locals>;
+
def discard_all
: Flag<["-", "--"], "discard-all">,
HelpText<"Remove all local symbols except file and section symbols">;
diff --git a/llvm/tools/llvm-objcopy/StripOpts.td b/llvm/tools/llvm-objcopy/StripOpts.td
index fa98e27..75f7034 100644
--- a/llvm/tools/llvm-objcopy/StripOpts.td
+++ b/llvm/tools/llvm-objcopy/StripOpts.td
@@ -57,6 +57,11 @@
MetaVarName<"symbol">;
def K : JoinedOrSeparate<["-"], "K">, Alias<keep_symbol>;
+def discard_locals : Flag<["-", "--"], "discard-locals">,
+ HelpText<"Remove compiler-generated local symbols, (e.g. "
+ "symbols starting with .L)">;
+def X : Flag<["-"], "X">, Alias<discard_locals>;
+
def discard_all
: Flag<["-", "--"], "discard-all">,
HelpText<"Remove all local symbols except file and section symbols">;