diff options
-rw-r--r-- | src/ir/table-utils.h | 15 | ||||
-rw-r--r-- | src/passes/Print.cpp | 17 | ||||
-rw-r--r-- | src/wasm-binary.h | 3 | ||||
-rw-r--r-- | src/wasm.h | 10 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 56 | ||||
-rw-r--r-- | test/dylib.wasm | bin | 306 -> 433 bytes | |||
-rw-r--r-- | test/dylib.wasm.fromBinary | 101 | ||||
-rw-r--r-- | test/passes/multi_line_table.bin.txt | 6 |
8 files changed, 160 insertions, 48 deletions
diff --git a/src/ir/table-utils.h b/src/ir/table-utils.h index 3c49ab16a..e0453dece 100644 --- a/src/ir/table-utils.h +++ b/src/ir/table-utils.h @@ -67,10 +67,23 @@ inline Table::Segment& ensureTableWithOneSegment(Table& table, Module& wasm) { // Appends a name to the table. This assumes the table has 0 or 1 segments, // as with 2 or more it's ambiguous what we should do (use a hole in the middle // or not). +// This works on code from wasm-ld, but on arbitrary code it may not be valid +// in the presence of a dynamic linking section. Specifically, we assume the +// module has a single table segment, and that the dylink section indicates +// we can validly append to that segment, see the check below. inline Index append(Table& table, Name name, Module& wasm) { auto& segment = ensureTableWithOneSegment(table, wasm); - table.segments[0]; auto tableIndex = segment.data.size(); + if (wasm.dylinkSection) { + if (segment.data.size() != wasm.dylinkSection->tableSize) { + Fatal() << "Appending to the table in a module with a dylink section " + "that has tableSize which indicates it wants to reserve more " + "table space than the actual table elements in the module. " + "We don't know how to correctly update the dylink section in " + "that case."; + } + wasm.dylinkSection->tableSize++; + } segment.data.push_back(name); table.initial = table.initial + 1; return tableIndex; diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index daa7e7ac6..d6dbb3300 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -2340,6 +2340,20 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> { o << "\")" << maybeNewLine; } } + void printDylinkSection(const std::unique_ptr<DylinkSection>& dylinkSection) { + doIndent(o, indent) << ";; dylink section\n"; + doIndent(o, indent) << ";; memorysize: " << dylinkSection->memorySize + << '\n'; + doIndent(o, indent) << ";; memoryalignment: " + << dylinkSection->memoryAlignment << '\n'; + doIndent(o, indent) << ";; tablesize: " << dylinkSection->tableSize + << '\n'; + doIndent(o, indent) << ";; tablealignment: " + << dylinkSection->tableAlignment << '\n'; + for (auto& neededDynlib : dylinkSection->neededDynlibs) { + doIndent(o, indent) << ";; needed dynlib: " << neededDynlib << '\n'; + } + } void visitModule(Module* curr) { currModule = curr; o << '('; @@ -2388,6 +2402,9 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> { } ModuleUtils::iterDefinedFunctions( *curr, [&](Function* func) { visitFunction(func); }); + if (curr->dylinkSection) { + printDylinkSection(curr->dylinkSection); + } for (auto& section : curr->userSections) { doIndent(o, indent); o << ";; custom section \"" << section.name << "\", size " diff --git a/src/wasm-binary.h b/src/wasm-binary.h index a90d5fb5f..1a13dbb75 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1011,10 +1011,10 @@ public: void writeNames(); void writeSourceMapUrl(); void writeSymbolMap(); - void writeEarlyUserSections(); void writeLateUserSections(); void writeUserSection(const UserSection& section); void writeFeaturesSection(); + void writeDylinkSection(); void initializeDebugInfo(); void writeSourceMapProlog(); @@ -1257,6 +1257,7 @@ public: static Name escape(Name name); void readNames(size_t); void readFeatures(size_t); + void readDylink(size_t); // Debug information reading helpers void setDebugLocations(std::istream* sourceMap_) { sourceMap = sourceMap_; } diff --git a/src/wasm.h b/src/wasm.h index 21fef1049..73f22e7d7 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -1460,6 +1460,13 @@ public: std::vector<char> data; }; +// The optional "dylink" section is used in dynamic linking. +class DylinkSection { +public: + Index memorySize, memoryAlignment, tableSize, tableAlignment; + std::vector<Name> neededDynlibs; +}; + class Module { public: // wasm contents (generally you shouldn't access these from outside, except @@ -1475,6 +1482,9 @@ public: std::vector<UserSection> userSections; + // Optional user section IR representation. + std::unique_ptr<DylinkSection> dylinkSection; + // Source maps debug info. std::vector<std::string> debugInfoFileNames; diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 8d9696aa2..c36789828 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -38,7 +38,7 @@ void WasmBinaryWriter::prepare() { void WasmBinaryWriter::write() { writeHeader(); - writeEarlyUserSections(); + writeDylinkSection(); initializeDebugInfo(); if (sourceMap) { @@ -632,16 +632,6 @@ void WasmBinaryWriter::writeSourceMapEpilog() { *sourceMap << "\"}"; } -void WasmBinaryWriter::writeEarlyUserSections() { - // The dylink section must be the first in the module, per - // the spec, to allow simple parsing by loaders. - for (auto& section : wasm->userSections) { - if (section.name == BinaryConsts::UserSections::Dylink) { - writeUserSection(section); - } - } -} - void WasmBinaryWriter::writeLateUserSections() { for (auto& section : wasm->userSections) { if (section.name != BinaryConsts::UserSections::Dylink) { @@ -707,6 +697,24 @@ void WasmBinaryWriter::writeFeaturesSection() { finishSection(start); } +void WasmBinaryWriter::writeDylinkSection() { + if (!wasm->dylinkSection) { + return; + } + + auto start = startSection(BinaryConsts::User); + writeInlineString(BinaryConsts::UserSections::Dylink); + o << U32LEB(wasm->dylinkSection->memorySize); + o << U32LEB(wasm->dylinkSection->memoryAlignment); + o << U32LEB(wasm->dylinkSection->tableSize); + o << U32LEB(wasm->dylinkSection->tableAlignment); + o << U32LEB(wasm->dylinkSection->neededDynlibs.size()); + for (auto& neededDynlib : wasm->dylinkSection->neededDynlibs) { + writeInlineString(neededDynlib.c_str()); + } + finishSection(start); +} + void WasmBinaryWriter::writeDebugLocation(const Function::DebugLocation& loc) { if (loc == lastDebugLocation) { return; @@ -963,6 +971,8 @@ void WasmBinaryBuilder::readUserSection(size_t payloadLen) { readNames(payloadLen); } else if (sectionName.equals(BinaryConsts::UserSections::TargetFeatures)) { readFeatures(payloadLen); + } else if (sectionName.equals(BinaryConsts::UserSections::Dylink)) { + readDylink(payloadLen); } else { // an unfamiliar custom section if (sectionName.equals(BinaryConsts::UserSections::Linking)) { @@ -2122,8 +2132,8 @@ void WasmBinaryBuilder::readFeatures(size_t payloadLen) { wasm.features = FeatureSet::MVP; auto sectionPos = pos; - size_t num_feats = getU32LEB(); - for (size_t i = 0; i < num_feats; ++i) { + size_t numFeatures = getU32LEB(); + for (size_t i = 0; i < numFeatures; ++i) { uint8_t prefix = getInt8(); if (prefix != BinaryConsts::FeatureUsed) { if (prefix == BinaryConsts::FeatureRequired) { @@ -2171,6 +2181,26 @@ void WasmBinaryBuilder::readFeatures(size_t payloadLen) { } } +void WasmBinaryBuilder::readDylink(size_t payloadLen) { + wasm.dylinkSection = make_unique<DylinkSection>(); + + auto sectionPos = pos; + + wasm.dylinkSection->memorySize = getU32LEB(); + wasm.dylinkSection->memoryAlignment = getU32LEB(); + wasm.dylinkSection->tableSize = getU32LEB(); + wasm.dylinkSection->tableAlignment = getU32LEB(); + + size_t numNeededDynlibs = getU32LEB(); + for (size_t i = 0; i < numNeededDynlibs; ++i) { + wasm.dylinkSection->neededDynlibs.push_back(getInlineString()); + } + + if (pos != sectionPos + payloadLen) { + throwError("bad features section size"); + } +} + BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { if (pos == endOfFunction) { throwError("Reached function end without seeing End opcode"); diff --git a/test/dylib.wasm b/test/dylib.wasm Binary files differindex 06ac55e86..ba62a3bef 100644 --- a/test/dylib.wasm +++ b/test/dylib.wasm diff --git a/test/dylib.wasm.fromBinary b/test/dylib.wasm.fromBinary index 45d64fb67..23db9fe85 100644 --- a/test/dylib.wasm.fromBinary +++ b/test/dylib.wasm.fromBinary @@ -1,50 +1,87 @@ (module - (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) + (type $none_=>_none (func)) (type $i32_=>_i32 (func (param i32) (result i32))) - (import "env" "memory" (memory $2 256)) - (data (global.get $gimport$0) "hello, world!") - (import "env" "table" (table $timport$3 0 funcref)) - (import "env" "memoryBase" (global $gimport$0 i32)) - (import "env" "tableBase" (global $gimport$4 i32)) - (import "env" "_puts" (func $fimport$1 (param i32) (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (import "env" "memory" (memory $5 0)) + (data (global.get $gimport$4) "*\00\00\00") + (import "env" "__memory_base" (global $gimport$4 i32)) + (import "env" "g$waka_mine" (func $fimport$0 (result i32))) + (import "env" "g$waka_others" (func $fimport$1 (result i32))) + (import "env" "fp$_Z16waka_func_theirsi$ii" (func $fimport$2 (result i32))) + (import "env" "fp$_Z14waka_func_minei$ii" (func $fimport$3 (result i32))) (global $global$0 (mut i32) (i32.const 0)) (global $global$1 (mut i32) (i32.const 0)) - (global $global$2 i32 (i32.const 0)) - (export "__post_instantiate" (func $2)) - (export "_main" (func $0)) - (export "runPostSets" (func $1)) - (export "_str" (global $global$2)) - (func $0 (; 1 ;) (result i32) - (block $label$1 (result i32) - (drop - (call $fimport$1 - (global.get $gimport$0) - ) - ) - (i32.const 0) - ) - ) - (func $1 (; 2 ;) + (global $global$2 (mut i32) (i32.const 0)) + (global $global$3 (mut i32) (i32.const 0)) + (global $global$4 i32 (i32.const 0)) + (global $global$5 i32 (i32.const 0)) + (export "__wasm_apply_relocs" (func $0)) + (export "_Z14waka_func_minei" (func $1)) + (export "__original_main" (func $2)) + (export "waka_mine" (global $global$4)) + (export "main" (func $3)) + (export "__dso_handle" (global $global$5)) + (export "__post_instantiate" (func $4)) + (func $0 (; 4 ;) (nop) ) - (func $2 (; 3 ;) - (block $label$1 - (global.set $global$0 + (func $1 (; 5 ;) (param $0 i32) (result i32) + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (func $2 (; 6 ;) (result i32) + (i32.add + (i32.load + (global.get $global$3) + ) + (i32.add + (i32.load + (global.get $global$2) + ) (i32.add - (global.get $gimport$0) - (i32.const 16) + (global.get $global$0) + (global.get $global$1) ) ) - (global.set $global$1 + ) + ) + (func $3 (; 7 ;) (param $0 i32) (param $1 i32) (result i32) + (i32.add + (i32.load + (global.get $global$3) + ) + (i32.add + (i32.load + (global.get $global$2) + ) (i32.add (global.get $global$0) - (i32.const 5242880) + (global.get $global$1) ) ) - (call $1) ) ) - ;; custom section "dylink", size 5 + (func $4 (; 8 ;) + (global.set $global$2 + (call $fimport$0) + ) + (global.set $global$3 + (call $fimport$1) + ) + (global.set $global$0 + (call $fimport$2) + ) + (global.set $global$1 + (call $fimport$3) + ) + ) + ;; dylink section + ;; memorysize: 4 + ;; memoryalignment: 2 + ;; tablesize: 0 + ;; tablealignment: 0 ) diff --git a/test/passes/multi_line_table.bin.txt b/test/passes/multi_line_table.bin.txt index 3212e1c14..c4fd4d013 100644 --- a/test/passes/multi_line_table.bin.txt +++ b/test/passes/multi_line_table.bin.txt @@ -466,7 +466,11 @@ file_names[ 1]: (local.get $0) ) ) - ;; custom section "dylink", size 5 + ;; dylink section + ;; memorysize: 0 + ;; memoryalignment: 0 + ;; tablesize: 0 + ;; tablealignment: 0 ;; custom section ".debug_info", size 130 ;; custom section ".debug_abbrev", size 100 ;; custom section ".debug_line", size 145 |