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
+ }
Original file line number Diff line number Diff line change
1
+ interface WasmDemangleModule {
2
+ wasm_demangle ( mangled : string ) : string
3
+ }
4
+
5
+ export default function ModuleFactory ( options ?: unknown ) : Promise < WasmDemangleModule >
Original file line number Diff line number Diff line change
1
+ export { loadDemangling } from './demangle'
Original file line number Diff line number Diff line change 1
1
import { lastOf , KeyedSet } from './utils'
2
2
import { ValueFormatter , RawValueFormatter } from './value-formatters'
3
3
import { FileFormat } from './file-format-spec'
4
- const demangleCppModule = import ( './demangle-cpp' )
5
4
6
5
export interface FrameInfo {
7
6
key : string | number
@@ -404,16 +403,20 @@ export class Profile {
404
403
405
404
// Demangle symbols for readability
406
405
async demangle ( ) {
407
- let demangleCpp : ( ( name : string ) => string ) | null = null
406
+ let demangle : ( ( name : string ) => string ) | null = null
408
407
409
408
for ( let frame of this . frames ) {
410
- // This function converts a mangled C++ name such as "__ZNK7Support6ColorFeqERKS0_"
411
- // into a human-readable symbol (in this case "Support::ColorF::==(Support::ColorF&)")
412
- if ( frame . name . startsWith ( '__Z' ) ) {
413
- if ( ! demangleCpp ) {
414
- demangleCpp = ( await demangleCppModule ) . demangleCpp
409
+ // This function converts a mangled C++ and Rust name into a human-readable symbol.
410
+ if (
411
+ frame . name . startsWith ( '__Z' ) ||
412
+ frame . name . startsWith ( '_R' ) ||
413
+ frame . name . startsWith ( '_Z' )
414
+ ) {
415
+ if ( ! demangle ) {
416
+ const demangleModule = await import ( './demangle' )
417
+ demangle = await demangleModule . loadDemangling ( )
415
418
}
416
- frame . name = demangleCpp ( frame . name )
419
+ frame . name = demangle ( frame . name )
417
420
}
418
421
}
419
422
}
Original file line number Diff line number Diff line change @@ -28,7 +28,7 @@ const importModule = import('../import')
28
28
// We put them all in one place so we can directly control the relative priority
29
29
// of these.
30
30
importModule . then ( ( ) => { } )
31
- import ( '../lib/demangle-cpp ' ) . then ( ( ) => { } )
31
+ import ( '../lib/demangle' ) . then ( ( ) => { } )
32
32
import ( 'source-map' ) . then ( ( ) => { } )
33
33
34
34
async function importProfilesFromText (
You can’t perform that action at this time.
0 commit comments