Skip to content

Commit 95c65e9

Browse files
authored
Remove wasm offset converter (#24963)
The v8 bug that made this necessary was fixed in 2019: https://crbug.com/v8/9172 From running some tests I confirmed the node v12 and newer work fine without the offset converter. Older node versions such as v10 will show a warning about the legacy backtrace format and will not see symbol names in their backtraces (when using ASAN etc). Fixes: #24587
1 parent a033a96 commit 95c65e9

23 files changed

+54
-406
lines changed

ChangeLog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ See docs/process.md for more on how version tagging works.
2020

2121
4.0.14 (in development)
2222
-----------------------
23+
- The wasm offset converter was removed along with the `WASM_OFFSET_CONVERTER`
24+
setting. This feature only existed to work around an old v8 bug that was fixed
25+
back in 2019. (#24963)
2326

2427
4.0.13 - 08/14/25
2528
-----------------

eslint.config.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ export default [{
4343
'src/webGLClient.js',
4444
'src/webGLWorker.js',
4545
'src/*_shell_read.js',
46-
'src/wasm_offset_converter.js',
4746
'src/threadprofiler.js',
4847
'src/cpuprofiler.js',
4948
'src/memoryprofiler.js',

site/source/docs/tools_reference/settings_reference.rst

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3053,18 +3053,6 @@ future release.
30533053

30543054
Default value: -1
30553055

3056-
.. _use_offset_converter:
3057-
3058-
USE_OFFSET_CONVERTER
3059-
====================
3060-
3061-
Whether we should use the offset converter. This is needed for older
3062-
versions of v8 (<7.7) that does not give the hex module offset into wasm
3063-
binary in stack traces, as well as for avoiding using source map entries
3064-
across function boundaries.
3065-
3066-
Default value: false
3067-
30683056
.. _load_source_map:
30693057

30703058
LOAD_SOURCE_MAP

src/lib/libpthread.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -355,9 +355,6 @@ var LibraryPThread = {
355355
#if LOAD_SOURCE_MAP
356356
wasmSourceMap,
357357
#endif
358-
#if USE_OFFSET_CONVERTER
359-
wasmOffsetConverter,
360-
#endif
361358
#if MAIN_MODULE
362359
dynamicLibraries,
363360
// Share all modules that have been loaded so far. New workers

src/lib/libstack_trace.js

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -104,19 +104,14 @@ var LibraryStackTrace = {
104104
var match;
105105

106106
if (match = /\bwasm-function\[\d+\]:(0x[0-9a-f]+)/.exec(frame)) {
107-
// some engines give the binary offset directly, so we use that as return address
107+
// Wasm engines give the binary offset directly, so we use that as return address
108108
return +match[1];
109-
} else if (match = /\bwasm-function\[(\d+)\]:(\d+)/.exec(frame)) {
110-
// Older versions of v8 give function index and offset in the function,
111-
// so we try using the offset converter. If that doesn't work,
112-
// we pack index and offset into a "return address"
113-
#if !USE_OFFSET_CONVERTER
114-
abort('Legacy backtrace format detected but -sUSE_OFFSET_CONVERTER not present.')
115-
#else
116109
#if ASSERTIONS
117-
assert(wasmOffsetConverter, 'wasmOffsetConverter global not found');
118-
#endif
119-
return wasmOffsetConverter.convert(+match[1], +match[2]);
110+
} else if (match = /\bwasm-function\[(\d+)\]:(\d+)/.exec(frame)) {
111+
// Older versions of v8 (e.g node v10) give function index and offset in
112+
// the function. That format is not supported since it does not provide
113+
// the information we need to map the frame to a global program counter.
114+
warnOnce('legacy backtrace format detected, this version of v8 is no longer supported by the emscripten backtrace mechanism')
120115
#endif
121116
} else if (match = /:(\d+):\d+(?:\)|$)/.exec(frame)) {
122117
// If we are in js, we can use the js line number as the "return address".
@@ -205,12 +200,12 @@ var LibraryStackTrace = {
205200
$saveInUnwindCache__deps: ['$UNWIND_CACHE', '$convertFrameToPC'],
206201
$saveInUnwindCache__internal: true,
207202
$saveInUnwindCache: (callstack) => {
208-
callstack.forEach((frame) => {
209-
var pc = convertFrameToPC(frame);
203+
for (var line of callstack) {
204+
var pc = convertFrameToPC(line);
210205
if (pc) {
211-
UNWIND_CACHE[pc] = frame;
206+
UNWIND_CACHE[pc] = line;
212207
}
213-
});
208+
}
214209
},
215210

216211
// Unwinds the stack from a cached PC value. See emscripten_stack_snapshot for
@@ -242,32 +237,37 @@ var LibraryStackTrace = {
242237
},
243238

244239
// Look up the function name from our stack frame cache with our PC representation.
245-
emscripten_pc_get_function__deps: ['$UNWIND_CACHE', 'free', '$stringToNewUTF8'],
240+
emscripten_pc_get_function__deps: ['$UNWIND_CACHE', 'free', '$stringToNewUTF8', 'emscripten_stack_snapshot'],
246241
// Don't treat allocation of _emscripten_pc_get_function.ret as a leak
247242
emscripten_pc_get_function__noleakcheck: true,
248243
emscripten_pc_get_function: (pc) => {
249-
var name;
250-
if (pc & 0x80000000) {
251-
// If this is a JavaScript function, try looking it up in the unwind cache.
252-
var frame = UNWIND_CACHE[pc];
253-
if (!frame) return 0;
244+
var frame = UNWIND_CACHE[pc];
245+
if (!frame) return 0;
246+
dbg(getCallstack())
254247

255-
var match;
256-
if (match = /^\s+at (.*) \(.*\)$/.exec(frame)) {
257-
name = match[1];
258-
} else if (match = /^(.+?)@/.exec(frame)) {
259-
name = match[1];
260-
} else {
261-
return 0;
262-
}
248+
var name;
249+
var match;
250+
// First try to match foo.wasm.sym files explcitly. e.g.
251+
//
252+
// at test_return_address.wasm.main (wasm://wasm/test_return_address.wasm-0012cc2a:wasm-function[26]:0x9f3
253+
//
254+
// Then match JS symbols which don't include that module name:
255+
//
256+
// at invokeEntryPoint (.../test_return_address.js:1500:42)
257+
//
258+
// Finally match firefox format:
259+
//
260+
// Object._main@http://server.com:4324:12'
261+
if (match = /^\s+at .*\.wasm\.(.*) \(.*\)$/.exec(frame)) {
262+
name = match[1];
263+
} else if (match = /^\s+at (.*) \(.*\)$/.exec(frame)) {
264+
name = match[1];
265+
} else if (match = /^(.+?)@/.exec(frame)) {
266+
name = match[1];
263267
} else {
264-
#if !USE_OFFSET_CONVERTER
265-
abort('Cannot use emscripten_pc_get_function on native functions without -sUSE_OFFSET_CONVERTER');
266268
return 0;
267-
#else
268-
name = wasmOffsetConverter.getName(pc);
269-
#endif
270269
}
270+
271271
_free(_emscripten_pc_get_function.ret ?? 0);
272272
_emscripten_pc_get_function.ret = stringToNewUTF8(name);
273273
return _emscripten_pc_get_function.ret;

src/modules.mjs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -452,10 +452,6 @@ function exportRuntimeSymbols() {
452452
runtimeElements.push('HEAP_DATA_VIEW');
453453
}
454454

455-
if (USE_OFFSET_CONVERTER) {
456-
runtimeElements.push('WasmOffsetConverter');
457-
}
458-
459455
if (LOAD_SOURCE_MAP) {
460456
runtimeElements.push('WasmSourceMap');
461457
}

src/postamble_minimal.js

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,6 @@ WebAssembly.instantiate(Module['wasm'], imports).then(/** @suppress {missingProp
190190
wasmExports = applySignatureConversions(wasmExports);
191191
#endif
192192

193-
#if USE_OFFSET_CONVERTER
194-
#if PTHREADS
195-
if (!ENVIRONMENT_IS_PTHREAD)
196-
#endif
197-
wasmOffsetConverter = new WasmOffsetConverter(Module['wasm'], output.module);
198-
#endif
199-
200193
#if !DECLARE_ASM_MODULE_EXPORTS
201194
exportWasmSymbols(wasmExports);
202195
#else

src/preamble.js

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ function receiveSourceMapJSON(sourceMap) {
417417
}
418418
#endif
419419

420-
#if (PTHREADS || WASM_WORKERS) && (LOAD_SOURCE_MAP || USE_OFFSET_CONVERTER)
420+
#if (PTHREADS || WASM_WORKERS) && LOAD_SOURCE_MAP
421421
// When using postMessage to send an object, it is processed by the structured
422422
// clone algorithm. The prototype, and hence methods, on that object is then
423423
// lost. This function adds back the lost prototype. This does not work with
@@ -557,9 +557,6 @@ function instantiateSync(file, info) {
557557
module = new WebAssembly.Module(binary);
558558
#endif // NODE_CODE_CACHING
559559
var instance = new WebAssembly.Instance(module, info);
560-
#if USE_OFFSET_CONVERTER
561-
wasmOffsetConverter = new WasmOffsetConverter(binary, module);
562-
#endif
563560
#if LOAD_SOURCE_MAP
564561
receiveSourceMapJSON(getSourceMap());
565562
#endif
@@ -572,11 +569,6 @@ async function instantiateArrayBuffer(binaryFile, imports) {
572569
try {
573570
var binary = await getWasmBinary(binaryFile);
574571
var instance = await WebAssembly.instantiate(binary, imports);
575-
#if USE_OFFSET_CONVERTER
576-
// wasmOffsetConverter needs to be assigned before calling resolve.
577-
// See comments below in instantiateAsync.
578-
wasmOffsetConverter = new WasmOffsetConverter(binary, instance.module);
579-
#endif
580572
return instance;
581573
} catch (reason) {
582574
err(`failed to asynchronously prepare wasm: ${reason}`);
@@ -635,31 +627,7 @@ async function instantiateAsync(binary, binaryFile, imports) {
635627
) {
636628
try {
637629
var response = fetch(binaryFile, {{{ makeModuleReceiveExpr('fetchSettings', "{ credentials: 'same-origin' }") }}});
638-
#if USE_OFFSET_CONVERTER
639-
// We need the wasm binary for the offset converter. Clone the response
640-
// in order to get its arrayBuffer (cloning should be more efficient
641-
// than doing another entire request).
642-
// (We must clone the response now in order to use it later, as if we
643-
// try to clone it asynchronously lower down then we will get a
644-
// "response was already consumed" error.)
645-
var clonedResponse = (await response).clone();
646-
#endif
647630
var instantiationResult = await WebAssembly.instantiateStreaming(response, imports);
648-
#if USE_OFFSET_CONVERTER
649-
// When using the offset converter, we must interpose here. First,
650-
// the instantiation result must arrive (if it fails, the error
651-
// handling later down will handle it). Once it arrives, we can
652-
// initialize the offset converter. And only then is it valid to
653-
// call receiveInstantiationResult, as that function will use the
654-
// offset converter (in the case of pthreads, it will create the
655-
// pthreads and send them the offsets along with the wasm instance).
656-
var arrayBufferResult = await clonedResponse.arrayBuffer();
657-
try {
658-
wasmOffsetConverter = new WasmOffsetConverter(new Uint8Array(arrayBufferResult), instantiationResult.module);
659-
} catch (reason) {
660-
err(`failed to initialize offset-converter: ${reason}`);
661-
}
662-
#endif
663631
return instantiationResult;
664632
} catch (reason) {
665633
// We expect the most common failure cause to be a bad MIME type for the binary,

src/runtime_common.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,6 @@ var wasmSourceMap;
6060
#include "source_map_support.js"
6161
#endif
6262

63-
#if USE_OFFSET_CONVERTER
64-
var wasmOffsetConverter;
65-
#include "wasm_offset_converter.js"
66-
#endif
67-
6863
// Memory management
6964

7065
#if !WASM_ESM_INTEGRATION || IMPORTED_MEMORY

src/runtime_pthread.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ if (ENVIRONMENT_IS_PTHREAD) {
2626
// Thread-local guard variable for one-time init of the JS state
2727
var initializedJS = false;
2828

29-
#if LOAD_SOURCE_MAP || USE_OFFSET_CONVERTER
29+
#if LOAD_SOURCE_MAP
3030
// When using postMessage to send an object, it is processed by the structured
3131
// clone algorithm. The prototype, and hence methods, on that object is then
3232
// lost. This function adds back the lost prototype. This does not work with
@@ -112,9 +112,6 @@ if (ENVIRONMENT_IS_PTHREAD) {
112112
#if LOAD_SOURCE_MAP
113113
wasmSourceMap = resetPrototype(WasmSourceMap, msgData.wasmSourceMap);
114114
#endif
115-
#if USE_OFFSET_CONVERTER
116-
wasmOffsetConverter = resetPrototype(WasmOffsetConverter, msgData.wasmOffsetConverter);
117-
#endif
118115

119116
#if !WASM_ESM_INTEGRATION
120117
#if MINIMAL_RUNTIME

0 commit comments

Comments
 (0)