Skip to content

Commit 659a083

Browse files
committed
[WebAssembly] Add import info to dylink section of shared libraries
See WebAssembly/tool-conventions#175 Differential Revision: https://reviews.llvm.org/D111345
1 parent cfd155c commit 659a083

File tree

7 files changed

+111
-18
lines changed

7 files changed

+111
-18
lines changed

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
2+
# RUN: wasm-ld --experimental-pic -shared -o %t.wasm %t.o
3+
# RUN: obj2yaml %t.wasm | FileCheck %s
4+
# RUN: llvm-objdump -d %t.wasm | FileCheck %s -check-prefix=ASM
5+
6+
# Verify the weak undefined symbols are marked as such in the
7+
# dylink section.
8+
9+
.weak weak_func
10+
.functype weak_func () -> (i32)
11+
12+
.globl call_weak
13+
call_weak:
14+
# ASM: <call_weak>:
15+
.functype call_weak () -> (i32)
16+
call weak_func
17+
# ASM: 10 80 80 80 80 00 call 0
18+
end_function
19+
# ASM-NEXT: 0b end
20+
21+
# CHECK: Sections:
22+
# CHECK-NEXT: - Type: CUSTOM
23+
# CHECK-NEXT: Name: dylink.0
24+
# CHECK-NEXT: MemorySize: 0
25+
# CHECK-NEXT: MemoryAlignment: 0
26+
# CHECK-NEXT: TableSize: 0
27+
# CHECK-NEXT: TableAlignment: 0
28+
# CHECK-NEXT: Needed: []
29+
# CHECK-NEXT: ImportInfo:
30+
# CHECK-NEXT: - Module: env
31+
# CHECK-NEXT: Field: weak_func
32+
# CHECK-NEXT: Flags: [ BINDING_WEAK, UNDEFINED ]

lld/wasm/SyntheticSections.cpp

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,22 @@ void DylinkSection::writeBody() {
7474
sub.writeTo(os);
7575
}
7676

77-
// Under certain circumstances we need to include extra information about the
78-
// exports we are providing to the dynamic linker. Currently this is only the
79-
// case for TLS symbols where the exported value is relative to __tls_base
80-
// rather than __memory_base.
77+
// Under certain circumstances we need to include extra information about our
78+
// exports and/or imports to the dynamic linker.
79+
// For exports we need to notify the linker when an export is TLS since the
80+
// exported value is relative to __tls_base rather than __memory_base.
81+
// For imports we need to notify the dynamic linker when an import is weak
82+
// so that knows not to report an error for such symbols.
83+
std::vector<const Symbol *> importInfo;
8184
std::vector<const Symbol *> exportInfo;
8285
for (const Symbol *sym : symtab->getSymbols()) {
83-
if (sym->isExported() && sym->isLive() && sym->isTLS() &&
84-
isa<DefinedData>(sym)) {
85-
exportInfo.push_back(sym);
86+
if (sym->isLive()) {
87+
if (sym->isExported() && sym->isTLS() && isa<DefinedData>(sym)) {
88+
exportInfo.push_back(sym);
89+
}
90+
if (sym->isUndefWeak()) {
91+
importInfo.push_back(sym);
92+
}
8693
}
8794
}
8895

@@ -104,6 +111,22 @@ void DylinkSection::writeBody() {
104111

105112
sub.writeTo(os);
106113
}
114+
115+
if (!importInfo.empty()) {
116+
SubSection sub(WASM_DYLINK_IMPORT_INFO);
117+
writeUleb128(sub.os, importInfo.size(), "num imports");
118+
119+
for (const Symbol *sym : importInfo) {
120+
LLVM_DEBUG(llvm::dbgs() << "imports info: " << toString(*sym) << "\n");
121+
StringRef module = sym->importModule.getValueOr(defaultModule);
122+
StringRef name = sym->importName.getValueOr(sym->getName());
123+
writeStr(sub.os, module, "import module");
124+
writeStr(sub.os, name, "import name");
125+
writeUleb128(sub.os, sym->flags, "sym flags");
126+
}
127+
128+
sub.writeTo(os);
129+
}
107130
}
108131

