aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2024-08-19 21:52:17 -0700
committerGitHub <noreply@github.com>2024-08-19 21:52:17 -0700
commit2a6136e552d24b6bf665c42a6e32efc0b2d88fbf (patch)
treeb7d9248a47553484ea96fd958bd0cbc7482f385b
parent5403123197f8e331d3c2c24d82439ca1fe7e702d (diff)
downloadllvm-upstream/main.zip
llvm-upstream/main.tar.gz
llvm-upstream/main.tar.bz2
[llvm-objcopy][WebAssembly] Allow --strip-debug to operate on relocatable files. (#102978)upstream/main
This change is enough to allow `--strip-debug` to work on object files, without breaking the relocation information or symbol table. A more complete version of this change would instead reconstruct the symbol table and relocation sections, but that is much larger change. Bug: #102002
-rw-r--r--lld/wasm/Writer.cpp5
-rw-r--r--llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp2
-rw-r--r--llvm/lib/ObjCopy/wasm/WasmObject.cpp18
-rw-r--r--llvm/lib/ObjCopy/wasm/WasmObject.h1
-rw-r--r--llvm/lib/ObjCopy/wasm/WasmReader.cpp1
-rw-r--r--llvm/lib/ObjectYAML/WasmEmitter.cpp3
-rw-r--r--llvm/test/ObjectYAML/wasm/invalid_section_order.yaml2
-rw-r--r--llvm/test/tools/llvm-objcopy/wasm/basic-only-section.test16
-rw-r--r--llvm/test/tools/llvm-objcopy/wasm/only-keep-debug.test38
-rw-r--r--llvm/test/tools/llvm-objcopy/wasm/strip-all.test6
-rw-r--r--llvm/test/tools/llvm-objcopy/wasm/strip-debug.test71
-rw-r--r--llvm/test/tools/llvm-objcopy/wasm/strip-reloc.test4
12 files changed, 132 insertions, 35 deletions
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index 6a66a29..6beef81 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -138,6 +138,11 @@ void Writer::calculateCustomSections() {
// Exclude COMDAT sections that are not selected for inclusion
if (section->discarded)
continue;
+ // Ignore empty custom sections. In particular objcopy/strip will
+ // sometimes replace stripped sections with empty custom sections to
+ // avoid section re-numbering.
+ if (section->getSize() == 0)
+ continue;
StringRef name = section->name;
// These custom sections are known the linker and synthesized rather than
// blindly copied.
diff --git a/llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp b/llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp
index 5bba1dea..cf3d884 100644
--- a/llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp
+++ b/llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp
@@ -22,7 +22,7 @@ using namespace object;
using SectionPred = std::function<bool(const Section &Sec)>;
static bool isDebugSection(const Section &Sec) {
- return Sec.Name.starts_with(".debug");
+ return Sec.Name.starts_with(".debug") || Sec.Name.starts_with("reloc..debug");
}
static bool isLinkerSection(const Section &Sec) {
diff --git a/llvm/lib/ObjCopy/wasm/WasmObject.cpp b/llvm/lib/ObjCopy/wasm/WasmObject.cpp
index 28a2de6..0b543b7 100644
--- a/llvm/lib/ObjCopy/wasm/WasmObject.cpp
+++ b/llvm/lib/ObjCopy/wasm/WasmObject.cpp
@@ -25,8 +25,22 @@ void Object::addSectionWithOwnedContents(
}
void Object::removeSections(function_ref<bool(const Section &)> ToRemove) {
- // TODO: remove reloc sections for the removed section, handle symbols, etc.
- llvm::erase_if(Sections, ToRemove);
+ if (isRelocatableObject) {
+ // For relocatable objects, avoid actually removing any sections,
+ // since that can invalidate the symbol table and relocation sections.
+ // TODO: Allow removal of sections by re-generating symbol table and
+ // relocation sections here instead.
+ for (auto &Sec : Sections) {
+ if (ToRemove(Sec)) {
+ Sec.Name = ".objcopy.removed";
+ Sec.SectionType = wasm::WASM_SEC_CUSTOM;
+ Sec.Contents = {};
+ Sec.HeaderSecSizeEncodingLen = std::nullopt;
+ }
+ }
+ } else {
+ llvm::erase_if(Sections, ToRemove);
+ }
}
} // end namespace wasm
diff --git a/llvm/lib/ObjCopy/wasm/WasmObject.h b/llvm/lib/ObjCopy/wasm/WasmObject.h
index f860ec6..374e523 100644
--- a/llvm/lib/ObjCopy/wasm/WasmObject.h
+++ b/llvm/lib/ObjCopy/wasm/WasmObject.h
@@ -32,6 +32,7 @@ struct Object {
llvm::wasm::WasmObjectHeader Header;
// For now don't discriminate between kinds of sections.
std::vector<Section> Sections;
+ bool isRelocatableObject = false;
void addSectionWithOwnedContents(Section NewSection,
std::unique_ptr<MemoryBuffer> &&Content);
diff --git a/llvm/lib/ObjCopy/wasm/WasmReader.cpp b/llvm/lib/ObjCopy/wasm/WasmReader.cpp
index 578e789..420d17f 100644
--- a/llvm/lib/ObjCopy/wasm/WasmReader.cpp
+++ b/llvm/lib/ObjCopy/wasm/WasmReader.cpp
@@ -18,6 +18,7 @@ using namespace llvm::wasm;
Expected<std::unique_ptr<Object>> Reader::create() const {
auto Obj = std::make_unique<Object>();
Obj->Header = WasmObj.getHeader();
+ Obj->isRelocatableObject = WasmObj.isRelocatableObject();
std::vector<Section> Sections;
Obj->Sections.reserve(WasmObj.getNumSections());
for (const SectionRef &Sec : WasmObj.sections()) {
diff --git a/llvm/lib/ObjectYAML/WasmEmitter.cpp b/llvm/lib/ObjectYAML/WasmEmitter.cpp
index 9b8fd11..4f38492 100644
--- a/llvm/lib/ObjectYAML/WasmEmitter.cpp
+++ b/llvm/lib/ObjectYAML/WasmEmitter.cpp
@@ -604,7 +604,8 @@ bool WasmWriter::writeWasm(raw_ostream &OS) {
if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
SecName = S->Name;
if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
- reportError("out of order section type: " + Twine(Sec->Type));
+ reportError("out of order section type: " +
+ wasm::sectionTypeToString(Sec->Type));
return false;
}
encodeULEB128(Sec->Type, OS);
diff --git a/llvm/test/ObjectYAML/wasm/invalid_section_order.yaml b/llvm/test/ObjectYAML/wasm/invalid_section_order.yaml
index 7176757..08319e5 100644
--- a/llvm/test/ObjectYAML/wasm/invalid_section_order.yaml
+++ b/llvm/test/ObjectYAML/wasm/invalid_section_order.yaml
@@ -14,7 +14,7 @@ Sections:
- Index: 0
Locals: []
Body: 0B
- # CHECK: yaml2obj: error: out of order section type: 3
+ # CHECK: yaml2obj: error: out of order section type: FUNCTION
- Type: FUNCTION
FunctionTypes: [ 0 ]
...
diff --git a/llvm/test/tools/llvm-objcopy/wasm/basic-only-section.test b/llvm/test/tools/llvm-objcopy/wasm/basic-only-section.test
index fe47d5c..f30743c 100644
--- a/llvm/test/tools/llvm-objcopy/wasm/basic-only-section.test
+++ b/llvm/test/tools/llvm-objcopy/wasm/basic-only-section.test
@@ -1,15 +1,15 @@
## Test --only-section.
# RUN: yaml2obj %s -o %t
# RUN: llvm-objcopy --only-section=foo %t %t2
-# RUN: obj2yaml %t2 | FileCheck --implicit-check-not TYPE --implicit-check-not linking %s
+# RUN: obj2yaml %t2 | FileCheck --implicit-check-not TYPE --implicit-check-not producers %s
## Test that it's the same with only-section + keep-section (for the same section).
# RUN: llvm-objcopy --only-section=foo --keep-section=foo %t %t2
-# RUN: obj2yaml %t2 | FileCheck --implicit-check-not TYPE --implicit-check-not linking %s
+# RUN: obj2yaml %t2 | FileCheck --implicit-check-not TYPE --implicit-check-not producers %s
## Also test that only-section overrides remove-section.
# RUN: llvm-objcopy --only-section=foo --remove-section=foo %t %t2
-# RUN: obj2yaml %t2 | FileCheck --implicit-check-not linking %s
+# RUN: obj2yaml %t2 | FileCheck --implicit-check-not producers %s
## This file has both known and custom sections. Check that only the foo section is left.
# CHECK: Sections:
@@ -19,10 +19,10 @@
# CHECK-NEXT: ...
## Test that only-section + keep-section keeps both sections.
-# RUN: llvm-objcopy --only-section=foo --keep-section=linking %t %t2
+# RUN: llvm-objcopy --only-section=foo --keep-section=producers %t %t2
# RUN: obj2yaml %t2 | FileCheck --implicit-check-not=TYPE --check-prefix=KEEP %s
# KEEP: Name: foo
-# KEEP: Name: linking
+# KEEP: Name: producers
--- !WASM
FileHeader:
@@ -39,5 +39,7 @@ Sections:
ReturnTypes:
- F32
- Type: CUSTOM
- Name: linking
- Version: 2
+ Name: producers
+ Tools:
+ - Name: clang
+ Version: 9.0.0
diff --git a/llvm/test/tools/llvm-objcopy/wasm/only-keep-debug.test b/llvm/test/tools/llvm-objcopy/wasm/only-keep-debug.test
index fc57329..c7a5da9 100644
--- a/llvm/test/tools/llvm-objcopy/wasm/only-keep-debug.test
+++ b/llvm/test/tools/llvm-objcopy/wasm/only-keep-debug.test
@@ -1,26 +1,32 @@
## 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
+# RUN: yaml2obj %s -o %t.wasm
+# RUN: llvm-strip --only-keep-debug %t.wasm -o %t2.wasm
+# RUN: obj2yaml %t2.wasm | FileCheck %s -check-prefixes=CHECK,STRIPTYPE,STRIPFOO
## 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
+# RUN: llvm-strip --only-keep-debug --keep-section=foo %t.wasm -o %t3.wasm
+# RUN: obj2yaml %t3.wasm | FileCheck --implicit-check-not=Name --check-prefixes=CHECK,STRIPTYPE,KEEPFOO %s
## Test that keep-section overrides only-keep-debug, even for known sections.
-# RUN: yaml2obj %s -o %t
-# RUN: llvm-strip --only-keep-debug --keep-section=TYPE %t
-# RUN: obj2yaml %t | FileCheck --implicit-check-not=Name --check-prefix=CHECK --check-prefix=KEEPTYPE %s
+# RUN: llvm-strip --only-keep-debug --keep-section=TYPE %t.wasm -o %t4.wasm
+# RUN: obj2yaml %t4.wasm | FileCheck --implicit-check-not=Name --check-prefixes=CHECK,KEEPTYPE,STRIPFOO %s
# CHECK: Sections:
-# KEEPTYPE: - Type: TYPE
-# CHECK-NOT: - Type: TYPE
-# CHECK: - Type: CUSTOM
-# CHECK-NEXT: Name: .debug_info
-# CHECK: - Type: CUSTOM
-# CHECK-NEXT: Name: .debug_line
-# KEEP: Name: foo
+# KEEPTYPE: - Type: TYPE
+# STRIPTYPE-NOT: - Type: TYPE
+# STRIPTYPE: - Type: CUSTOM
+# STRIPTYPE-NEXT: Name: .objcopy.removed
+# CHECK: - Type: CUSTOM
+# CHECK-NEXT: Name: .debug_info
+# CHECK: - Type: CUSTOM
+# CHECK-NEXT: Name: .objcopy.removed
+# CHECK: - Type: CUSTOM
+# CHECK-NEXT: Name: .objcopy.removed
+# CHECK: - Type: CUSTOM
+# CHECK-NEXT: Name: .debug_line
+# CHECK: - Type: CUSTOM
+# KEEPFOO-NEXT: Name: foo
+# STRIPFOO-NEXT: Name: .objcopy.removed
## Test that remove-section overrides only-keep-debug.
# RUN: yaml2obj %s -o %t
diff --git a/llvm/test/tools/llvm-objcopy/wasm/strip-all.test b/llvm/test/tools/llvm-objcopy/wasm/strip-all.test
index 9a90157..ef7c1a9 100644
--- a/llvm/test/tools/llvm-objcopy/wasm/strip-all.test
+++ b/llvm/test/tools/llvm-objcopy/wasm/strip-all.test
@@ -7,6 +7,12 @@
# CHECK: Sections:
# CHECK-NEXT: - Type: TYPE
# CHECK: - Type: CUSTOM
+# CHECK-NEXT: Name: .objcopy.removed
+# CHECK: - Type: CUSTOM
+# CHECK-NEXT: Name: .objcopy.removed
+# CHECK: - Type: CUSTOM
+# CHECK-NEXT: Name: .objcopy.removed
+# CHECK: - Type: CUSTOM
# CHECK-NEXT: Name: foo
--- !WASM
diff --git a/llvm/test/tools/llvm-objcopy/wasm/strip-debug.test b/llvm/test/tools/llvm-objcopy/wasm/strip-debug.test
index 2747c3b..53e8153 100644
--- a/llvm/test/tools/llvm-objcopy/wasm/strip-debug.test
+++ b/llvm/test/tools/llvm-objcopy/wasm/strip-debug.test
@@ -1,14 +1,65 @@
-## 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
+# RUN: cp %t %t3
+# RUN: llvm-objcopy --strip-debug %t %t2
+## Test that debug sections (but not linking or names) are stripped with --strip-debug
+# RUN: obj2yaml %t2 | FileCheck --implicit-check-not=.debug %s
+#
+# RUN: llvm-objcopy -g %t %t2g
+# Verify that --strip-debug and -g produce the same output
+# RUN: cmp %t2 %t2g
+
+# RUN: llvm-strip --strip-debug %t3
+# RUN: cmp %t2 %t3
+
+# RUN: cp %t %t4
+# RUN: llvm-strip -d %t4
+# RUN: cmp %t2 %t4
+
+# RUN: cp %t %t5
+# RUN: llvm-strip -g %t5
+# RUN: cmp %t2 %t5
+
+# RUN: cp %t %t6
+# RUN: llvm-strip -S %t6
+# RUN: cmp %t2 %t6
+
+# Verify that an archive with multiple object files is handled correctly.
+# RUN: cp %t %t.duplicate
+# RUN: cp %t2 %t.duplicate.stripped
+# RUN: rm -f %t.multiple-stripped-obj.a
+# RUN: llvm-ar crs %t.multiple-stripped-obj.a %t2 %t.duplicate.stripped
+# RUN: rm -f %t.multiple-obj.a
+# RUN: llvm-ar crs %t.multiple-obj.a %t %t.duplicate
+# RUN: llvm-objcopy --strip-debug %t.multiple-obj.a %t.multiple-obj.stripped.a
+# RUN: llvm-ar p %t.multiple-stripped-obj.a > %t.multiple-stripped-obj.a.dump
+# RUN: llvm-ar p %t.multiple-obj.stripped.a > %t.multiple-obj.stripped.a.dump
+# RUN: cmp %t.multiple-stripped-obj.a.dump %t.multiple-obj.stripped.a.dump
# CHECK: Sections:
# CHECK-NEXT: - Type: TYPE
-# CHECK: Name: linking
+# CHECK: - Type: CUSTOM
+## We expect the linking section to be preceeded by the removed `.debug_info`
+## section.
+# CHECK-NEXT: Name: .objcopy.removed
+# CHECK-NEXT: Payload: ''
+# CHECK-NEXT: - Type: CUSTOM
+# CHECK-NEXT: Name: linking
# CHECK: Name: name
# CHECK-NEXT: FunctionNames:
# CHECK: Name: producers
+## Following the producers section we expect to find three removed sections.
+## The `.debug_line` section that two reloction section corresponding to the
+## two debug sections.
+# CHECK: - Type: CUSTOM
+# CHECK-NEXT: Name: .objcopy.removed
+# CHECK-NEXT: Payload: ''
+# CHECK-NEXT: - Type: CUSTOM
+# CHECK-NEXT: Name: .objcopy.removed
+# CHECK-NEXT: Payload: ''
+# CHECK-NEXT: - Type: CUSTOM
+# CHECK-NEXT: Name: .objcopy.removed
+# CHECK-NEXT: Payload: ''
+
--- !WASM
FileHeader:
@@ -28,7 +79,11 @@ Sections:
Body: 0B
- Type: CUSTOM
Name: .debug_info
- Payload: CAFE1234
+ Payload: 'CAFE123456'
+ Relocations:
+ - Type: R_WASM_FUNCTION_INDEX_LEB
+ Index: 0
+ Offset: 0x0000000
- Type: CUSTOM
Name: linking
Version: 2
@@ -50,4 +105,8 @@ Sections:
Version: 9.0.0
- Type: CUSTOM
Name: .debug_line
- Payload: DEADBEEF
+ Payload: 'DEADBEEF01'
+ Relocations:
+ - Type: R_WASM_FUNCTION_INDEX_LEB
+ Index: 0
+ Offset: 0x0000000
diff --git a/llvm/test/tools/llvm-objcopy/wasm/strip-reloc.test b/llvm/test/tools/llvm-objcopy/wasm/strip-reloc.test
index 4c8d1ba..d072bf7 100644
--- a/llvm/test/tools/llvm-objcopy/wasm/strip-reloc.test
+++ b/llvm/test/tools/llvm-objcopy/wasm/strip-reloc.test
@@ -5,13 +5,15 @@
# RUN: yaml2obj %s -o %t
# RUN: llvm-objcopy --strip-all %t %t2
-# RUN: obj2yaml %t2 | FileCheck --implicit-check-not=Type: %s
+# RUN: obj2yaml %t2 | FileCheck %s
## Check that the known sections are still present.
# CHECK: Sections:
# CHECK: - Type: TYPE
# CHECK: - Type: FUNCTION
# CHECK: - Type: CODE
+# CHECK-NOT: Relocations
+# CHECK-NOT: linking
## Check that there are still functions in the code section.
# CHECK: Functions: