From dd6412c05c1039e582a970da1aee62cdde75c892 Mon Sep 17 00:00:00 2001 From: Derek Schuff Date: Wed, 9 Dec 2020 10:57:27 -0800 Subject: [PATCH] [WebAssembly][lld] Exclude COMDAT sections Allow exclusion/discarding of custom sections with COMDAT groups. It piggybacks on the existing COMDAT-handling code, but applies to custom sections as well. Differential Revision: https://reviews.llvm.org/D92950 --- lld/test/wasm/Inputs/comdat1.s | 13 +++++++++++++ lld/test/wasm/Inputs/comdat2.s | 13 +++++++++++++ lld/test/wasm/comdat-sections.s | 22 ++++++++++++++++++++++ lld/wasm/InputChunks.h | 2 +- lld/wasm/InputFiles.cpp | 19 +++++++++++++------ lld/wasm/OutputSections.cpp | 1 + lld/wasm/Writer.cpp | 3 +++ 7 files changed, 66 insertions(+), 7 deletions(-) create mode 100644 lld/test/wasm/Inputs/comdat1.s create mode 100644 lld/test/wasm/Inputs/comdat2.s create mode 100644 lld/test/wasm/comdat-sections.s diff --git a/lld/test/wasm/Inputs/comdat1.s b/lld/test/wasm/Inputs/comdat1.s new file mode 100644 index 0000000..ff988cc --- /dev/null +++ b/lld/test/wasm/Inputs/comdat1.s @@ -0,0 +1,13 @@ + .text + .section .text.foo,"G",@,foo,comdat + .globl foo + .type foo,@function +foo: + .functype foo () -> () + return + end_function + + .section .debug_foo,"G",@,foo,comdat + .int32 1 + .section .debug_foo,"G",@,duplicate,comdat + .int64 123 diff --git a/lld/test/wasm/Inputs/comdat2.s b/lld/test/wasm/Inputs/comdat2.s new file mode 100644 index 0000000..f498fdd --- /dev/null +++ b/lld/test/wasm/Inputs/comdat2.s @@ -0,0 +1,13 @@ + .text + .section .text.foo,"G",@,foo,comdat + .globl foo + .type foo,@function +foo: + .functype foo () -> () + return + end_function + + .section .debug_foo,"G",@,foo,comdat + .int32 2 + .section .debug_foo,"G",@,duplicate,comdat + .int64 234 diff --git a/lld/test/wasm/comdat-sections.s b/lld/test/wasm/comdat-sections.s new file mode 100644 index 0000000..fc8d2de --- /dev/null +++ b/lld/test/wasm/comdat-sections.s @@ -0,0 +1,22 @@ +# RUN: llvm-mc -triple=wasm32 -filetype=obj %p/Inputs/comdat1.s -o %t1.o +# RUN: llvm-mc -triple=wasm32 -filetype=obj %p/Inputs/comdat2.s -o %t2.o +# RUN: llvm-mc -triple=wasm32 -filetype=obj %s -o %t.o +# RUN: wasm-ld -o %t.wasm %t.o %t1.o %t2.o +# RUN: obj2yaml %t.wasm | FileCheck %s + + + .globl _start + .type _start,@function +_start: + .functype _start () -> () + call foo + end_function + + .functype foo () -> () + + +# Check that we got 1 copy of each of the .debug_foo sections from the 2 object +# files, and that they came from the same object. +# CHECK: - Type: CUSTOM +# CHECK-NEXT: Name: .debug_foo +# CHECK-NEXT: Payload: 010000007B00000000000000 diff --git a/lld/wasm/InputChunks.h b/lld/wasm/InputChunks.h index ba4e2a5..9082d1d 100644 --- a/lld/wasm/InputChunks.h +++ b/lld/wasm/InputChunks.h @@ -221,7 +221,7 @@ public: StringRef getName() const override { return section.Name; } StringRef getDebugName() const override { return StringRef(); } - uint32_t getComdat() const override { return UINT32_MAX; } + uint32_t getComdat() const override { return section.Comdat; } protected: ArrayRef data() const override { return section.Content; } diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp index 2b3c259..68a9472 100644 --- a/lld/wasm/InputFiles.cpp +++ b/lld/wasm/InputFiles.cpp @@ -341,6 +341,12 @@ void ObjFile::parse(bool ignoreComdats) { } } + ArrayRef comdats = wasmObj->linkingData().Comdats; + for (StringRef comdat : comdats) { + bool isNew = ignoreComdats || symtab->addComdat(comdat); + keptComdats.push_back(isNew); + } + uint32_t sectionIndex = 0; // Bool for each symbol, true if called directly. This allows us to implement @@ -360,7 +366,9 @@ void ObjFile::parse(bool ignoreComdats) { assert(!dataSection); dataSection = §ion; } else if (section.Type == WASM_SEC_CUSTOM) { - customSections.emplace_back(make(section, this)); + auto *customSec = make(section, this); + customSec->discarded = isExcludedByComdat(customSec); + customSections.emplace_back(customSec); customSections.back()->setRelocations(section.Relocations); customSectionsByIndex[sectionIndex] = customSections.back(); } @@ -374,11 +382,6 @@ void ObjFile::parse(bool ignoreComdats) { typeMap.resize(getWasmObj()->types().size()); typeIsUsed.resize(getWasmObj()->types().size(), false); - ArrayRef comdats = wasmObj->linkingData().Comdats; - for (StringRef comdat : comdats) { - bool isNew = ignoreComdats || symtab->addComdat(comdat); - keptComdats.push_back(isNew); - } // Populate `Segments`. for (const WasmSegment &s : wasmObj->dataSegments()) { @@ -487,6 +490,10 @@ Symbol *ObjFile::createDefined(const WasmSymbol &sym) { case WASM_SYMBOL_TYPE_SECTION: { InputSection *section = customSectionsByIndex[sym.Info.ElementIndex]; assert(sym.isBindingLocal()); + // Need to return null if discarded here? data and func only do that when + // binding is not local. + if (section->discarded) + return nullptr; return make(flags, section, this); } case WASM_SYMBOL_TYPE_EVENT: { diff --git a/lld/wasm/OutputSections.cpp b/lld/wasm/OutputSections.cpp index 89f51ec..1af448d 100644 --- a/lld/wasm/OutputSections.cpp +++ b/lld/wasm/OutputSections.cpp @@ -239,6 +239,7 @@ void CustomSection::finalizeContents() { os.flush(); for (InputSection *section : inputSections) { + assert(!section->discarded); section->outputSec = this; section->outputOffset = payloadSize; payloadSize += section->getSize(); diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index 3f25596..c95b925 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -120,6 +120,9 @@ void Writer::calculateCustomSections() { bool stripDebug = config->stripDebug || config->stripAll; for (ObjFile *file : symtab->objectFiles) { for (InputSection *section : file->customSections) { + // Exclude COMDAT sections that are not selected for inclusion + if (section->discarded) + continue; StringRef name = section->getName(); // These custom sections are known the linker and synthesized rather than // blindly copied. -- 2.7.4