[WebAssembly] Convert to new "dylink.0" section format
authorSam Clegg <sbc@chromium.org>
Fri, 10 Sep 2021 11:21:28 +0000 (07:21 -0400)
committerSam Clegg <sbc@chromium.org>
Sun, 12 Sep 2021 12:30:38 +0000 (05:30 -0700)
This format is based on sub-sections (like the "linking" and "name"
sections) and is therefore easier to extend going forward.

spec change: https://github.com/WebAssembly/tool-conventions/pull/170
binaryen change: https://github.com/WebAssembly/binaryen/pull/4141
wabt change:  https://github.com/WebAssembly/wabt/pull/1707
emscripten change: https://github.com/emscripten-core/emscripten/pull/15019

Differential Revision: https://reviews.llvm.org/D109595

14 files changed:
lld/test/wasm/pie.ll
lld/test/wasm/shared-needed.s
lld/test/wasm/shared.s
lld/test/wasm/shared64.s
lld/wasm/SyntheticSections.cpp
lld/wasm/SyntheticSections.h
llvm/include/llvm/BinaryFormat/Wasm.h
llvm/include/llvm/Object/Wasm.h
llvm/include/llvm/ObjectYAML/WasmYAML.h
llvm/lib/Object/WasmObjectFile.cpp
llvm/lib/ObjectYAML/WasmEmitter.cpp
llvm/lib/ObjectYAML/WasmYAML.cpp
llvm/test/ObjectYAML/wasm/dylink_section.yaml
llvm/tools/obj2yaml/wasm2yaml.cpp

index af28ddd..ee2f027 100644 (file)
@@ -34,7 +34,7 @@ declare void @external_func()
 
 ;      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
index c6ebd5e..12c4597 100644 (file)
@@ -23,7 +23,7 @@ data:
 
 # 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 @@ data:
 
 # 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
index 29cf8f6..7861485 100644 (file)
@@ -127,7 +127,7 @@ get_local_func_address:
 
 # 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
index d441dd3..86d5a52 100644 (file)
@@ -128,7 +128,7 @@ get_local_func_address:
 
 # 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
index bb04396..3e6e9fe 100644 (file)
@@ -57,13 +57,22 @@ public:
 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) {
index 12517b6..d26f89b 100644 (file)
@@ -74,7 +74,7 @@ protected:
 // 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;
 
index 1d0eb70..f49828c 100644 (file)
@@ -339,6 +339,12 @@ enum : unsigned {
   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,
index 2cea950..d15722d 100644 (file)
@@ -260,6 +260,7 @@ private:
 
   // Custom section types
   Error parseDylinkSection(ReadContext &Ctx);
+  Error parseDylink0Section(ReadContext &Ctx);
   Error parseNameSection(ReadContext &Ctx);
   Error parseLinkingSection(ReadContext &Ctx);
   Error parseLinkingSectionSymtab(ReadContext &Ctx);
index 661e06f..8b827bf 100644 (file)
@@ -200,11 +200,11 @@ struct CustomSection : Section {
 };
 
 struct DylinkSection : CustomSection {
-  DylinkSection() : CustomSection("dylink") {}
+  DylinkSection() : CustomSection("dylink.0") {}
 
   static bool classof(const Section *S) {
     auto C = dyn_cast<CustomSection>(S);
-    return C && C->Name == "dylink";
+    return C && C->Name == "dylink.0";
   }
 
   uint32_t MemorySize;
index 9a4e246..3b1392e 100644 (file)
@@ -339,7 +339,8 @@ Error WasmObjectFile::parseSection(WasmSection &Sec) {
 }
 
 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 @@ Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
   while (Count--) {
     DylinkInfo.Needed.push_back(readString(Ctx));
   }
+
   if (Ctx.Ptr != Ctx.End)
     return make_error<GenericBinaryError>("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<GenericBinaryError>("unknown dylink.0 sub-section",
+                                            object_error::parse_failed);
+      Ctx.Ptr += Size;
+      break;
+    }
+    if (Ctx.Ptr != Ctx.End) {
+      return make_error<GenericBinaryError>(
+          "dylink.0 sub-section ended prematurely", object_error::parse_failed);
+    }
+  }
+
+  if (Ctx.Ptr != Ctx.End)
+    return make_error<GenericBinaryError>("dylink.0 section ended prematurely",
+                                          object_error::parse_failed);
+  return Error::success();
+}
+
 Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
   llvm::DenseSet<uint64_t> SeenFunctions;
   llvm::DenseSet<uint64_t> SeenGlobals;
@@ -984,6 +1031,9 @@ Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
   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 @@ int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
   case wasm::WASM_SEC_CUSTOM:
     return StringSwitch<unsigned>(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)
index 888ba11..86d4bc0 100644 (file)
@@ -157,13 +157,24 @@ void WasmWriter::writeInitExpr(raw_ostream &OS,
 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,
index 365f63c..b798987 100644 (file)
@@ -177,7 +177,7 @@ void MappingTraits<std::unique_ptr<WasmYAML::Section>>::mapping(
     } 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<WasmYAML::DylinkSection>(Section.get()));
index 76bb727..a43f678 100644 (file)
@@ -5,7 +5,7 @@ FileHeader:
 
 Sections:
   - Type:            CUSTOM
-    Name:            dylink
+    Name:            dylink.0
     MemorySize:      4
     MemoryAlignment: 2
     TableSize:       1
@@ -17,7 +17,7 @@ Sections:
 # CHECK:   Version:           0x1
 # CHECK: Sections:
 # CHECK:   - Type:            CUSTOM
-# CHECK:     Name:            dylink
+# CHECK:     Name:            dylink.0
 # CHECK:     MemorySize:      4
 # CHECK:     MemoryAlignment: 2
 # CHECK:     TableSize:       1
index 5b4f672..9555cb2 100644 (file)
@@ -51,7 +51,7 @@ static WasmYAML::Table makeTable(uint32_t Index,
 std::unique_ptr<WasmYAML::CustomSection>
 WasmDumper::dumpCustomSection(const WasmSection &WasmSec) {
   std::unique_ptr<WasmYAML::CustomSection> CustomSec;
-  if (WasmSec.Name == "dylink") {
+  if (WasmSec.Name == "dylink" || WasmSec.Name == "dylink.0") {
     std::unique_ptr<WasmYAML::DylinkSection> DylinkSec =
         std::make_unique<WasmYAML::DylinkSection>();
     const wasm::WasmDylinkInfo& Info = Obj.dylinkInfo();