diff --git a/lld/test/wasm/pie.ll b/lld/test/wasm/pie.ll --- a/lld/test/wasm/pie.ll +++ b/lld/test/wasm/pie.ll @@ -34,7 +34,7 @@ ; CHECK: Sections: ; CHECK-NEXT: - Type: CUSTOM -; CHECK-NEXT: Name: dylink +; CHECK-NEXT: Name: dylink.0 ; CHECK-NEXT: MemorySize: 16 ; CHECK-NEXT: MemoryAlignment: 2 ; CHECK-NEXT: TableSize: 1 diff --git a/lld/test/wasm/shared-needed.s b/lld/test/wasm/shared-needed.s --- a/lld/test/wasm/shared-needed.s +++ b/lld/test/wasm/shared-needed.s @@ -23,7 +23,7 @@ # SO1: Sections: # SO1-NEXT: - Type: CUSTOM -# SO1-NEXT: Name: dylink +# SO1-NEXT: Name: dylink.0 # SO1-NEXT: MemorySize: 4 # SO1-NEXT: MemoryAlignment: 2 # SO1-NEXT: TableSize: 0 @@ -33,7 +33,7 @@ # SO2: Sections: # SO2-NEXT: - Type: CUSTOM -# SO2-NEXT: Name: dylink +# SO2-NEXT: Name: dylink.0 # SO2-NEXT: MemorySize: 0 # SO2-NEXT: MemoryAlignment: 0 # SO2-NEXT: TableSize: 0 diff --git a/lld/test/wasm/shared.s b/lld/test/wasm/shared.s --- a/lld/test/wasm/shared.s +++ b/lld/test/wasm/shared.s @@ -127,7 +127,7 @@ # CHECK: Sections: # CHECK-NEXT: - Type: CUSTOM -# CHECK-NEXT: Name: dylink +# CHECK-NEXT: Name: dylink.0 # CHECK-NEXT: MemorySize: 24 # CHECK-NEXT: MemoryAlignment: 2 # CHECK-NEXT: TableSize: 2 diff --git a/lld/test/wasm/shared64.s b/lld/test/wasm/shared64.s --- a/lld/test/wasm/shared64.s +++ b/lld/test/wasm/shared64.s @@ -128,7 +128,7 @@ # CHECK: Sections: # CHECK-NEXT: - Type: CUSTOM -# CHECK-NEXT: Name: dylink +# CHECK-NEXT: Name: dylink.0 # CHECK-NEXT: MemorySize: 36 # CHECK-NEXT: MemoryAlignment: 2 # CHECK-NEXT: TableSize: 2 diff --git a/lld/wasm/SyntheticSections.h b/lld/wasm/SyntheticSections.h --- a/lld/wasm/SyntheticSections.h +++ b/lld/wasm/SyntheticSections.h @@ -74,7 +74,7 @@ // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md class DylinkSection : public SyntheticSection { public: - DylinkSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "dylink") {} + DylinkSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "dylink.0") {} bool isNeeded() const override { return config->isPic; } void writeBody() override; diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp --- a/lld/wasm/SyntheticSections.cpp +++ b/lld/wasm/SyntheticSections.cpp @@ -57,13 +57,22 @@ void DylinkSection::writeBody() { raw_ostream &os = bodyOutputStream; - writeUleb128(os, memSize, "MemSize"); - writeUleb128(os, memAlign, "MemAlign"); - writeUleb128(os, out.elemSec->numEntries(), "TableSize"); - writeUleb128(os, 0, "TableAlign"); - writeUleb128(os, symtab->sharedFiles.size(), "Needed"); - for (auto *so : symtab->sharedFiles) - writeStr(os, llvm::sys::path::filename(so->getName()), "so name"); + { + SubSection sub(WASM_DYLINK_MEM_INFO); + writeUleb128(sub.os, memSize, "MemSize"); + writeUleb128(sub.os, memAlign, "MemAlign"); + writeUleb128(sub.os, out.elemSec->numEntries(), "TableSize"); + writeUleb128(sub.os, 0, "TableAlign"); + sub.writeTo(os); + } + + if (symtab->sharedFiles.size()) { + SubSection sub(WASM_DYLINK_NEEDED); + writeUleb128(sub.os, symtab->sharedFiles.size(), "Needed"); + for (auto *so : symtab->sharedFiles) + writeStr(sub.os, llvm::sys::path::filename(so->getName()), "so name"); + sub.writeTo(os); + } } uint32_t TypeSection::registerType(const WasmSignature &sig) { diff --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h --- a/llvm/include/llvm/BinaryFormat/Wasm.h +++ b/llvm/include/llvm/BinaryFormat/Wasm.h @@ -339,6 +339,12 @@ WASM_SYMBOL_TABLE = 0x8, }; +// Kind codes used in the custom "dylink" section +enum : unsigned { + WASM_DYLINK_MEM_INFO = 0x1, + WASM_DYLINK_NEEDED = 0x2, +}; + // Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO enum : unsigned { WASM_COMDAT_DATA = 0x0, diff --git a/llvm/include/llvm/Object/Wasm.h b/llvm/include/llvm/Object/Wasm.h --- a/llvm/include/llvm/Object/Wasm.h +++ b/llvm/include/llvm/Object/Wasm.h @@ -260,6 +260,7 @@ // Custom section types Error parseDylinkSection(ReadContext &Ctx); + Error parseDylink0Section(ReadContext &Ctx); Error parseNameSection(ReadContext &Ctx); Error parseLinkingSection(ReadContext &Ctx); Error parseLinkingSectionSymtab(ReadContext &Ctx); diff --git a/llvm/include/llvm/ObjectYAML/WasmYAML.h b/llvm/include/llvm/ObjectYAML/WasmYAML.h --- a/llvm/include/llvm/ObjectYAML/WasmYAML.h +++ b/llvm/include/llvm/ObjectYAML/WasmYAML.h @@ -200,11 +200,11 @@ }; struct DylinkSection : CustomSection { - DylinkSection() : CustomSection("dylink") {} + DylinkSection() : CustomSection("dylink.0") {} static bool classof(const Section *S) { auto C = dyn_cast(S); - return C && C->Name == "dylink"; + return C && C->Name == "dylink.0"; } uint32_t MemorySize; diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -339,7 +339,8 @@ } Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) { - // See https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md + // Legacy "dylink" section support. + // See parseDylink0Section for the current "dylink.0" section parsing. HasDylinkSection = true; DylinkInfo.MemorySize = readVaruint32(Ctx); DylinkInfo.MemoryAlignment = readVaruint32(Ctx); @@ -349,12 +350,58 @@ while (Count--) { DylinkInfo.Needed.push_back(readString(Ctx)); } + if (Ctx.Ptr != Ctx.End) return make_error("dylink section ended prematurely", object_error::parse_failed); return Error::success(); } +Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) { + // See + // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md + HasDylinkSection = true; + + const uint8_t *OrigEnd = Ctx.End; + while (Ctx.Ptr < OrigEnd) { + Ctx.End = OrigEnd; + uint8_t Type = readUint8(Ctx); + uint32_t Size = readVaruint32(Ctx); + LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size + << "\n"); + Ctx.End = Ctx.Ptr + Size; + uint32_t Count; + switch (Type) { + case wasm::WASM_DYLINK_MEM_INFO: + DylinkInfo.MemorySize = readVaruint32(Ctx); + DylinkInfo.MemoryAlignment = readVaruint32(Ctx); + DylinkInfo.TableSize = readVaruint32(Ctx); + DylinkInfo.TableAlignment = readVaruint32(Ctx); + break; + case wasm::WASM_DYLINK_NEEDED: + Count = readVaruint32(Ctx); + while (Count--) { + DylinkInfo.Needed.push_back(readString(Ctx)); + } + break; + default: + return make_error("unknown dylink.0 sub-section", + object_error::parse_failed); + Ctx.Ptr += Size; + break; + } + if (Ctx.Ptr != Ctx.End) { + return make_error( + "dylink.0 sub-section ended prematurely", object_error::parse_failed); + } + } + + if (Ctx.Ptr != Ctx.End) + return make_error("dylink.0 section ended prematurely", + object_error::parse_failed); + return Error::success(); +} + Error WasmObjectFile::parseNameSection(ReadContext &Ctx) { llvm::DenseSet SeenFunctions; llvm::DenseSet SeenGlobals; @@ -984,6 +1031,9 @@ if (Sec.Name == "dylink") { if (Error Err = parseDylinkSection(Ctx)) return Err; + } else if (Sec.Name == "dylink.0") { + if (Error Err = parseDylink0Section(Ctx)) + return Err; } else if (Sec.Name == "name") { if (Error Err = parseNameSection(Ctx)) return Err; @@ -1793,6 +1843,7 @@ case wasm::WASM_SEC_CUSTOM: return StringSwitch(CustomSectionName) .Case("dylink", WASM_SEC_ORDER_DYLINK) + .Case("dylink.0", WASM_SEC_ORDER_DYLINK) .Case("linking", WASM_SEC_ORDER_LINKING) .StartsWith("reloc.", WASM_SEC_ORDER_RELOC) .Case("name", WASM_SEC_ORDER_NAME) diff --git a/llvm/lib/ObjectYAML/WasmEmitter.cpp b/llvm/lib/ObjectYAML/WasmEmitter.cpp --- a/llvm/lib/ObjectYAML/WasmEmitter.cpp +++ b/llvm/lib/ObjectYAML/WasmEmitter.cpp @@ -157,13 +157,24 @@ void WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::DylinkSection &Section) { writeStringRef(Section.Name, OS); - encodeULEB128(Section.MemorySize, OS); - encodeULEB128(Section.MemoryAlignment, OS); - encodeULEB128(Section.TableSize, OS); - encodeULEB128(Section.TableAlignment, OS); - encodeULEB128(Section.Needed.size(), OS); - for (StringRef Needed : Section.Needed) - writeStringRef(Needed, OS); + + writeUint8(OS, wasm::WASM_DYLINK_MEM_INFO); + SubSectionWriter SubSection(OS); + raw_ostream &SubOS = SubSection.getStream(); + encodeULEB128(Section.MemorySize, SubOS); + encodeULEB128(Section.MemoryAlignment, SubOS); + encodeULEB128(Section.TableSize, SubOS); + encodeULEB128(Section.TableAlignment, SubOS); + SubSection.done(); + + if (Section.Needed.size()) { + writeUint8(OS, wasm::WASM_DYLINK_NEEDED); + raw_ostream &SubOS = SubSection.getStream(); + encodeULEB128(Section.Needed.size(), SubOS); + for (StringRef Needed : Section.Needed) + writeStringRef(Needed, SubOS); + SubSection.done(); + } } void WasmWriter::writeSectionContent(raw_ostream &OS, diff --git a/llvm/lib/ObjectYAML/WasmYAML.cpp b/llvm/lib/ObjectYAML/WasmYAML.cpp --- a/llvm/lib/ObjectYAML/WasmYAML.cpp +++ b/llvm/lib/ObjectYAML/WasmYAML.cpp @@ -50,6 +50,7 @@ static void sectionMapping(IO &IO, WasmYAML::DylinkSection &Section) { commonSectionMapping(IO, Section); IO.mapRequired("Name", Section.Name); + IO.mapRequired("MemorySize", Section.MemorySize); IO.mapRequired("MemoryAlignment", Section.MemoryAlignment); IO.mapRequired("TableSize", Section.TableSize); @@ -177,7 +178,7 @@ } else { IO.mapRequired("Name", SectionName); } - if (SectionName == "dylink") { + if (SectionName == "dylink" || SectionName == "dylink.0") { if (!IO.outputting()) Section.reset(new WasmYAML::DylinkSection()); sectionMapping(IO, *cast(Section.get())); diff --git a/llvm/test/ObjectYAML/wasm/dylink_section.yaml b/llvm/test/ObjectYAML/wasm/dylink_section.yaml --- a/llvm/test/ObjectYAML/wasm/dylink_section.yaml +++ b/llvm/test/ObjectYAML/wasm/dylink_section.yaml @@ -5,7 +5,7 @@ Sections: - Type: CUSTOM - Name: dylink + Name: dylink.0 MemorySize: 4 MemoryAlignment: 2 TableSize: 1 @@ -17,7 +17,7 @@ # CHECK: Version: 0x1 # CHECK: Sections: # CHECK: - Type: CUSTOM -# CHECK: Name: dylink +# CHECK: Name: dylink.0 # CHECK: MemorySize: 4 # CHECK: MemoryAlignment: 2 # CHECK: TableSize: 1 diff --git a/llvm/tools/obj2yaml/wasm2yaml.cpp b/llvm/tools/obj2yaml/wasm2yaml.cpp --- a/llvm/tools/obj2yaml/wasm2yaml.cpp +++ b/llvm/tools/obj2yaml/wasm2yaml.cpp @@ -51,7 +51,7 @@ std::unique_ptr WasmDumper::dumpCustomSection(const WasmSection &WasmSec) { std::unique_ptr CustomSec; - if (WasmSec.Name == "dylink") { + if (WasmSec.Name == "dylink" || WasmSec.Name == "dylink.0") { std::unique_ptr DylinkSec = std::make_unique(); const wasm::WasmDylinkInfo& Info = Obj.dylinkInfo();