Skip to content

Commit 02ae5a6

Browse files
authored
Fix read-write of dylink section (#1648)
The 'dylink' user section must be emitted before all other sections, per the spec (to allow simple parsing by loaders) This PR makes reading and writing of a dynamic library remain a valid dynamic library.
1 parent 5c01f25 commit 02ae5a6

File tree

5 files changed

+50
-9
lines changed

5 files changed

+50
-9
lines changed

check.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,21 @@ def run_crash_tests():
239239
run_command(cmd, expected_err='parse exception:', err_contains=True, expected_status=1)
240240

241241

242+
def run_dylink_tests():
243+
print "\n[ we emit dylink sections properly... ]\n"
244+
245+
for t in os.listdir(options.binaryen_test):
246+
if t.startswith('dylib') and t.endswith('.wasm'):
247+
print '..', t
248+
t = os.path.join(options.binaryen_test, t)
249+
cmd = WASM_OPT + [t, '-o', 'a.wasm']
250+
run_command(cmd)
251+
with open('a.wasm') as output:
252+
index = output.read().find('dylink')
253+
print ' ', index
254+
assert index == 11, 'dylink section must be first, right after the magic number etc.'
255+
256+
242257
def run_ctor_eval_tests():
243258
print '\n[ checking wasm-ctor-eval... ]\n'
244259

@@ -640,6 +655,7 @@ def main():
640655
run_wasm_dis_tests()
641656
run_wasm_merge_tests()
642657
run_crash_tests()
658+
run_dylink_tests()
643659
run_ctor_eval_tests()
644660
run_wasm_metadce_tests()
645661
if has_shell_timeout():

src/tools/wasm-merge.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ struct Mergeable {
106106
}
107107
}
108108
for (auto& section : wasm.userSections) {
109-
if (section.name == "dylink") {
109+
if (section.name == BinaryConsts::UserSections::Dylink) {
110110
WasmBinaryBuilder builder(wasm, section.data, false);
111111
totalMemorySize = std::max(totalMemorySize, builder.getU32LEB());
112112
totalTableSize = std::max(totalTableSize, builder.getU32LEB());

src/wasm-binary.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,8 @@ namespace UserSections {
340340
extern const char* Name;
341341
extern const char* SourceMapUrl;
342342

343+
extern const char* Dylink;
344+
343345
enum Subsection {
344346
NameFunction = 1,
345347
NameLocal = 2,
@@ -713,7 +715,9 @@ class WasmBinaryWriter {
713715
void writeNames();
714716
void writeSourceMapUrl();
715717
void writeSymbolMap();
716-
void writeUserSections();
718+
void writeEarlyUserSections();
719+
void writeLateUserSections();
720+
void writeUserSection(const UserSection& section);
717721

718722
void writeSourceMapProlog();
719723
void writeSourceMapEpilog();

src/wasm/wasm-binary.cpp

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ void WasmBinaryWriter::prepare() {
3939

4040
void WasmBinaryWriter::write() {
4141
writeHeader();
42+
43+
writeEarlyUserSections();
44+
4245
if (sourceMap) {
4346
writeSourceMapProlog();
4447
}
@@ -62,7 +65,7 @@ void WasmBinaryWriter::write() {
6265
writeSourceMapEpilog();
6366
}
6467

65-
writeUserSections();
68+
writeLateUserSections();
6669

6770
finishUp();
6871
}
@@ -535,17 +538,33 @@ void WasmBinaryWriter::writeSourceMapEpilog() {
535538
*sourceMap << "\"}";
536539
}
537540

538-
void WasmBinaryWriter::writeUserSections() {
541+
void WasmBinaryWriter::writeEarlyUserSections() {
542+
// The dylink section must be the first in the module, per
543+
// the spec, to allow simple parsing by loaders.
539544
for (auto& section : wasm->userSections) {
540-
auto start = startSection(0);
541-
writeInlineString(section.name.c_str());
542-
for (size_t i = 0; i < section.data.size(); i++) {
543-
o << uint8_t(section.data[i]);
545+
if (section.name == BinaryConsts::UserSections::Dylink) {
546+
writeUserSection(section);
544547
}
545-
finishSection(start);
546548
}
547549
}
548550

551+
void WasmBinaryWriter::writeLateUserSections() {
552+
for (auto& section : wasm->userSections) {
553+
if (section.name != BinaryConsts::UserSections::Dylink) {
554+
writeUserSection(section);
555+
}
556+
}
557+
}
558+
559+
void WasmBinaryWriter::writeUserSection(const UserSection& section) {
560+
auto start = startSection(0);
561+
writeInlineString(section.name.c_str());
562+
for (size_t i = 0; i < section.data.size(); i++) {
563+
o << uint8_t(section.data[i]);
564+
}
565+
finishSection(start);
566+
}
567+
549568
void WasmBinaryWriter::writeDebugLocation(Expression* curr, Function* func) {
550569
auto& debugLocations = func->debugLocations;
551570
auto iter = debugLocations.find(curr);

src/wasm/wasm.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ namespace BinaryConsts {
2929
namespace UserSections {
3030
const char* Name = "name";
3131
const char* SourceMapUrl = "sourceMappingURL";
32+
33+
const char* Dylink = "dylink";
3234
}
3335
}
3436

0 commit comments

Comments
 (0)