[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