diff options
| author | Sam Clegg <sbc@chromium.org> | 2018-11-15 00:37:21 +0000 |
|---|---|---|
| committer | Sam Clegg <sbc@chromium.org> | 2018-11-15 00:37:21 +0000 |
| commit | bfb75348e29298beb9e62cf0e88a67f754b4ad58 (patch) | |
| tree | 0a6354e291754cbdae9192ac023a8c93dac3320e /lld/wasm/Writer.cpp | |
| parent | ae533d31af508b1b83bf637a4ddf84378ed07de1 (diff) | |
| download | bcm5719-llvm-bfb75348e29298beb9e62cf0e88a67f754b4ad58.tar.gz bcm5719-llvm-bfb75348e29298beb9e62cf0e88a67f754b4ad58.zip | |
[WebAssembly] Initial support for shared objects (-shared)
Based on the initial spec proposal:
https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
The llvm/codegen side of this is still missing but I believe this change is
still worth landing as an incremental step
Differential Revision: https://reviews.llvm.org/D54249
llvm-svn: 346918
Diffstat (limited to 'lld/wasm/Writer.cpp')
| -rw-r--r-- | lld/wasm/Writer.cpp | 60 |
1 files changed, 49 insertions, 11 deletions
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index cb413de67ba..60485081249 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -39,7 +39,6 @@ using namespace lld; using namespace lld::wasm; static constexpr int kStackAlignment = 16; -static constexpr int kInitialTableOffset = 1; static constexpr const char *kFunctionTableName = "__indirect_function_table"; namespace { @@ -90,6 +89,7 @@ private: void createCustomSections(); // Custom sections + void createDylinkSection(); void createRelocSections(); void createLinkingSection(); void createNameSection(); @@ -98,8 +98,13 @@ private: void writeSections(); uint64_t FileSize = 0; + uint32_t TableBase = 0; uint32_t NumMemoryPages = 0; uint32_t MaxMemoryPages = 0; + // Memory size and aligment. Written to the "dylink" section + // when build with -shared or -pie. + uint32_t MemAlign = 0; + uint32_t MemSize = 0; std::vector<const WasmSignature *> Types; DenseMap<WasmSignature, int32_t> TypeIndices; @@ -161,7 +166,7 @@ void Writer::createImportSection() { } if (Config->ImportTable) { - uint32_t TableSize = kInitialTableOffset + IndirectFunctions.size(); + uint32_t TableSize = TableBase + IndirectFunctions.size(); WasmImport Import; Import.Module = "env"; Import.Field = kFunctionTableName; @@ -259,7 +264,7 @@ void Writer::createTableSection() { // no address-taken function will fail at validation time since it is // a validation error to include a call_indirect instruction if there // is not table. - uint32_t TableSize = kInitialTableOffset + IndirectFunctions.size(); + uint32_t TableSize = TableBase + IndirectFunctions.size(); SyntheticSection *Section = createSyntheticSection(WASM_SEC_TABLE); raw_ostream &OS = Section->getStream(); @@ -325,12 +330,18 @@ void Writer::createElemSection() { writeUleb128(OS, 1, "segment count"); writeUleb128(OS, 0, "table index"); WasmInitExpr InitExpr; - InitExpr.Opcode = WASM_OPCODE_I32_CONST; - InitExpr.Value.Int32 = kInitialTableOffset; + if (Config->Pic) { + InitExpr.Opcode = WASM_OPCODE_GET_GLOBAL; + InitExpr.Value.Global = + cast<GlobalSymbol>(WasmSym::TableBase)->getGlobalIndex(); + } else { + InitExpr.Opcode = WASM_OPCODE_I32_CONST; + InitExpr.Value.Int32 = TableBase; + } writeInitExpr(OS, InitExpr); writeUleb128(OS, IndirectFunctions.size(), "elem count"); - uint32_t TableIndex = kInitialTableOffset; + uint32_t TableIndex = TableBase; for (const FunctionSymbol *Sym : IndirectFunctions) { assert(Sym->getTableIndex() == TableIndex); writeUleb128(OS, Sym->getFunctionIndex(), "function index"); @@ -425,6 +436,20 @@ public: raw_string_ostream OS{Body}; }; +// Create the custom "dylink" section containing information for the dynamic +// linker. +// See +// https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md +void Writer::createDylinkSection() { + SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, "dylink"); + raw_ostream &OS = Section->getStream(); + + writeUleb128(OS, MemSize, "MemSize"); + writeUleb128(OS, int(log2(MemAlign)), "MemAlign"); + writeUleb128(OS, IndirectFunctions.size(), "TableSize"); + writeUleb128(OS, 0, "TableAlign"); +} + // Create the custom "linking" section containing linker metadata. // This is only created when relocatable output is requested. void Writer::createLinkingSection() { @@ -599,7 +624,7 @@ void Writer::layoutMemory() { uint32_t MemoryPtr = 0; auto PlaceStack = [&]() { - if (Config->Relocatable) + if (Config->Relocatable || Config->Shared) return; MemoryPtr = alignTo(MemoryPtr, kStackAlignment); if (Config->ZStackSize != alignTo(Config->ZStackSize, kStackAlignment)) @@ -625,7 +650,9 @@ void Writer::layoutMemory() { if (WasmSym::DsoHandle) WasmSym::DsoHandle->setVirtualAddress(DataStart); + MemAlign = 0; for (OutputSegment *Seg : Segments) { + MemAlign = std::max(MemAlign, Seg->Alignment); MemoryPtr = alignTo(MemoryPtr, Seg->Alignment); Seg->StartVA = MemoryPtr; log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", Seg->Name, @@ -658,8 +685,8 @@ void Writer::layoutMemory() { else MemoryPtr = Config->InitialMemory; } - uint32_t MemSize = alignTo(MemoryPtr, WasmPageSize); - NumMemoryPages = MemSize / WasmPageSize; + MemSize = MemoryPtr; + NumMemoryPages = alignTo(MemoryPtr, WasmPageSize) / WasmPageSize; log("mem: total pages = " + Twine(NumMemoryPages)); if (Config->MaxMemory != 0) { @@ -682,6 +709,8 @@ SyntheticSection *Writer::createSyntheticSection(uint32_t Type, void Writer::createSections() { // Known sections + if (Config->Pic) + createDylinkSection(); createTypeSection(); createImportSection(); createFunctionSection(); @@ -874,7 +903,7 @@ void Writer::assignIndexes() { AddDefinedFunction(Func); } - uint32_t TableIndex = kInitialTableOffset; + uint32_t TableIndex = TableBase; auto HandleRelocs = [&](InputChunk *Chunk) { if (!Chunk->Live) return; @@ -926,6 +955,10 @@ void Writer::assignIndexes() { } static StringRef getOutputDataSegmentName(StringRef Name) { + // With PIC code we currently only support a single data segment since + // we only have a single __memory_base to use as our base address. + if (Config->Pic) + return "data"; if (!Config->MergeDataSegments) return Name; if (Name.startswith(".text.")) @@ -1010,9 +1043,14 @@ void Writer::calculateInitFunctions() { } void Writer::run() { - if (Config->Relocatable) + if (Config->Relocatable || Config->Pic) Config->GlobalBase = 0; + // For PIC code the table base is assigned dynamically by the loader. + // For non-PIC, we start at 1 so that accessing table index 0 always traps. + if (!Config->Pic) + TableBase = 1; + log("-- calculateImports"); calculateImports(); log("-- assignIndexes"); |

