[llvm] 7cb25f5 - [llvm-strip][WebAssembly] Support strip flags
Derek Schuff via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 14 14:17:26 PDT 2021
Author: Derek Schuff
Date: 2021-07-14T14:17:02-07:00
New Revision: 7cb25f53875e5490bccaf297accd34b7331cfb8b
URL: https://github.com/llvm/llvm-project/commit/7cb25f53875e5490bccaf297accd34b7331cfb8b
DIFF: https://github.com/llvm/llvm-project/commit/7cb25f53875e5490bccaf297accd34b7331cfb8b.diff
LOG: [llvm-strip][WebAssembly] Support strip flags
Summary:
Add support for the basic section stripping (and keeping) flags for wasm:
strip with no flags, --strip-all, --strip-debug,
--only-section, --keep-section, and --only-keep-debug.
Factor section removal into a function and use a predicate chain like
the ELF implementation.
Reviewers: jhenderson, sbc100
Differential Revision: https://reviews.llvm.org/D73820
Added:
llvm/test/tools/llvm-objcopy/wasm/basic-keep.test
llvm/test/tools/llvm-objcopy/wasm/basic-only-section.test
llvm/test/tools/llvm-objcopy/wasm/basic-strip.test
llvm/test/tools/llvm-objcopy/wasm/only-keep-debug.test
llvm/test/tools/llvm-objcopy/wasm/strip-all.test
llvm/test/tools/llvm-objcopy/wasm/strip-debug.test
llvm/test/tools/llvm-objcopy/wasm/strip-reloc.test
Modified:
llvm/tools/llvm-objcopy/ConfigManager.cpp
llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp
Removed:
################################################################################
diff --git a/llvm/test/tools/llvm-objcopy/wasm/basic-keep.test b/llvm/test/tools/llvm-objcopy/wasm/basic-keep.test
new file mode 100644
index 0000000000000..a32f08e6d79f3
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/wasm/basic-keep.test
@@ -0,0 +1,26 @@
+## Test that --keep-section keeps a debug section when stripping.
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-objcopy --strip-all --keep-section=.debug_info %t %t2
+# RUN: obj2yaml %t2 | FileCheck --implicit-check-not linking %s
+
+# CHECK: Sections:
+# CHECK: Name: .debug_info
+# CHECK-NEXT: Payload: DEADBEEF
+
+## Test that keep overrides an explicit removal.
+# RUN: llvm-objcopy --remove-section=.debug_info --keep-section=.debug_info %t %t2
+# RUN: obj2yaml %t2 | FileCheck %s --check-prefix=KEEP
+
+# KEEP: Sections:
+# KEEP: Name: .debug_info
+
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: CUSTOM
+ Name: linking
+ Version: 2
+ - Type: CUSTOM
+ Name: .debug_info
+ Payload: DEADBEEF
diff --git a/llvm/test/tools/llvm-objcopy/wasm/basic-only-section.test b/llvm/test/tools/llvm-objcopy/wasm/basic-only-section.test
new file mode 100644
index 0000000000000..f4b7d91a12367
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/wasm/basic-only-section.test
@@ -0,0 +1,44 @@
+## Test --only-section.
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-objcopy --only-section=producers %t %t2
+# RUN: obj2yaml %t2 | FileCheck --implicit-check-not TYPE --implicit-check-not linking %s
+
+## Test that it's the same with only-section + keep-section (for the same section).
+# RUN: llvm-objcopy --only-section=producers --keep-section=producers %t %t2
+# RUN: obj2yaml %t2 | FileCheck --implicit-check-not TYPE --implicit-check-not linking %s
+
+## Also test that only-section overrides remove-section.
+# RUN: llvm-objcopy --only-section=producers --remove-section=producers %t %t2
+# RUN: obj2yaml %t2 | FileCheck --implicit-check-not linking %s
+
+## This file has both known and custom sections. Check that only the producers section is left.
+# CHECK: Sections:
+# CHECK-NEXT: - Type: CUSTOM
+# CHECK-NEXT: Name: producers
+# CHECK-NEXT: Tools:
+
+## Test that only-section + keep-section keeps both sections.
+# RUN: llvm-objcopy --only-section=producers --keep-section=linking %t %t2
+# RUN: obj2yaml %t2 | FileCheck --implicit-check-not=TYPE --check-prefix=KEEP %s
+# KEEP: Name: linking
+# KEEP: Name: producers
+
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: TYPE
+ Signatures:
+ - Index: 0
+ ParamTypes:
+ - I32
+ ReturnTypes:
+ - F32
+ - Type: CUSTOM
+ Name: linking
+ Version: 2
+ - Type: CUSTOM
+ Name: producers
+ Tools:
+ - Name: clang
+ Version: 9.0.0
diff --git a/llvm/test/tools/llvm-objcopy/wasm/basic-strip.test b/llvm/test/tools/llvm-objcopy/wasm/basic-strip.test
new file mode 100644
index 0000000000000..e76de46b08e22
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/wasm/basic-strip.test
@@ -0,0 +1,46 @@
+## Test that debug, name, and producers sections are stripped with --strip-all.
+## Other sections (unknown to LLVM, such as foo) are not stripped by --strip-all.
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-strip --strip-all %t
+# RUN: obj2yaml %t | FileCheck --implicit-check-not producers --implicit-check-not .debug --implicit-check-not name %s
+
+## The default no-arg behavior is the same as --strip-all.
+# RUN: llvm-strip %t
+# RUN: obj2yaml %t | FileCheck --implicit-check-not producers --implicit-check-not .debug --implicit-check-not name %s
+
+# CHECK: Sections:
+# CHECK-NEXT: - Type: TYPE
+# CHECK: Name: foo
+
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: TYPE
+ Signatures:
+ - Index: 0
+ ParamTypes: []
+ ReturnTypes: []
+ - Type: FUNCTION
+ FunctionTypes: [ 0 ]
+ - Type: CODE
+ Functions:
+ - Index: 0
+ Locals: []
+ Body: 0B
+ - Type: CUSTOM
+ Name: name
+ FunctionNames:
+ - Index: 0
+ Name: foo
+ - Type: CUSTOM
+ Name: producers
+ Tools:
+ - Name: clang
+ Version: 9.0.0
+ - Type: CUSTOM
+ Name: .debug_info
+ Payload: DEADBEEF
+ - Type: CUSTOM
+ Name: foo
+ Payload: CAFE
diff --git a/llvm/test/tools/llvm-objcopy/wasm/only-keep-debug.test b/llvm/test/tools/llvm-objcopy/wasm/only-keep-debug.test
new file mode 100644
index 0000000000000..5db95a10e44b1
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/wasm/only-keep-debug.test
@@ -0,0 +1,52 @@
+## Test that only debug sections are kept with --only-keep-debug.
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-strip --only-keep-debug %t
+# RUN: obj2yaml %t | FileCheck %s
+
+## Test that keep-section overrides only-keep-debug.
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-strip --only-keep-debug --keep-section=foo %t
+# RUN: obj2yaml %t | FileCheck --implicit-check-not=Name --check-prefix=CHECK --check-prefix=KEEP %s
+
+# CHECK: Sections:
+# CHECK: - Type: CUSTOM
+# CHECK-NEXT: Name: .debug_info
+# CHECK: - Type: CUSTOM
+# CHECK-NEXT: Name: .debug_line
+# KEEP: Name: foo
+
+## Test that remove-section overrides only-keep-debug.
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-strip --only-keep-debug --remove-section=.debug_info %t
+# RUN: obj2yaml %t | FileCheck %s --check-prefix=NOINFO --implicit-check-not=.debug_info
+
+# NOINFO: Name: .debug_line
+
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: TYPE
+ Signatures:
+ - Index: 0
+ ParamTypes:
+ - I32
+ ReturnTypes:
+ - F32
+ - Type: CUSTOM
+ Name: .debug_info
+ Payload: CAFE1234
+ - Type: CUSTOM
+ Name: linking
+ Version: 2
+ - Type: CUSTOM
+ Name: producers
+ Tools:
+ - Name: clang
+ Version: 9.0.0
+ - Type: CUSTOM
+ Name: .debug_line
+ Payload: DEADBEEF
+ - Type: CUSTOM
+ Name: foo
+ Payload: CAFE
diff --git a/llvm/test/tools/llvm-objcopy/wasm/strip-all.test b/llvm/test/tools/llvm-objcopy/wasm/strip-all.test
new file mode 100644
index 0000000000000..9a9015713242c
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/wasm/strip-all.test
@@ -0,0 +1,34 @@
+## Test that --strip-all removes debug, linking, and producers sections, but not
+## known or unknown-custom sections.
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-objcopy --strip-all %t %t2
+# RUN: obj2yaml %t2 | FileCheck --implicit-check-not=Type: %s
+
+# CHECK: Sections:
+# CHECK-NEXT: - Type: TYPE
+# CHECK: - Type: CUSTOM
+# CHECK-NEXT: Name: foo
+
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: TYPE
+ Signatures:
+ - Index: 0
+ ParamTypes: []
+ ReturnTypes: []
+ - Type: CUSTOM
+ Name: linking
+ Version: 2
+ - Type: CUSTOM
+ Name: producers
+ Tools:
+ - Name: clang
+ Version: 9.0.0
+ - Type: CUSTOM
+ Name: .debug_info
+ Payload: DEADBEEF
+ - Type: CUSTOM
+ Name: foo
+ Payload: CAFE
diff --git a/llvm/test/tools/llvm-objcopy/wasm/strip-debug.test b/llvm/test/tools/llvm-objcopy/wasm/strip-debug.test
new file mode 100644
index 0000000000000..2747c3bab742e
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/wasm/strip-debug.test
@@ -0,0 +1,53 @@
+## Test that debug sections (but not linking or names) are stripped with --strip-debug
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-strip --strip-debug %t
+# RUN: obj2yaml %t | FileCheck --implicit-check-not=.debug %s
+
+# CHECK: Sections:
+# CHECK-NEXT: - Type: TYPE
+# CHECK: Name: linking
+# CHECK: Name: name
+# CHECK-NEXT: FunctionNames:
+# CHECK: Name: producers
+
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: TYPE
+ Signatures:
+ - Index: 0
+ ParamTypes: []
+ ReturnTypes: []
+ - Type: FUNCTION
+ FunctionTypes: [ 0 ]
+ - Type: CODE
+ Functions:
+ - Index: 0
+ Locals: []
+ Body: 0B
+ - Type: CUSTOM
+ Name: .debug_info
+ Payload: CAFE1234
+ - Type: CUSTOM
+ Name: linking
+ Version: 2
+ SymbolTable:
+ - Index: 0
+ Kind: FUNCTION
+ Name: foo
+ Flags: [ BINDING_LOCAL ]
+ Function: 0
+ - Type: CUSTOM
+ Name: name
+ FunctionNames:
+ - Index: 0
+ Name: foo
+ - Type: CUSTOM
+ Name: producers
+ Tools:
+ - Name: clang
+ Version: 9.0.0
+ - Type: CUSTOM
+ Name: .debug_line
+ Payload: DEADBEEF
diff --git a/llvm/test/tools/llvm-objcopy/wasm/strip-reloc.test b/llvm/test/tools/llvm-objcopy/wasm/strip-reloc.test
new file mode 100644
index 0000000000000..4c8d1ba670447
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/wasm/strip-reloc.test
@@ -0,0 +1,51 @@
+## Test that linking, reloc, and name sections are stripped by --strip-all.
+
+## These get a separate test because ObjectYaml understands relocs and names,
+## so the test needs to be a valid object with relocs and names.
+
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-objcopy --strip-all %t %t2
+# RUN: obj2yaml %t2 | FileCheck --implicit-check-not=Type: %s
+
+## Check that the known sections are still present.
+# CHECK: Sections:
+# CHECK: - Type: TYPE
+# CHECK: - Type: FUNCTION
+# CHECK: - Type: CODE
+## Check that there are still functions in the code section.
+# CHECK: Functions:
+
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: TYPE
+ Signatures:
+ - Index: 0
+ ParamTypes: []
+ ReturnTypes: []
+ - Type: FUNCTION
+ FunctionTypes: [ 0 ]
+ - Type: CODE
+ Relocations:
+ - Type: R_WASM_FUNCTION_INDEX_LEB
+ Index: 0
+ Offset: 0x4
+ Functions:
+ - Index: 0
+ Locals: []
+ Body: 1080808080000B
+ - Type: CUSTOM
+ Name: linking
+ Version: 2
+ SymbolTable:
+ - Index: 0
+ Kind: FUNCTION
+ Name: foo
+ Flags: [ BINDING_LOCAL ]
+ Function: 0
+ - Type: CUSTOM
+ Name: name
+ FunctionNames:
+ - Index: 0
+ Name: foo
diff --git a/llvm/tools/llvm-objcopy/ConfigManager.cpp b/llvm/tools/llvm-objcopy/ConfigManager.cpp
index 2f04e70dd6ffd..9f7d06b99418d 100644
--- a/llvm/tools/llvm-objcopy/ConfigManager.cpp
+++ b/llvm/tools/llvm-objcopy/ConfigManager.cpp
@@ -614,16 +614,15 @@ Expected<const WasmConfig &> ConfigManager::getWasmConfig() const {
!Common.AllocSectionsPrefix.empty() ||
Common.DiscardMode != DiscardType::None || ELF.NewSymbolVisibility ||
!Common.SymbolsToAdd.empty() || !Common.RPathToAdd.empty() ||
- !Common.OnlySection.empty() || !Common.SymbolsToGlobalize.empty() ||
- !Common.SymbolsToKeep.empty() || !Common.SymbolsToLocalize.empty() ||
- !Common.SymbolsToRemove.empty() ||
+ !Common.SymbolsToGlobalize.empty() || !Common.SymbolsToLocalize.empty() ||
+ !Common.SymbolsToKeep.empty() || !Common.SymbolsToRemove.empty() ||
!Common.UnneededSymbolsToRemove.empty() ||
!Common.SymbolsToWeaken.empty() || !Common.SymbolsToKeepGlobal.empty() ||
!Common.SectionsToRename.empty() || !Common.SetSectionAlignment.empty() ||
!Common.SetSectionFlags.empty() || !Common.SymbolsToRename.empty()) {
return createStringError(
llvm::errc::invalid_argument,
- "only add-section, dump-section, and remove-section are supported");
+ "only flags for section dumping, removal, and addition are supported");
}
return Wasm;
diff --git a/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp b/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp
index 75c4749167891..397d09757e54c 100644
--- a/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp
+++ b/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp
@@ -19,6 +19,23 @@ namespace objcopy {
namespace wasm {
using namespace object;
+using SectionPred = std::function<bool(const Section &Sec)>;
+
+static bool isDebugSection(const Section &Sec) {
+ return Sec.Name.startswith(".debug");
+}
+
+static bool isLinkerSection(const Section &Sec) {
+ return Sec.Name.startswith("reloc.") || Sec.Name == "linking";
+}
+
+static bool isNameSection(const Section &Sec) { return Sec.Name == "name"; }
+
+// Sections which are known to be "comments" or informational and do not affect
+// program semantics.
+static bool isCommentSection(const Section &Sec) {
+ return Sec.Name == "producers";
+}
static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
Object &Obj) {
@@ -39,6 +56,59 @@ static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
return createStringError(errc::invalid_argument, "section '%s' not found",
SecName.str().c_str());
}
+
+static void removeSections(const CommonConfig &Config, Object &Obj) {
+ SectionPred RemovePred = [](const Section &) { return false; };
+
+ // Explicitly-requested sections.
+ if (!Config.ToRemove.empty()) {
+ RemovePred = [&Config](const Section &Sec) {
+ return Config.ToRemove.matches(Sec.Name);
+ };
+ }
+
+ if (Config.StripDebug) {
+ RemovePred = [RemovePred](const Section &Sec) {
+ return RemovePred(Sec) || isDebugSection(Sec);
+ };
+ }
+
+ if (Config.StripAll) {
+ RemovePred = [RemovePred](const Section &Sec) {
+ return RemovePred(Sec) || isDebugSection(Sec) || isLinkerSection(Sec) ||
+ isNameSection(Sec) || isCommentSection(Sec);
+ };
+ }
+
+ if (Config.OnlyKeepDebug) {
+ RemovePred = [&Config](const Section &Sec) {
+ // Keep debug sections, unless explicitly requested to remove.
+ // Remove everything else, including known sections.
+ return Config.ToRemove.matches(Sec.Name) || !isDebugSection(Sec);
+ };
+ }
+
+ if (!Config.OnlySection.empty()) {
+ RemovePred = [&Config](const Section &Sec) {
+ // Explicitly keep these sections regardless of previous removes.
+ // Remove everything else, inluding known sections.
+ return !Config.OnlySection.matches(Sec.Name);
+ };
+ }
+
+ if (!Config.KeepSection.empty()) {
+ RemovePred = [&Config, RemovePred](const Section &Sec) {
+ // Explicitly keep these sections regardless of previous removes.
+ if (Config.KeepSection.matches(Sec.Name))
+ return false;
+ // Otherwise defer to RemovePred.
+ return RemovePred(Sec);
+ };
+ }
+
+ Obj.removeSections(RemovePred);
+}
+
static Error handleArgs(const CommonConfig &Config, Object &Obj) {
// Only support AddSection, DumpSection, RemoveSection for now.
for (StringRef Flag : Config.DumpSection) {
@@ -49,11 +119,7 @@ static Error handleArgs(const CommonConfig &Config, Object &Obj) {
return createFileError(FileName, std::move(E));
}
- Obj.removeSections([&Config](const Section &Sec) {
- if (Config.ToRemove.matches(Sec.Name))
- return true;
- return false;
- });
+ removeSections(Config, Obj);
for (StringRef Flag : Config.AddSection) {
StringRef SecName, FileName;
More information about the llvm-commits
mailing list