Skip to content

[llvm-objcopy][WebAssembly] Allow --strip-debug to operate on relocatable files. #102978

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lld/wasm/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
18 changes: 16 additions & 2 deletions llvm/lib/ObjCopy/wasm/WasmObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/ObjCopy/wasm/WasmObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/ObjCopy/wasm/WasmReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/ObjectYAML/WasmEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/ObjectYAML/wasm/invalid_section_order.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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 ]
...
16 changes: 9 additions & 7 deletions llvm/test/tools/llvm-objcopy/wasm/basic-only-section.test
Original file line number Diff line number Diff line change
@@ -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:
Expand All @@ -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:
Expand All @@ -39,5 +39,7 @@ Sections:
ReturnTypes:
- F32
- Type: CUSTOM
Name: linking
Version: 2
Name: producers
Tools:
- Name: clang
Version: 9.0.0
38 changes: 22 additions & 16 deletions llvm/test/tools/llvm-objcopy/wasm/only-keep-debug.test
Original file line number Diff line number Diff line change
@@ -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
Expand Down
6 changes: 6 additions & 0 deletions llvm/test/tools/llvm-objcopy/wasm/strip-all.test
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
71 changes: 65 additions & 6 deletions llvm/test/tools/llvm-objcopy/wasm/strip-debug.test
Original file line number Diff line number Diff line change
@@ -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:
Expand All @@ -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
Expand All @@ -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
4 changes: 3 additions & 1 deletion llvm/test/tools/llvm-objcopy/wasm/strip-reloc.test
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
Loading