109132
uint32_t TypeSection::registerType(const WasmSignature &sig) {

llvm/include/llvm/BinaryFormat/Wasm.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,13 @@ struct WasmObjectHeader {
3636
uint32_t Version;
3737
};
3838

39-
struct WasmDylinkExport {
39+
struct WasmDylinkImportInfo {
40+
StringRef Module;
41+
StringRef Field;
42+
uint32_t Flags;
43+
};
44+
45+
struct WasmDylinkExportInfo {
4046
StringRef Name;
4147
uint32_t Flags;
4248
};
@@ -47,7 +53,8 @@ struct WasmDylinkInfo {
4753
uint32_t TableSize; // Table size in elements
4854
uint32_t TableAlignment; // P2 alignment of table
4955
std::vector<StringRef> Needed; // Shared library dependencies
50-
std::vector<WasmDylinkExport> ExportInfo; // Shared library dependencies
56+
std::vector<WasmDylinkImportInfo> ImportInfo;
57+
std::vector<WasmDylinkExportInfo> ExportInfo;
5158
};
5259

5360
struct WasmProducerInfo {
@@ -346,6 +353,7 @@ enum : unsigned {
346353
WASM_DYLINK_MEM_INFO = 0x1,
347354
WASM_DYLINK_NEEDED = 0x2,
348355
WASM_DYLINK_EXPORT_INFO = 0x3,
356+
WASM_DYLINK_IMPORT_INFO = 0x4,
349357
};
350358

351359
// Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO

llvm/include/llvm/ObjectYAML/WasmYAML.h

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,13 @@ struct CustomSection : Section {
193193
yaml::BinaryRef Payload;
194194
};
195195

196-
struct DylinkExport {
196+
struct DylinkImportInfo {
197+
StringRef Module;
198+
StringRef Field;
199+
SymbolFlags Flags;
200+
};
201+
202+
struct DylinkExportInfo {
197203
StringRef Name;
198204
SymbolFlags Flags;
199205
};
@@ -211,7 +217,8 @@ struct DylinkSection : CustomSection {
211217
uint32_t TableSize;
212218
uint32_t TableAlignment;
213219
std::vector<StringRef> Needed;
214-
std::vector<DylinkExport> ExportInfo;
220+
std::vector<DylinkImportInfo> ImportInfo;
221+
std::vector<DylinkExportInfo> ExportInfo;
215222
};
216223

217224
struct NameSection : CustomSection {
@@ -425,7 +432,8 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SymbolInfo)
425432
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::InitFunction)
426433
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ComdatEntry)
427434
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Comdat)
428-
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::DylinkExport)
435+
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::DylinkImportInfo)
436+
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::DylinkExportInfo)
429437

430438
namespace llvm {
431439
namespace yaml {
@@ -570,8 +578,12 @@ template <> struct ScalarEnumerationTraits<WasmYAML::RelocType> {
570578
static void enumeration(IO &IO, WasmYAML::RelocType &Kind);
571579
};
572580

573-
template <> struct MappingTraits<WasmYAML::DylinkExport> {
574-
static void mapping(IO &IO, WasmYAML::DylinkExport &Export);
581+
template <> struct MappingTraits<WasmYAML::DylinkImportInfo> {
582+
static void mapping(IO &IO, WasmYAML::DylinkImportInfo &Info);
583+
};
584+
585+
template <> struct MappingTraits<WasmYAML::DylinkExportInfo> {
586+
static void mapping(IO &IO, WasmYAML::DylinkExportInfo &Info);
575587
};
576588

577589
} // end namespace yaml

llvm/lib/Object/WasmObjectFile.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,14 @@ Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
391391
}
392392
break;
393393
}
394+
case wasm::WASM_DYLINK_IMPORT_INFO: {
395+
uint32_t Count = readVaruint32(Ctx);
396+
while (Count--) {
397+
DylinkInfo.ImportInfo.push_back(
398+
{readString(Ctx), readString(Ctx), readVaruint32(Ctx)});
399+
}
400+
break;
401+
}
394402
default:
395403
LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type << "\n");
396404
Ctx.Ptr += Size;

llvm/lib/ObjectYAML/WasmYAML.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ static void sectionMapping(IO &IO, WasmYAML::DylinkSection &Section) {
5555
IO.mapRequired("TableSize", Section.TableSize);
5656
IO.mapRequired("TableAlignment", Section.TableAlignment);
5757
IO.mapRequired("Needed", Section.Needed);
58+
IO.mapOptional("ImportInfo", Section.ImportInfo);
5859
IO.mapOptional("ExportInfo", Section.ExportInfo);
5960
}
6061

@@ -524,10 +525,17 @@ void MappingTraits<WasmYAML::SymbolInfo>::mapping(IO &IO,
524525
}
525526
}
526527

527-
void MappingTraits<WasmYAML::DylinkExport>::mapping(
528-
IO &IO, WasmYAML::DylinkExport &Export) {
529-
IO.mapRequired("Name", Export.Name);
530-
IO.mapRequired("Flags", Export.Flags);
528+
void MappingTraits<WasmYAML::DylinkImportInfo>::mapping(
529+
IO &IO, WasmYAML::DylinkImportInfo &Info) {
530+
IO.mapRequired("Module", Info.Module);
531+
IO.mapRequired("Field", Info.Field);
532+
IO.mapRequired("Flags", Info.Flags);
533+
}
534+
535+
void MappingTraits<WasmYAML::DylinkExportInfo>::mapping(
536+
IO &IO, WasmYAML::DylinkExportInfo &Info) {
537+
IO.mapRequired("Name", Info.Name);
538+
IO.mapRequired("Flags", Info.Flags);
531539
}
532540

533541
void ScalarBitSetTraits<WasmYAML::LimitFlags>::bitset(

llvm/tools/obj2yaml/wasm2yaml.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ WasmDumper::dumpCustomSection(const WasmSection &WasmSec) {
6060
DylinkSec->TableSize = Info.TableSize;
6161
DylinkSec->TableAlignment = Info.TableAlignment;
6262
DylinkSec->Needed = Info.Needed;
63+
for (const auto &Imp : Info.ImportInfo)
64+
DylinkSec->ImportInfo.push_back({Imp.Module, Imp.Field, Imp.Flags});
6365
for (const auto &Exp : Info.ExportInfo)
6466
DylinkSec->ExportInfo.push_back({Exp.Name, Exp.Flags});
6567
CustomSec = std::move(DylinkSec);

0 commit comments

Comments
 (0)