Skip to content

Commit

Permalink
[llvm-objcopy][WebAssembly] Allow --strip-debug to operate on relocat…
Browse files Browse the repository at this point in the history
…able files.

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: llvm#102002
  • Loading branch information
sbc100 committed Aug 19, 2024
1 parent 4d08bb1 commit f996389
Show file tree
Hide file tree
Showing 12 changed files with 132 additions and 35 deletions.
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

0 comments on commit f996389

Please sign in to comment.