[llvm] 659a083 - [WebAssembly] Add import info to `dylink` section of shared libraries

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 15 11:51:39 PDT 2021


Author: Sam Clegg
Date: 2021-10-15T11:49:16-07:00
New Revision: 659a08399a78c8807218558767f5d574a904ed30

URL: https://github.com/llvm/llvm-project/commit/659a08399a78c8807218558767f5d574a904ed30
DIFF: https://github.com/llvm/llvm-project/commit/659a08399a78c8807218558767f5d574a904ed30.diff

LOG: [WebAssembly] Add import info to `dylink` section of shared libraries

See https://github.com/WebAssembly/tool-conventions/pull/175

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

Added: 
    lld/test/wasm/shared-weak-undefined.s

Modified: 
    lld/wasm/SyntheticSections.cpp
    llvm/include/llvm/BinaryFormat/Wasm.h
    llvm/include/llvm/ObjectYAML/WasmYAML.h
    llvm/lib/Object/WasmObjectFile.cpp
    llvm/lib/ObjectYAML/WasmYAML.cpp
    llvm/tools/obj2yaml/wasm2yaml.cpp

Removed: 
    


################################################################################
diff  --git a/lld/test/wasm/shared-weak-undefined.s b/lld/test/wasm/shared-weak-undefined.s
new file mode 100644
index 0000000000000..5560ccecb807d
--- /dev/null
+++ b/lld/test/wasm/shared-weak-undefined.s
@@ -0,0 +1,32 @@
+# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
+# RUN: wasm-ld --experimental-pic -shared -o %t.wasm %t.o
+# RUN: obj2yaml %t.wasm | FileCheck %s
+# RUN: llvm-objdump -d %t.wasm | FileCheck %s -check-prefix=ASM
+
+# Verify the weak undefined symbols are marked as such in the
+# dylink section.
+
+.weak weak_func
+.functype weak_func () -> (i32)
+
+.globl call_weak
+call_weak:
+# ASM: <call_weak>:
+  .functype call_weak () -> (i32)
+  call weak_func
+# ASM:           10 80 80 80 80 00      call  0
+  end_function
+# ASM-NEXT:      0b                     end
+
+#      CHECK: Sections:
+# CHECK-NEXT:   - Type:            CUSTOM
+# CHECK-NEXT:     Name:            dylink.0
+# CHECK-NEXT:     MemorySize:      0
+# CHECK-NEXT:     MemoryAlignment: 0
+# CHECK-NEXT:     TableSize:       0
+# CHECK-NEXT:     TableAlignment:  0
+# CHECK-NEXT:     Needed:          []
+# CHECK-NEXT:     ImportInfo:
+# CHECK-NEXT:       - Module:          env
+# CHECK-NEXT:         Field:           weak_func
+# CHECK-NEXT:         Flags:           [ BINDING_WEAK, UNDEFINED ]

diff  --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp
index be1a82b9f5d8c..05d2d9be3525f 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -74,15 +74,22 @@ void DylinkSection::writeBody() {
     sub.writeTo(os);
   }
 
