Skip to content

Commit a2cc5d6

Browse files
committed
hijack dylink section
1 parent c74c041 commit a2cc5d6

File tree

8 files changed

+88
-356
lines changed

8 files changed

+88
-356
lines changed

lib/binaryen.js

Lines changed: 0 additions & 341 deletions
This file was deleted.

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
},
1313
"dependencies": {
1414
"@protobufjs/utf8": "^1.1.0",
15-
"binaryen": "89.0.0-nightly.20190918",
15+
"binaryen": "89.0.0-nightly.20191012",
1616
"glob": "^7.1.4",
1717
"long": "^4.0.0",
1818
"opencollective-postinstall": "^2.0.0",

src/compiler.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,9 @@ import {
178178
writeI64,
179179
writeF32,
180180
writeF64,
181-
makeMap
181+
makeMap,
182+
writeU32Leb128,
183+
lengthU32Leb128
182184
} from "./util";
183185

184186
/** Compiler options. */
@@ -471,17 +473,21 @@ export class Compiler extends DiagnosticEmitter {
471473
if (file.source.sourceKind == SourceKind.USER_ENTRY) this.ensureModuleExports(file);
472474
}
473475

474-
// set up relocation hints
476+
// add dylink section if relocatable
475477
if (options.relocatable) {
476-
let memorySize = i64_align(memoryOffset, 16);
477-
if (options.isWasm64) {
478-
module.addGlobal("__memory_size", NativeType.I64, false, module.i64(i64_low(memorySize), i64_high(memorySize)));
479-
} else {
480-
module.addGlobal("__memory_size", NativeType.I32, false, module.i32(i64_low(memorySize)));
481-
}
482-
module.addGlobalExport("__memory_size", "__memory_size");
483-
module.addGlobal("__table_size", NativeType.I32, false, module.i32(functionTable.length));
484-
module.addGlobalExport("__table_size", "__table_size");
478+
let memorySize64 = i64_align(memoryOffset, 16);
479+
assert(i64_is_u32(memorySize64));
480+
let msize = i64_low(memorySize64);
481+
let tsize = functionTable.length;
482+
let size = lengthU32Leb128(msize) + lengthU32Leb128(tsize) + 3;
483+
let buffer = new Uint8Array(size);
484+
let offset = writeU32Leb128(msize, buffer, 0); // memory_size
485+
offset = writeU32Leb128(4, buffer, offset); // memory_align
486+
offset = writeU32Leb128(tsize, buffer, offset); // table_size
487+
offset = writeU32Leb128(0, buffer, offset); // table_align
488+
offset = writeU32Leb128(0, buffer, offset); // lib_count
489+
assert(offset == size);
490+
module.addCustomSection("dylink", buffer);
485491
}
486492

487493
return module;

src/glue/binaryen.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,8 @@ declare function _BinaryenModuleGetDebugInfoFileName(module: BinaryenModuleRef,
706706
declare function _BinaryenModuleGetFeatures(module: BinaryenModuleRef): BinaryenFeatureFlags;
707707
declare function _BinaryenModuleSetFeatures(module: BinaryenModuleRef, featureFlags: BinaryenFeatureFlags): void;
708708

709+
declare function _BinaryenAddCustomSection(module: BinaryenModuleRef, name: usize, contents: usize, contentsSize: BinaryenIndex): void;
710+
709711
declare type BinaryenRelooperRef = usize;
710712
declare type BinaryenRelooperBlockRef = usize;
711713

src/module.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,6 +1248,16 @@ export class Module {
12481248
_BinaryenSetStart(this.ref, func);
12491249
}
12501250

1251+
addCustomSection(name: string, contents: Uint8Array): void {
1252+
var cStr = this.allocStringCached(name);
1253+
var cArr = allocU8Array(contents);
1254+
try {
1255+
_BinaryenAddCustomSection(this.ref, cStr, cArr, contents.length);
1256+
} finally {
1257+
memory.free(cArr);
1258+
}
1259+
}
1260+
12511261
getOptimizeLevel(): i32 {
12521262
return _BinaryenGetOptimizeLevel();
12531263
}

src/util/binary.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,24 @@ export function writeF64(value: f64, buffer: Uint8Array, offset: i32): void {
7272
writeI32(i64_low(valueI64), buffer, offset);
7373
writeI32(i64_high(valueI64), buffer, offset + 4);
7474
}
75+
76+
/** Computes the length of a 32-bit unsigned integer when encoded as LEB128. */
77+
export function lengthU32Leb128(value: u32): i32 {
78+
var length = 1;
79+
while (value >>>= 7) ++length;
80+
return length;
81+
}
82+
83+
/** Writes a 32-bit unsigned integer to the specified buffer using LEB128 encoding. */
84+
export function writeU32Leb128(value: u32, buffer: Uint8Array, offset: i32): i32 {
85+
do {
86+
let b = value & 0x7f;
87+
if (value >>>= 7) {
88+
buffer[offset++] = b | 0x80;
89+
} else {
90+
buffer[offset++] = b;
91+
break;
92+
}
93+
} while (true);
94+
return offset;
95+
}

tests/compiler/relocatable.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,42 @@
1+
function readU32Leb128(buffer, offset) {
2+
var value = 0;
3+
var shift = 0;
4+
var length = buffer.length;
5+
while (offset < length) {
6+
let b = buffer[offset++];
7+
value |= (b & 0x7f) << shift;
8+
if (!(b & 0x80)) break;
9+
shift += 7;
10+
}
11+
return { value, offset };
12+
}
13+
14+
function readDylinkSection(buffer) {
15+
var view = new Uint8Array(buffer);
16+
var temp = readU32Leb128(view, 0);
17+
var memory_size = temp.value;
18+
temp = readU32Leb128(view, temp.offset);
19+
var memory_align = temp.value;
20+
temp = readU32Leb128(view, temp.offset);
21+
var table_size = temp.value;
22+
temp = readU32Leb128(view, temp.offset);
23+
var table_align = temp.value;
24+
// TODO: read required libraries
25+
// temp = readU32Leb128(view, temp.offset);
26+
// var lib_count = temp.value;
27+
// ...
28+
return { memory_size, memory_align, table_size, table_align };
29+
}
30+
131
exports.preInstantiate = function(imports, exports, module) {
232
// compiler generates initial = 1 because it doesn't know the imported value
333
// of env.memory_base yet, hence we need to import a suitable memory as well:
434
imports["env"]["memory"] = new WebAssembly.Memory({ initial: 2 });
535
imports["env"]["memory_base"] = 65536;
636
imports["env"]["table"] = new WebAssembly.Table({ element: "anyfunc", initial: 20 });
737
imports["env"]["table_base"] = 10;
38+
39+
var dylink = WebAssembly.Module.customSections(module, "dylink");
40+
if (dylink && dylink.length) console.log(readDylinkSection(dylink[0]));
41+
else throw Error("missing dylink section");
842
};

0 commit comments

Comments
 (0)