Skip to content

Commit

Permalink
[WebAssembly] Add import info to dylink section of shared libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
sbc100 committed Oct 15, 2021
1 parent cfd155c commit 659a083
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 18 deletions.
32 changes: 32 additions & 0 deletions 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 ]
37 changes: 30 additions & 7 deletions lld/wasm/SyntheticSections.cpp
Expand Up @@ -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);
}
}
}

Expand All @@ -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) {
Expand Down
12 changes: 10 additions & 2 deletions llvm/include/llvm/BinaryFormat/Wasm.h
Expand Up @@ -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;
};
Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
22 changes: 17 additions & 5 deletions llvm/include/llvm/ObjectYAML/WasmYAML.h
Expand Up @@ -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;
};
Expand All @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Object/WasmObjectFile.cpp
Expand Up @@ -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;
Expand Down
16 changes: 12 additions & 4 deletions llvm/lib/ObjectYAML/WasmYAML.cpp
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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(
Expand Down
2 changes: 2 additions & 0 deletions llvm/tools/obj2yaml/wasm2yaml.cpp
Expand Up @@ -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);
Expand Down

0 comments on commit 659a083

Please sign in to comment.