File tree Expand file tree Collapse file tree 15 files changed +226
-54
lines changed
Expand file tree Collapse file tree 15 files changed +226
-54
lines changed Load Diff This file was deleted.
Load Diff This file was deleted.
Original file line number Diff line number Diff line change 1+ gcc
Original file line number Diff line number Diff line change 1+ EMCC = emcc
2+ CFLAGS = -Os -Igcc/include -DHAVE_STDLIB_H -DHAVE_STRING_H
3+ LDFLAGS_COMMON = \
4+ -s EXPORTED_RUNTIME_METHODS=stringToUTF8OnStack,UTF8ToString \
5+ -s EXPORTED_FUNCTIONS=_demangle,_free \
6+ -s MODULARIZE=1 \
7+ -s WASM=1 \
8+ -s FILESYSTEM=0 \
9+ -s MINIMAL_RUNTIME=1
10+
11+ # We have to disable EXPORT_ES6 as otherwise since esbuild cannot transpile that
12+ # into umd or anything else.
13+ # .ts files throughout the project can do this just fine because they are
14+ # transpiled to compatible js.
15+ ifeq ($(TEST ) ,1)
16+ LDFLAGS = $(LDFLAGS_COMMON ) -s EXPORT_ES6=1
17+ else
18+ # SINGLE_FILE=1 embeds the wasm as base64.
19+ LDFLAGS = $(LDFLAGS_COMMON ) -s ASSERTIONS=0 -s SINGLE_FILE=1 -s ENVIRONMENT=web
20+ endif
21+
22+ SRC_FILES = \
23+ gcc/libiberty/safe-ctype.c \
24+ gcc/libiberty/rust-demangle.c \
25+ gcc/libiberty/cp-demangle.c \
26+ demangle.c
27+ POST_JS = demangle.post.js
28+ EXTERN_POST_JS = demangle.extern.post.js
29+ OUTPUT = demangle.wasm.js
30+
31+ all : $(OUTPUT )
32+
33+ $(OUTPUT ) : $(SRC_FILES ) $(POST_JS )
34+ $(EMCC ) $(CFLAGS ) $(SRC_FILES ) $(LDFLAGS ) --post-js $(POST_JS ) --extern-post-js $(EXTERN_POST_JS ) --no-entry -o $@
35+
36+ clean :
37+ rm -f $(OUTPUT )
38+
39+ .PHONY : all clean
Original file line number Diff line number Diff line change 1+ # demangle
2+
3+ A wrapper function on top of demangling functions from the ` GNU libiberty ` ,
4+ using emscripten.
5+
6+ # Build dependencies
7+
8+ ## emscripten 4.0.0
9+
10+ Follow the official ` emsdk ` installation instructions:
11+
12+ https://emscripten.org/docs/getting_started/downloads.html#installation-instructions-using-the-emsdk-recommended
13+
14+ And make sure you have ` emcc ` in your PATH.
15+
16+ # Source dependencies
17+
18+ ## GCC
19+
20+ Make sure to fetch ` gcc ` sources.
21+
22+ * ` git clone https://github.com/gcc-mirror/gcc `
23+ * ` git reset --hard 40754a3b9bef83bf4da0675fcb378e8cd1675602 `
24+
25+ # Build instructions
26+
27+ ` make ` to produce a single CommonJS module that contains also contain the base64 encoded wasm file.
28+ ` make TEST=1 ` to produce both a ES6 module AND the wasm file.
29+
30+ Using ` make TEST=1 ` produce a file that can be used by ` node ` for testing purposes.
Original file line number Diff line number Diff line change 1+ #include "gcc/include/demangle.h"
2+
3+ #include <string.h>
4+
5+ static char * non_microsoft_demangle (const char * mangled ) {
6+ int is_itanium_symbol = strncmp (mangled , "_Z" , 2 ) == 0 ;
7+ if (is_itanium_symbol ) {
8+ // Note: __cxa_demangle default is DMGL_PARAMS | DMGL_TYPES
9+ return cplus_demangle_v3 (mangled , DMGL_PARAMS | DMGL_TYPES );
10+ }
11+
12+ int is_rust_symbol = strncmp (mangled , "_R" , 2 ) == 0 ;
13+ if (is_rust_symbol ) {
14+ // Note: rust_demangle uses only DMGL_VERBOSE and DMGL_NO_RECURSE_LIMIT,
15+ // so no need to pass any options in our case.
16+ return rust_demangle (mangled , DMGL_NO_OPTS );
17+ }
18+
19+ return NULL ;
20+ }
21+
22+ // Logic is inspired by llvm::demangle.
23+ // It is the caller's responsibility to free the string which is returned.
24+ char * demangle (const char * mangled ) {
25+ char * demangled = non_microsoft_demangle (mangled );
26+ if (demangled ) {
27+ return demangled ;
28+ }
29+
30+ if (mangled [0 ] == '_' ) {
31+ demangled = non_microsoft_demangle (& mangled [1 ]);
32+ if (demangled ) {
33+ return demangled ;
34+ }
35+ }
36+
37+ return NULL ;
38+ }
Original file line number Diff line number Diff line change 1+ /**
2+ * DO NOT USE THIS FILE DIRECTLY.
3+ *
4+ * This file is only used as --extern-post-js of emcc.
5+ */
6+ module . exports = Module
7+ module . exports . default = Module
Original file line number Diff line number Diff line change 1+ /**
2+ * DO NOT USE THIS FILE DIRECTLY.
3+ *
4+ * This file is only used as --post-js of emcc.
5+ *
6+ * This file provides a higher level demangle function ready to use
7+ * in JavaScript.
8+ */
9+ Module [ 'wasm_demangle' ] = function ( mangled ) {
10+ /*
11+ * We are manually calling the lower-level generated functions
12+ * instead of using `cwrap` because we need to `free` the pointer
13+ * returned by `_demangle`.
14+ */
15+ const param_ptr = stringToUTF8OnStack ( mangled ) ;
16+ const result_ptr = _demangle ( param_ptr ) ;
17+ const result = UTF8ToString ( result_ptr ) ;
18+ if ( result_ptr !== null && result_ptr !== undefined ) {
19+ _free ( result_ptr ) ;
20+ }
21+ return result ;
22+ }
Original file line number Diff line number Diff line change 1+ import { loadDemangling } from './demangle'
2+
3+ test ( 'demangle' , async ( ) => {
4+ const demangle = await loadDemangling ( )
5+
6+ expect ( demangle ( 'a' ) ) . toBe ( 'a' )
7+ expect ( demangle ( 'someUnobfuscatedFunction' ) ) . toBe ( 'someUnobfuscatedFunction' )
8+
9+ // C++ mangling
10+ expect ( demangle ( '__ZNK7Support6ColorFeqERKS0_' ) ) . toBe (
11+ 'Support::ColorF::operator==(Support::ColorF const&) const' ,
12+ )
13+ // Running a second time to test the cache
14+ expect ( demangle ( '__ZNK7Support6ColorFeqERKS0_' ) ) . toBe (
15+ 'Support::ColorF::operator==(Support::ColorF const&) const' ,
16+ )
17+
18+ // Rust v0 mangling
19+ expect ( demangle ( '_RNvCskwGfYPst2Cb_3foo16example_function' ) ) . toBe ( 'foo::example_function' )
20+
21+ // Rust legacy mangling
22+ expect ( demangle ( '_ZN3std2fs8Metadata7created17h8df207f105c5d474E' ) ) . toBe (
23+ 'std::fs::Metadata::created::h8df207f105c5d474' ,
24+ )
25+
26+ // False positive
27+ expect ( demangle ( '_ZoomIn' ) ) . toBe ( '_ZoomIn' )
28+ } )
Original file line number Diff line number Diff line change 1+ import createWasmDemangleModule from './demangle.wasm'
2+
3+ const wasmDemangleModulePromise = createWasmDemangleModule ( ) . then ( module => module )
4+
5+ const cache = new Map < string , string > ( )
6+
7+ export async function loadDemangling ( ) : Promise < ( name : string ) => string > {
8+ // This function converts a mangled C++ name such as "__ZNK7Support6ColorFeqERKS0_"
9+ // into a human-readable symbol (in this case "Support::ColorF::==(Support::ColorF&)")
10+ const wasmDemangleModule = await wasmDemangleModulePromise
11+ return cached ( wasmDemangleModule . wasm_demangle )
12+ }
13+
14+ function cached ( demangle : ( name : string ) => string ) : ( name : string ) => string {
15+ return ( name : string ) : string => {
16+ let result = cache . get ( name )
17+ if ( result !== undefined ) {
18+ name = result
19+ } else {
20+ result = demangle ( name )
21+ result = result === '' ? name : result
22+ cache . set ( name , result )
23+ name = result
24+ }
25+ return name
26+ }
27+ }
You can’t perform that action at this time.
0 commit comments