diff options
author | Alon Zakai <alonzakai@gmail.com> | 2014-07-21 14:26:38 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2014-07-21 14:26:38 -0700 |
commit | 812f051215f469a8f26768fde343c2e464114cc1 (patch) | |
tree | 8161ee531c4265e814383557aeb8e5d94394cc1b | |
parent | d1e74bbabb835f0a9e988ab53f37c9f4d0a29d8c (diff) |
DEMANGLE_SUPPORT option to use libcxxabi's demangler in stackTrace()
-rwxr-xr-x | emcc | 7 | ||||
-rw-r--r-- | src/preamble.js | 28 | ||||
-rw-r--r-- | src/settings.js | 3 | ||||
-rw-r--r-- | tests/test_other.py | 26 | ||||
-rw-r--r-- | tools/system_libs.py | 5 |
5 files changed, 64 insertions, 5 deletions
@@ -1390,6 +1390,11 @@ try: next_arg_index += 1 shared.Settings.EXPORTED_FUNCTIONS += ['_stbi_load', '_stbi_load_from_memory', '_stbi_image_free'] + forced_stdlibs = [] + if shared.Settings.DEMANGLE_SUPPORT: + shared.Settings.EXPORTED_FUNCTIONS += ['___cxa_demangle'] + forced_stdlibs += ['libcxxabi'] + if type(shared.Settings.EXPORTED_FUNCTIONS) in (list, tuple): # always need malloc and free to be kept alive and exported, for internal use and other modules for required_export in ['_malloc', '_free']: @@ -1536,7 +1541,7 @@ try: if not LEAVE_INPUTS_RAW and \ not shared.Settings.BUILD_AS_SHARED_LIB and \ not shared.Settings.SIDE_MODULE: # shared libraries/side modules link no C libraries, need them in parent - extra_files_to_link = system_libs.calculate([f for _, f in sorted(temp_files)], in_temp, stdout, stderr) + extra_files_to_link = system_libs.calculate([f for _, f in sorted(temp_files)], in_temp, stdout, stderr, forced=forced_stdlibs) else: extra_files_to_link = [] diff --git a/src/preamble.js b/src/preamble.js index 1541075e..7ac9b549 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -778,6 +778,25 @@ function stringToUTF32(str, outPtr) { Module['stringToUTF32'] = stringToUTF32; function demangle(func) { + var hasLibcxxabi = !!Module['___cxa_demangle']; + if (hasLibcxxabi) { + try { + var buf = _malloc(func.length); + writeStringToMemory(func.substr(1), buf); + var status = _malloc(4); + var ret = Module['___cxa_demangle'](buf, 0, 0, status); + if (getValue(status, 'i32') === 0 && ret) { + return Pointer_stringify(ret); + } + // otherwise, libcxxabi failed, we can try ours which may return a partial result + } catch(e) { + // failure when using libcxxabi, we can try ours which may return a partial result + } finally { + if (buf) _free(buf); + if (status) _free(status); + if (ret) _free(ret); + } + } var i = 3; // params, etc. var basicTypes = { @@ -909,6 +928,7 @@ function demangle(func) { return ret + flushList(); } } + var final = func; try { // Special-case the entry point, since its name differs from other name mangling. if (func == 'Object._main' || func == '_main') { @@ -922,10 +942,14 @@ function demangle(func) { case 'n': return 'operator new()'; case 'd': return 'operator delete()'; } - return parse(); + final = parse(); } catch(e) { - return func; + final += '?'; + } + if (final.indexOf('?') >= 0 && !hasLibcxxabi) { + Runtime.warnOnce('A problem occurred in builtin C++ name demangling; build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling'); } + return final; } function demangleAll(text) { diff --git a/src/settings.js b/src/settings.js index 14077efd..b7947ac8 100644 --- a/src/settings.js +++ b/src/settings.js @@ -231,6 +231,9 @@ var LABEL_FUNCTION_FILTERS = []; // Filters for function label debug. // When the array is empty, the filter is disabled. var EXCEPTION_DEBUG = 0; // Print out exceptions in emscriptened code. Does not work in asm.js mode +var DEMANGLE_SUPPORT = 0; // If 1, build in libcxxabi's full c++ demangling code, to allow stackTrace() + // to emit fully proper demangled c++ names + var LIBRARY_DEBUG = 0; // Print out when we enter a library call (library*.js). You can also unset // Runtime.debug at runtime for logging to cease, and can set it when you // want it back. A simple way to set it in C++ is diff --git a/tests/test_other.py b/tests/test_other.py index b4e6a620..398975fc 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -2191,6 +2191,32 @@ void wakaw::Cm::RasterBase<wakaw::watwat::Polocator?>(unsigned int*, unsigned in assert 'one(int)' in output assert 'two(char)' in output + # full demangle support + + Popen([PYTHON, EMCC, 'src.cpp', '-s', 'LINKABLE=1', '-s', 'DEMANGLE_SUPPORT=1']).communicate() + output = run_js('a.out.js') + self.assertContained('''operator new(unsigned int) +main() +f2() +abcdabcdabcd(int) +abcdabcdabcd(int) +test(char, short, int, float, double, void*, int*, char*) +test::moarr(char, short, long, float, double, void*, int*, char*) +Waka::f::a23412341234::point() +void Foo<int>() +void Foo<int, double>(int) +void Foo::Bar<5>() +__cxxabiv1::__si_class_type_info::search_below_dst(__cxxabiv1::__dynamic_cast_info*, void const*, int, bool) const +parseword(char const*&, int, int&) +multi(wchar_t, signed char, unsigned char, unsigned short, unsigned int, unsigned long, long long, unsigned long long, ...) +a(int [32], char (*) [5]) +FWakaGLXFleeflsMarfoo::FWakaGLXFleeflsMarfoo(unsigned int, unsigned int, unsigned int, void const*, bool, unsigned int, unsigned int) +void wakaw::Cm::RasterBase<wakaw::watwat::Polocator>::merbine1<wakaw::Cm::RasterBase<wakaw::watwat::Polocator>::OR>(unsigned int const*, unsigned int) +''', output) + # test for multiple functions in one stack trace + assert 'one(int)' in output + assert 'two(char)' in output + def test_module_exports_with_closure(self): # This test checks that module.export is retained when JavaScript is minified by compiling with --closure 1 # This is important as if module.export is not present the Module object will not be visible to node.js diff --git a/tools/system_libs.py b/tools/system_libs.py index 9b63af09..700f219e 100644 --- a/tools/system_libs.py +++ b/tools/system_libs.py @@ -13,7 +13,7 @@ def call_process(cmd): if proc.returncode != 0: raise CalledProcessError(proc.returncode, cmd) -def calculate(temp_files, in_temp, stdout_, stderr_): +def calculate(temp_files, in_temp, stdout_, stderr_, forced=[]): global stdout, stderr stdout = stdout_ stderr = stderr_ @@ -455,7 +455,8 @@ def calculate(temp_files, in_temp, stdout_, stderr_): # You can provide 1 to include everything, or a comma-separated list with the ones you want force = os.environ.get('EMCC_FORCE_STDLIBS') force_all = force == '1' - force = set((force or '').split(',')) + force = set((force or '').split(',') + forced) + if force: logging.debug('forcing stdlibs: ' + str(force)) # Scan symbols symbolses = map(lambda temp_file: shared.Building.llvm_nm(temp_file), temp_files) |