-  // Under certain circumstances we need to include extra information about the
-  // exports we are providing to the dynamic linker.  Currently this is only the
-  // case for TLS symbols where the exported value is relative to __tls_base
-  // rather than __memory_base.
+  // Under certain circumstances we need to include extra information about our
+  // exports and/or imports to the dynamic linker.
+  // For exports we need to notify the linker when an export is TLS since the
+  // exported value is relative to __tls_base rather than __memory_base.
+  // For imports we need to notify the dynamic linker when an import is weak
+  // so that knows not to report an error for such symbols.
+  std::vector<const Symbol *> importInfo;
   std::vector<const Symbol *> exportInfo;
   for (const Symbol *sym : symtab->getSymbols()) {
-    if (sym->isExported() && sym->isLive() && sym->isTLS() &&
-        isa<DefinedData>(sym)) {
-      exportInfo.push_back(sym);
+    if (sym->isLive()) {
+      if (sym->isExported() && sym->isTLS() && isa<DefinedData>(sym)) {
+        exportInfo.push_back(sym);
+      }
+      if (sym->isUndefWeak()) {
+        importInfo.push_back(sym);
+      }
     }
   }
 
@@ -104,6 +111,22 @@ void DylinkSection::writeBody() {
 
     sub.writeTo(os);
   }
+
+  if (!importInfo.empty()) {
+    SubSection sub(WASM_DYLINK_IMPORT_INFO);
+    writeUleb128(sub.os, importInfo.size(), "num imports");
+
+    for (const Symbol *sym : importInfo) {
+      LLVM_DEBUG(llvm::dbgs() << "imports info: " << toString(*sym) << "\n");
+      StringRef module = sym->importModule.getValueOr(defaultModule);
+      StringRef name = sym->importName.getValueOr(sym->getName());
+      writeStr(sub.os, module, "import module");
+      writeStr(sub.os, name, "import name");
+      writeUleb128(sub.os, sym->flags, "sym flags");
+    }
+
+    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
index de5b3b48fa37b..ccdb11702567e 100644
--- a/llvm/include/llvm/BinaryFormat/Wasm.h
+++ b/llvm/include/llvm/BinaryFormat/Wasm.h
@@ -36,7 +36,13 @@ struct WasmObjectHeader {
   uint32_t Version;
 };
 
-struct WasmDylinkExport {
+struct WasmDylinkImportInfo {
+  StringRef Module;
+  StringRef Field;
+  uint32_t Flags;
+};
+
+struct WasmDylinkExportInfo {
   StringRef Name;
   uint32_t Flags;
 };
@@ -47,7 +53,8 @@ struct WasmDylinkInfo {
   uint32_t TableSize;  // Table size in elements
   uint32_t TableAlignment;  // P2 alignment of table
   std::vector<StringRef> Needed; // Shared library dependencies
-  std::vector<WasmDylinkExport> ExportInfo; // Shared library dependencies
+  std::vector<WasmDylinkImportInfo> ImportInfo;
+  std::vector<WasmDylinkExportInfo> ExportInfo;
 };
 
 struct WasmProducerInfo {
@@ -346,6 +353,7 @@ enum : unsigned {
   WASM_DYLINK_MEM_INFO = 0x1,
   WASM_DYLINK_NEEDED = 0x2,
   WASM_DYLINK_EXPORT_INFO = 0x3,
+  WASM_DYLINK_IMPORT_INFO = 0x4,
 };
 
 // Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO

diff  --git a/llvm/include/llvm/ObjectYAML/WasmYAML.h b/llvm/include/llvm/ObjectYAML/WasmYAML.h
index bfae481fd1056..e3a1ba0d58a68 100644
--- a/llvm/include/llvm/ObjectYAML/WasmYAML.h
+++ b/llvm/include/llvm/ObjectYAML/WasmYAML.h
@@ -193,7 +193,13 @@ struct CustomSection : Section {
   yaml::BinaryRef Payload;
 };
 
-struct DylinkExport {
+struct DylinkImportInfo {
+  StringRef Module;
+  StringRef Field;
+  SymbolFlags Flags;
+};
+
+struct DylinkExportInfo {
   StringRef Name;
   SymbolFlags Flags;
 };
@@ -211,7 +217,8 @@ struct DylinkSection : CustomSection {
   uint32_t TableSize;
   uint32_t TableAlignment;
   std::vector<StringRef> Needed;
-  std::vector<DylinkExport> ExportInfo;
+  std::vector<DylinkImportInfo> ImportInfo;
+  std::vector<DylinkExportInfo> ExportInfo;
 };
 
 struct NameSection : CustomSection {
@@ -425,7 +432,8 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SymbolInfo)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::InitFunction)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ComdatEntry)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Comdat)
-LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::DylinkExport)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::DylinkImportInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::DylinkExportInfo)
 
 namespace llvm {
 namespace yaml {
@@ -570,8 +578,12 @@ template <> struct ScalarEnumerationTraits<WasmYAML::RelocType> {
   static void enumeration(IO &IO, WasmYAML::RelocType &Kind);
 };
 
-template <> struct MappingTraits<WasmYAML::DylinkExport> {
-  static void mapping(IO &IO, WasmYAML::DylinkExport &Export);
+template <> struct MappingTraits<WasmYAML::DylinkImportInfo> {
+  static void mapping(IO &IO, WasmYAML::DylinkImportInfo &Info);
+};
+
+template <> struct MappingTraits<WasmYAML::DylinkExportInfo> {
+  static void mapping(IO &IO, WasmYAML::DylinkExportInfo &Info);
 };
 
 } // end namespace yaml

diff  --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp
index ed23c53381246..fedfcae959122 100644
--- a/llvm/lib/Object/WasmObjectFile.cpp
+++ b/llvm/lib/Object/WasmObjectFile.cpp
@@ -391,6 +391,14 @@ Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
       }
       break;
     }
