Skip to content

Commit 73c20f6

Browse files
authored
Support new dylink.0 custom section format (#15019)
See also: llvm change: https://reviews.llvm.org/D109595 wabt change: WebAssembly/wabt#1707 binaryen change: WebAssembly/binaryen#4141
1 parent a8d5565 commit 73c20f6

File tree

3 files changed

+125
-45
lines changed

3 files changed

+125
-45
lines changed

src/library_dylink.js

Lines changed: 76 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -256,60 +256,104 @@ var LibraryDylink = {
256256
// returns the side module metadata as an object
257257
// { memorySize, memoryAlign, tableSize, tableAlign, neededDynlibs}
258258
$getDylinkMetadata: function(binary) {
259-
var next = 0;
259+
var offset = 0;
260+
var end = 0;
261+
262+
function getU8() {
263+
return binary[offset++];
264+
}
265+
260266
function getLEB() {
261267
var ret = 0;
262268
var mul = 1;
263269
while (1) {
264-
var byte = binary[next++];
270+
var byte = binary[offset++];
265271
ret += ((byte & 0x7f) * mul);
266272
mul *= 0x80;
267273
if (!(byte & 0x80)) break;
268274
}
269275
return ret;
270276
}
271277

278+
function getString() {
279+
var len = getLEB();
280+
offset += len;
281+
return UTF8ArrayToString(binary, offset - len, len);
282+
}
283+
284+
var name = 'dylink.0';
272285
if (binary instanceof WebAssembly.Module) {
273-
var dylinkSection = WebAssembly.Module.customSections(binary, "dylink");
286+
var dylinkSection = WebAssembly.Module.customSections(binary, name);
287+
if (dylinkSection.length === 0) {
288+
name = 'dylink'
289+
dylinkSection = WebAssembly.Module.customSections(binary, name);
290+
}
274291
assert(dylinkSection.length != 0, 'need dylink section');
275292
binary = new Uint8Array(dylinkSection[0]);
293+
end = binary.length
276294
} else {
277295
var int32View = new Uint32Array(new Uint8Array(binary.subarray(0, 24)).buffer);
278296
assert(int32View[0] == 0x6d736100, 'need to see wasm magic number'); // \0asm
279-
// we should see the dylink section right after the magic number and wasm version
297+
// we should see the dylink custom section right after the magic number and wasm version
280298
assert(binary[8] === 0, 'need the dylink section to be first')
281-
next = 9;
282-
getLEB(); //section size
283-
assert(binary[next] === 6); next++; // size of "dylink" string
284-
assert(binary[next] === 'd'.charCodeAt(0)); next++;
285-
assert(binary[next] === 'y'.charCodeAt(0)); next++;
286-
assert(binary[next] === 'l'.charCodeAt(0)); next++;
287-
assert(binary[next] === 'i'.charCodeAt(0)); next++;
288-
assert(binary[next] === 'n'.charCodeAt(0)); next++;
289-
assert(binary[next] === 'k'.charCodeAt(0)); next++;
290-
}
291-
292-
var customSection = {};
293-
customSection.memorySize = getLEB();
294-
customSection.memoryAlign = getLEB();
295-
customSection.tableSize = getLEB();
296-
customSection.tableAlign = getLEB();
299+
offset = 9;
300+
var section_size = getLEB(); //section size
301+
end = offset + section_size;
302+
name = getString();
303+
}
304+
305+
var customSection = { neededDynlibs: [] };
306+
if (name == 'dylink') {
307+
customSection.memorySize = getLEB();
308+
customSection.memoryAlign = getLEB();
309+
customSection.tableSize = getLEB();
310+
customSection.tableAlign = getLEB();
311+
// shared libraries this module needs. We need to load them first, so that
312+
// current module could resolve its imports. (see tools/shared.py
313+
// WebAssembly.make_shared_library() for "dylink" section extension format)
314+
var neededDynlibsCount = getLEB();
315+
for (var i = 0; i < neededDynlibsCount; ++i) {
316+
var name = getString();
317+
customSection.neededDynlibs.push(name);
318+
}
319+
} else {
320+
assert(name === 'dylink.0');
321+
var WASM_DYLINK_MEM_INFO = 0x1;
322+
var WASM_DYLINK_NEEDED = 0x2;
323+
while (offset < end) {
324+
var subsectionType = getU8();
325+
var subsectionSize = getLEB();
326+
if (subsectionType === WASM_DYLINK_MEM_INFO) {
327+
customSection.memorySize = getLEB();
328+
customSection.memoryAlign = getLEB();
329+
customSection.tableSize = getLEB();
330+
customSection.tableAlign = getLEB();
331+
} else if (subsectionType === WASM_DYLINK_NEEDED) {
332+
var neededDynlibsCount = getLEB();
333+
for (var i = 0; i < neededDynlibsCount; ++i) {
334+
var name = getString();
335+
customSection.neededDynlibs.push(name);
336+
}
337+
} else {
338+
#if ASSERTIONS
339+
err('unknown dylink.0 subsection: ' + subsectionType)
340+
#endif
341+
// unknown subsection
342+
offset += subsectionSize;
343+
}
344+
}
345+
}
346+
297347
#if ASSERTIONS
298348
var tableAlign = Math.pow(2, customSection.tableAlign);
299349
assert(tableAlign === 1, 'invalid tableAlign ' + tableAlign);
300350
#endif
301-
// shared libraries this module needs. We need to load them first, so that
302-
// current module could resolve its imports. (see tools/shared.py
303-
// WebAssembly.make_shared_library() for "dylink" section extension format)
304-
var neededDynlibsCount = getLEB();
305-
customSection.neededDynlibs = [];
306-
for (var i = 0; i < neededDynlibsCount; ++i) {
307-
var nameLen = getLEB();
308-
var nameUTF8 = binary.subarray(next, next + nameLen);
309-
next += nameLen;
310-
var name = UTF8ArrayToString(nameUTF8, 0);
311-
customSection.neededDynlibs.push(name);
312-
}
351+
352+
#if DYLINK_DEBUG
353+
err('dylink needed:' + customSection.neededDynlibs);
354+
#endif
355+
356+
assert(offset == end);
313357
return customSection;
314358
},
315359

tools/building.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1266,7 +1266,7 @@ def is_wasm_dylib(filename):
12661266
section = next(module.sections())
12671267
if section.type == webassembly.SecType.CUSTOM:
12681268
module.seek(section.offset)
1269-
if module.readString() == 'dylink':
1269+
if module.readString() in ('dylink', 'dylink.0'):
12701270
return True
12711271
return False
12721272

tools/webassembly.py

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,11 @@ class ExternType(IntEnum):
135135
EVENT = 4
136136

137137

138+
class DylinkType(IntEnum):
139+
MEM_INFO = 1
140+
NEEDED = 2
141+
142+
138143
Section = namedtuple('Section', ['type', 'size', 'offset'])
139144
Limits = namedtuple('Limits', ['flags', 'initial', 'maximum'])
140145
Import = namedtuple('Import', ['kind', 'module', 'field'])
@@ -178,7 +183,13 @@ def readLimits(self):
178183
return Limits(flags, initial, maximum)
179184

180185
def seek(self, offset):
181-
self.buf.seek(offset)
186+
return self.buf.seek(offset)
187+
188+
def tell(self):
189+
return self.buf.tell()
190+
191+
def skip(self, count):
192+
self.buf.seek(count, os.SEEK_CUR)
182193

183194
def sections(self):
184195
"""Generator that lazily returns sections from the wasm file."""
@@ -200,18 +211,43 @@ def parse_dylink_section(wasm_file):
200211
module.seek(dylink_section.offset)
201212
# section name
202213
section_name = module.readString()
203-
assert section_name == 'dylink'
204-
mem_size = module.readULEB()
205-
mem_align = module.readULEB()
206-
table_size = module.readULEB()
207-
table_align = module.readULEB()
208-
209214
needed = []
210-
needed_count = module.readULEB()
211-
while needed_count:
212-
libname = module.readString()
213-
needed.append(libname)
214-
needed_count -= 1
215+
216+
if section_name == 'dylink':
217+
mem_size = module.readULEB()
218+
mem_align = module.readULEB()
219+
table_size = module.readULEB()
220+
table_align = module.readULEB()
221+
222+
needed_count = module.readULEB()
223+
while needed_count:
224+
libname = module.readString()
225+
needed.append(libname)
226+
needed_count -= 1
227+
elif section_name == 'dylink.0':
228+
section_end = dylink_section.offset + dylink_section.size
229+
while module.tell() < section_end:
230+
subsection_type = module.readULEB()
231+
subsection_size = module.readULEB()
232+
end = module.tell() + subsection_size
233+
if subsection_type == DylinkType.MEM_INFO:
234+
mem_size = module.readULEB()
235+
mem_align = module.readULEB()
236+
table_size = module.readULEB()
237+
table_align = module.readULEB()
238+
elif subsection_type == DylinkType.NEEDED:
239+
needed_count = module.readULEB()
240+
while needed_count:
241+
libname = module.readString()
242+
needed.append(libname)
243+
needed_count -= 1
244+
else:
245+
print(f'unknown subsection: {subsection_type}')
246+
# ignore unknown subsections
247+
module.skip(subsection_size)
248+
assert(module.tell() == end)
249+
else:
250+
utils.exit_with_error('error parsing shared library')
215251

216252
return Dylink(mem_size, mem_align, table_size, table_align, needed)
217253

0 commit comments

Comments
 (0)