mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[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
This commit is contained in:
parent
a8da5bdd63
commit
f708d3928c
26
test/tools/llvm-objcopy/wasm/basic-keep.test
Normal file
26
test/tools/llvm-objcopy/wasm/basic-keep.test
Normal file
@ -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
|
44
test/tools/llvm-objcopy/wasm/basic-only-section.test
Normal file
44
test/tools/llvm-objcopy/wasm/basic-only-section.test
Normal file
@ -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
|
46
test/tools/llvm-objcopy/wasm/basic-strip.test
Normal file
46
test/tools/llvm-objcopy/wasm/basic-strip.test
Normal file
@ -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
|
52
test/tools/llvm-objcopy/wasm/only-keep-debug.test
Normal file
52
test/tools/llvm-objcopy/wasm/only-keep-debug.test
Normal file
@ -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
|
34
test/tools/llvm-objcopy/wasm/strip-all.test
Normal file
34
test/tools/llvm-objcopy/wasm/strip-all.test
Normal file
@ -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
|
53
test/tools/llvm-objcopy/wasm/strip-debug.test
Normal file
53
test/tools/llvm-objcopy/wasm/strip-debug.test
Normal file
@ -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
|
51
test/tools/llvm-objcopy/wasm/strip-reloc.test
Normal file
51
test/tools/llvm-objcopy/wasm/strip-reloc.test
Normal file
@ -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
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user