+    case wasm::WASM_DYLINK_IMPORT_INFO: {
+      uint32_t Count = readVaruint32(Ctx);
+      while (Count--) {
+        DylinkInfo.ImportInfo.push_back(
+            {readString(Ctx), readString(Ctx), readVaruint32(Ctx)});
+      }
+      break;
+    }
     default:
       LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type << "\n");
       Ctx.Ptr += Size;

diff  --git a/llvm/lib/ObjectYAML/WasmYAML.cpp b/llvm/lib/ObjectYAML/WasmYAML.cpp
index f84a80980ed6c..3f0172ebf361d 100644
--- a/llvm/lib/ObjectYAML/WasmYAML.cpp
+++ b/llvm/lib/ObjectYAML/WasmYAML.cpp
@@ -55,6 +55,7 @@ static void sectionMapping(IO &IO, WasmYAML::DylinkSection &Section) {
   IO.mapRequired("TableSize", Section.TableSize);
   IO.mapRequired("TableAlignment", Section.TableAlignment);
   IO.mapRequired("Needed", Section.Needed);
+  IO.mapOptional("ImportInfo", Section.ImportInfo);
   IO.mapOptional("ExportInfo", Section.ExportInfo);
 }
 
@@ -524,10 +525,17 @@ void MappingTraits<WasmYAML::SymbolInfo>::mapping(IO &IO,
   }
 }
 
-void MappingTraits<WasmYAML::DylinkExport>::mapping(
-    IO &IO, WasmYAML::DylinkExport &Export) {
-  IO.mapRequired("Name", Export.Name);
-  IO.mapRequired("Flags", Export.Flags);
+void MappingTraits<WasmYAML::DylinkImportInfo>::mapping(
+    IO &IO, WasmYAML::DylinkImportInfo &Info) {
+  IO.mapRequired("Module", Info.Module);
+  IO.mapRequired("Field", Info.Field);
+  IO.mapRequired("Flags", Info.Flags);
+}
+
+void MappingTraits<WasmYAML::DylinkExportInfo>::mapping(
+    IO &IO, WasmYAML::DylinkExportInfo &Info) {
+  IO.mapRequired("Name", Info.Name);
+  IO.mapRequired("Flags", Info.Flags);
 }
 
 void ScalarBitSetTraits<WasmYAML::LimitFlags>::bitset(

diff  --git a/llvm/tools/obj2yaml/wasm2yaml.cpp b/llvm/tools/obj2yaml/wasm2yaml.cpp
index 189ca0bd004d7..e4a56524e36bc 100644
--- a/llvm/tools/obj2yaml/wasm2yaml.cpp
+++ b/llvm/tools/obj2yaml/wasm2yaml.cpp
@@ -60,6 +60,8 @@ WasmDumper::dumpCustomSection(const WasmSection &WasmSec) {
     DylinkSec->TableSize = Info.TableSize;
     DylinkSec->TableAlignment = Info.TableAlignment;
     DylinkSec->Needed = Info.Needed;
+    for (const auto &Imp : Info.ImportInfo)
+      DylinkSec->ImportInfo.push_back({Imp.Module, Imp.Field, Imp.Flags});
     for (const auto &Exp : Info.ExportInfo)
       DylinkSec->ExportInfo.push_back({Exp.Name, Exp.Flags});
     CustomSec = std::move(DylinkSec);


        


More information about the llvm-commits mailing list