Skip to content

Commit 2a6136e

Browse files
authored
[llvm-objcopy][WebAssembly] Allow --strip-debug to operate on relocatable files. (#102978)
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
1 parent 5403123 commit 2a6136e

File tree

12 files changed

+132
-35
lines changed

12 files changed

+132
-35
lines changed

lld/wasm/Writer.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ void Writer::calculateCustomSections() {
138138
// Exclude COMDAT sections that are not selected for inclusion
139139
if (section->discarded)
140140
continue;
141+
// Ignore empty custom sections. In particular objcopy/strip will
142+
// sometimes replace stripped sections with empty custom sections to
143+
// avoid section re-numbering.
144+
if (section->getSize() == 0)
145+
continue;
141146
StringRef name = section->name;
142147
// These custom sections are known the linker and synthesized rather than
143148
// blindly copied.

llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ using namespace object;
2222
using SectionPred = std::function<bool(const Section &Sec)>;
2323

2424
static bool isDebugSection(const Section &Sec) {
25-
return Sec.Name.starts_with(".debug");
25+
return Sec.Name.starts_with(".debug") || Sec.Name.starts_with("reloc..debug");
2626
}
2727

2828
static bool isLinkerSection(const Section &Sec) {

llvm/lib/ObjCopy/wasm/WasmObject.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,22 @@ void Object::addSectionWithOwnedContents(
2525
}
2626

2727
void Object::removeSections(function_ref<bool(const Section &)> ToRemove) {
28-
// TODO: remove reloc sections for the removed section, handle symbols, etc.
29-
llvm::erase_if(Sections, ToRemove);
28+
if (isRelocatableObject) {
29+
// For relocatable objects, avoid actually removing any sections,
30+
// since that can invalidate the symbol table and relocation sections.
31+
// TODO: Allow removal of sections by re-generating symbol table and
32+
// relocation sections here instead.
33+
for (auto &Sec : Sections) {
34+
if (ToRemove(Sec)) {
35+
Sec.Name = ".objcopy.removed";
36+
Sec.SectionType = wasm::WASM_SEC_CUSTOM;
37+
Sec.Contents = {};
38+
Sec.HeaderSecSizeEncodingLen = std::nullopt;
39+
}
40+
}
41+
} else {
42+
llvm::erase_if(Sections, ToRemove);
43+
}
3044
}
3145

3246
} // end namespace wasm

llvm/lib/ObjCopy/wasm/WasmObject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ struct Object {
3232
llvm::wasm::WasmObjectHeader Header;
3333
// For now don't discriminate between kinds of sections.
3434
std::vector<Section> Sections;
35+
bool isRelocatableObject = false;
3536

3637
void addSectionWithOwnedContents(Section NewSection,
3738
std::unique_ptr<MemoryBuffer> &&Content);

llvm/lib/ObjCopy/wasm/WasmReader.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ using namespace llvm::wasm;
1818
Expected<std::unique_ptr<Object>> Reader::create() const {
1919
auto Obj = std::make_unique<Object>();
2020
Obj->Header = WasmObj.getHeader();
21+
Obj->isRelocatableObject = WasmObj.isRelocatableObject();
2122
std::vector<Section> Sections;
2223
Obj->Sections.reserve(WasmObj.getNumSections());
2324
for (const SectionRef &Sec : WasmObj.sections()) {

llvm/lib/ObjectYAML/WasmEmitter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,8 @@ bool WasmWriter::writeWasm(raw_ostream &OS) {
604604
if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
605605
SecName = S->Name;
606606
if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
607-
reportError("out of order section type: " + Twine(Sec->Type));
607+
reportError("out of order section type: " +
608+
wasm::sectionTypeToString(Sec->Type));
608609
return false;
609610
}
610611
encodeULEB128(Sec->Type, OS);

llvm/test/ObjectYAML/wasm/invalid_section_order.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Sections:
1414
- Index: 0
1515
Locals: []
1616
Body: 0B
17-
# CHECK: yaml2obj: error: out of order section type: 3
17+
# CHECK: yaml2obj: error: out of order section type: FUNCTION
1818
- Type: FUNCTION
1919
FunctionTypes: [ 0 ]
2020
...

llvm/test/tools/llvm-objcopy/wasm/basic-only-section.test

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
## Test --only-section.
22
# RUN: yaml2obj %s -o %t
33
# RUN: llvm-objcopy --only-section=foo %t %t2
4-
# RUN: obj2yaml %t2 | FileCheck --implicit-check-not TYPE --implicit-check-not linking %s
4+
# RUN: obj2yaml %t2 | FileCheck --implicit-check-not TYPE --implicit-check-not producers %s
55

66
## Test that it's the same with only-section + keep-section (for the same section).
77
# RUN: llvm-objcopy --only-section=foo --keep-section=foo %t %t2
8-
# RUN: obj2yaml %t2 | FileCheck --implicit-check-not TYPE --implicit-check-not linking %s
8+
# RUN: obj2yaml %t2 | FileCheck --implicit-check-not TYPE --implicit-check-not producers %s
99

1010
## Also test that only-section overrides remove-section.
1111
# RUN: llvm-objcopy --only-section=foo --remove-section=foo %t %t2
12-
# RUN: obj2yaml %t2 | FileCheck --implicit-check-not linking %s
12+
# RUN: obj2yaml %t2 | FileCheck --implicit-check-not producers %s
1313

1414
## This file has both known and custom sections. Check that only the foo section is left.
1515
# CHECK: Sections:
@@ -19,10 +19,10 @@
1919
# CHECK-NEXT: ...
2020

2121
## Test that only-section + keep-section keeps both sections.
22-
# RUN: llvm-objcopy --only-section=foo --keep-section=linking %t %t2
22+
# RUN: llvm-objcopy --only-section=foo --keep-section=producers %t %t2
2323
# RUN: obj2yaml %t2 | FileCheck --implicit-check-not=TYPE --check-prefix=KEEP %s
2424
# KEEP: Name: foo
25-
# KEEP: Name: linking
25+
# KEEP: Name: producers
2626

2727
--- !WASM
2828
FileHeader:
@@ -39,5 +39,7 @@ Sections:
3939
ReturnTypes:
4040
- F32
4141
- Type: CUSTOM
42-
Name: linking
43-
Version: 2
42+
Name: producers
43+
Tools:
44+
- Name: clang
45+
Version: 9.0.0

llvm/test/tools/llvm-objcopy/wasm/only-keep-debug.test

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,32 @@
11
## Test that only debug sections are kept with --only-keep-debug.
2-
# RUN: yaml2obj %s -o %t
3-
# RUN: llvm-strip --only-keep-debug %t
4-
# RUN: obj2yaml %t | FileCheck %s
2+
# RUN: yaml2obj %s -o %t.wasm
3+
# RUN: llvm-strip --only-keep-debug %t.wasm -o %t2.wasm
4+
# RUN: obj2yaml %t2.wasm | FileCheck %s -check-prefixes=CHECK,STRIPTYPE,STRIPFOO
55

66
## Test that keep-section overrides only-keep-debug.
7-
# RUN: yaml2obj %s -o %t
8-
# RUN: llvm-strip --only-keep-debug --keep-section=foo %t
9-
# RUN: obj2yaml %t | FileCheck --implicit-check-not=Name --check-prefix=CHECK --check-prefix=KEEP %s
7+
# RUN: llvm-strip --only-keep-debug --keep-section=foo %t.wasm -o %t3.wasm
8+
# RUN: obj2yaml %t3.wasm | FileCheck --implicit-check-not=Name --check-prefixes=CHECK,STRIPTYPE,KEEPFOO %s
109

1110
## Test that keep-section overrides only-keep-debug, even for known sections.
12-
# RUN: yaml2obj %s -o %t
13-
# RUN: llvm-strip --only-keep-debug --keep-section=TYPE %t
14-
# RUN: obj2yaml %t | FileCheck --implicit-check-not=Name --check-prefix=CHECK --check-prefix=KEEPTYPE %s
11+
# RUN: llvm-strip --only-keep-debug --keep-section=TYPE %t.wasm -o %t4.wasm
12+
# RUN: obj2yaml %t4.wasm | FileCheck --implicit-check-not=Name --check-prefixes=CHECK,KEEPTYPE,STRIPFOO %s
1513

1614
# CHECK: Sections:
17-
# KEEPTYPE: - Type: TYPE
18-
# CHECK-NOT: - Type: TYPE
19-
# CHECK: - Type: CUSTOM
20-
# CHECK-NEXT: Name: .debug_info
21-
# CHECK: - Type: CUSTOM
22-
# CHECK-NEXT: Name: .debug_line
23-
# KEEP: Name: foo
15+
# KEEPTYPE: - Type: TYPE
16+
# STRIPTYPE-NOT: - Type: TYPE
17+
# STRIPTYPE: - Type: CUSTOM
18+
# STRIPTYPE-NEXT: Name: .objcopy.removed
19+
# CHECK: - Type: CUSTOM
20+
# CHECK-NEXT: Name: .debug_info
21+
# CHECK: - Type: CUSTOM
22+
# CHECK-NEXT: Name: .objcopy.removed
23+
# CHECK: - Type: CUSTOM
24+
# CHECK-NEXT: Name: .objcopy.removed
25+
# CHECK: - Type: CUSTOM
26+
# CHECK-NEXT: Name: .debug_line
27+
# CHECK: - Type: CUSTOM
28+
# KEEPFOO-NEXT: Name: foo
29+
# STRIPFOO-NEXT: Name: .objcopy.removed
2430

2531
## Test that remove-section overrides only-keep-debug.
2632
# RUN: yaml2obj %s -o %t

llvm/test/tools/llvm-objcopy/wasm/strip-all.test

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
# CHECK: Sections:
88
# CHECK-NEXT: - Type: TYPE
99
# CHECK: - Type: CUSTOM
10+
# CHECK-NEXT: Name: .objcopy.removed
11+
# CHECK: - Type: CUSTOM
12+
# CHECK-NEXT: Name: .objcopy.removed
13+
# CHECK: - Type: CUSTOM
14+
# CHECK-NEXT: Name: .objcopy.removed
15+
# CHECK: - Type: CUSTOM
1016
# CHECK-NEXT: Name: foo
1117

1218
--- !WASM

llvm/test/tools/llvm-objcopy/wasm/strip-debug.test

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,65 @@
1-
## Test that debug sections (but not linking or names) are stripped with --strip-debug
21
# RUN: yaml2obj %s -o %t
3-
# RUN: llvm-strip --strip-debug %t
4-
# RUN: obj2yaml %t | FileCheck --implicit-check-not=.debug %s
2+
# RUN: cp %t %t3
3+
# RUN: llvm-objcopy --strip-debug %t %t2
4+
## Test that debug sections (but not linking or names) are stripped with --strip-debug
5+
# RUN: obj2yaml %t2 | FileCheck --implicit-check-not=.debug %s
6+
#
7+
# RUN: llvm-objcopy -g %t %t2g
8+
# Verify that --strip-debug and -g produce the same output
9+
# RUN: cmp %t2 %t2g
10+
11+
# RUN: llvm-strip --strip-debug %t3
12+
# RUN: cmp %t2 %t3
13+
14+
# RUN: cp %t %t4
15+
# RUN: llvm-strip -d %t4
16+
# RUN: cmp %t2 %t4
17+
18+
# RUN: cp %t %t5
19+
# RUN: llvm-strip -g %t5
20+
# RUN: cmp %t2 %t5
21+
22+
# RUN: cp %t %t6
23+
# RUN: llvm-strip -S %t6
24+
# RUN: cmp %t2 %t6
25+
26+
# Verify that an archive with multiple object files is handled correctly.
27+
# RUN: cp %t %t.duplicate
28+
# RUN: cp %t2 %t.duplicate.stripped
29+
# RUN: rm -f %t.multiple-stripped-obj.a
30+
# RUN: llvm-ar crs %t.multiple-stripped-obj.a %t2 %t.duplicate.stripped
31+
# RUN: rm -f %t.multiple-obj.a
32+
# RUN: llvm-ar crs %t.multiple-obj.a %t %t.duplicate
33+
# RUN: llvm-objcopy --strip-debug %t.multiple-obj.a %t.multiple-obj.stripped.a
34+
# RUN: llvm-ar p %t.multiple-stripped-obj.a > %t.multiple-stripped-obj.a.dump
35+
# RUN: llvm-ar p %t.multiple-obj.stripped.a > %t.multiple-obj.stripped.a.dump
36+
# RUN: cmp %t.multiple-stripped-obj.a.dump %t.multiple-obj.stripped.a.dump
537

638
# CHECK: Sections:
739
# CHECK-NEXT: - Type: TYPE
8-
# CHECK: Name: linking
40+
# CHECK: - Type: CUSTOM
41+
## We expect the linking section to be preceeded by the removed `.debug_info`
42+
## section.
43+
# CHECK-NEXT: Name: .objcopy.removed
44+
# CHECK-NEXT: Payload: ''
45+
# CHECK-NEXT: - Type: CUSTOM
46+
# CHECK-NEXT: Name: linking
947
# CHECK: Name: name
1048
# CHECK-NEXT: FunctionNames:
1149
# CHECK: Name: producers
50+
## Following the producers section we expect to find three removed sections.
51+
## The `.debug_line` section that two reloction section corresponding to the
52+
## two debug sections.
53+
# CHECK: - Type: CUSTOM
54+
# CHECK-NEXT: Name: .objcopy.removed
55+
# CHECK-NEXT: Payload: ''
56+
# CHECK-NEXT: - Type: CUSTOM
57+
# CHECK-NEXT: Name: .objcopy.removed
58+
# CHECK-NEXT: Payload: ''
59+
# CHECK-NEXT: - Type: CUSTOM
60+
# CHECK-NEXT: Name: .objcopy.removed
61+
# CHECK-NEXT: Payload: ''
62+
1263

1364
--- !WASM
1465
FileHeader:
@@ -28,7 +79,11 @@ Sections:
2879
Body: 0B
2980
- Type: CUSTOM
3081
Name: .debug_info
31-
Payload: CAFE1234
82+
Payload: 'CAFE123456'
83+
Relocations:
84+
- Type: R_WASM_FUNCTION_INDEX_LEB
85+
Index: 0
86+
Offset: 0x0000000
3287
- Type: CUSTOM
3388
Name: linking
3489
Version: 2
@@ -50,4 +105,8 @@ Sections:
50105
Version: 9.0.0
51106
- Type: CUSTOM
52107
Name: .debug_line
53-
Payload: DEADBEEF
108+
Payload: 'DEADBEEF01'
109+
Relocations:
110+
- Type: R_WASM_FUNCTION_INDEX_LEB
111+
Index: 0
112+
Offset: 0x0000000

llvm/test/tools/llvm-objcopy/wasm/strip-reloc.test

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55

66
# RUN: yaml2obj %s -o %t
77
# RUN: llvm-objcopy --strip-all %t %t2
8-
# RUN: obj2yaml %t2 | FileCheck --implicit-check-not=Type: %s
8+
# RUN: obj2yaml %t2 | FileCheck %s
99

1010
## Check that the known sections are still present.
1111
# CHECK: Sections:
1212
# CHECK: - Type: TYPE
1313
# CHECK: - Type: FUNCTION
1414
# CHECK: - Type: CODE
15+
# CHECK-NOT: Relocations
16+
# CHECK-NOT: linking
1517
## Check that there are still functions in the code section.
1618
# CHECK: Functions:
1719

0 commit comments

Comments
 (0)