[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