forked from emscripten-core/emscripten
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlibrary_stack_trace.js
80 lines (75 loc) · 2.31 KB
/
library_stack_trace.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/**
* @license
* Copyright 2019 The Emscripten Authors
* SPDX-License-Identifier: MIT
*/
var LibraryStackTrace = {
$demangle: function(func) {
#if DEMANGLE_SUPPORT
// If demangle has failed before, stop demangling any further function names
// This avoids an infinite recursion with malloc()->abort()->stackTrace()->demangle()->malloc()->...
demangle.recursionGuard = (demangle.recursionGuard|0)+1;
if (demangle.recursionGuard > 1) return func;
var __cxa_demangle_func = Module['___cxa_demangle'] || Module['__cxa_demangle'];
assert(__cxa_demangle_func);
var stackTop = stackSave();
try {
var s = func;
if (s.startsWith('__Z'))
s = s.substr(1);
var len = lengthBytesUTF8(s)+1;
var buf = stackAlloc(len);
stringToUTF8(s, buf, len);
var status = stackAlloc(4);
var ret = __cxa_demangle_func(buf, 0, 0, status);
if ({{{ makeGetValue('status', '0', 'i32') }}} === 0 && ret) {
return UTF8ToString(ret);
}
// otherwise, libcxxabi failed
} catch(e) {
} finally {
_free(ret);
stackRestore(stackTop);
if (demangle.recursionGuard < 2) --demangle.recursionGuard;
}
// failure when using libcxxabi, don't demangle
return func;
#else // DEMANGLE_SUPPORT
#if ASSERTIONS
warnOnce('warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling');
#endif // ASSERTIONS
return func;
#endif // DEMANGLE_SUPPORT
},
$demangleAll: function(text) {
var regex =
/\b_Z[\w\d_]+/g;
return text.replace(regex,
function(x) {
var y = demangle(x);
return x === y ? x : (y + ' [' + x + ']');
});
},
$jsStackTrace: function() {
var error = new Error();
if (!error.stack) {
// IE10+ special cases: It does have callstack info, but it is only populated if an Error object is thrown,
// so try that as a special-case.
try {
throw new Error();
} catch(e) {
error = e;
}
if (!error.stack) {
return '(no stack trace available)';
}
}
return error.stack.toString();
},
$stackTrace: function() {
var js = jsStackTrace();
if (Module['extraStackTrace']) js += '\n' + Module['extraStackTrace']();
return demangleAll(js);
}
}
mergeInto(LibraryManager.library, LibraryStackTrace);