-
Notifications
You must be signed in to change notification settings - Fork 254
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for Rust v0 symbol mangling scheme (#491)
- Loading branch information
Showing
15 changed files
with
226 additions
and
54 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
gcc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
EMCC = emcc | ||
CFLAGS = -Os -Igcc/include -DHAVE_STDLIB_H -DHAVE_STRING_H | ||
LDFLAGS_COMMON = \ | ||
-s EXPORTED_RUNTIME_METHODS=stringToUTF8OnStack,UTF8ToString \ | ||
-s EXPORTED_FUNCTIONS=_demangle,_free \ | ||
-s MODULARIZE=1 \ | ||
-s WASM=1 \ | ||
-s FILESYSTEM=0 \ | ||
-s MINIMAL_RUNTIME=1 | ||
|
||
# We have to disable EXPORT_ES6 as otherwise since esbuild cannot transpile that | ||
# into umd or anything else. | ||
# .ts files throughout the project can do this just fine because they are | ||
# transpiled to compatible js. | ||
ifeq ($(TEST),1) | ||
LDFLAGS = $(LDFLAGS_COMMON) -s EXPORT_ES6=1 | ||
else | ||
# SINGLE_FILE=1 embeds the wasm as base64. | ||
LDFLAGS = $(LDFLAGS_COMMON) -s ASSERTIONS=0 -s SINGLE_FILE=1 -s ENVIRONMENT=web | ||
endif | ||
|
||
SRC_FILES = \ | ||
gcc/libiberty/safe-ctype.c \ | ||
gcc/libiberty/rust-demangle.c \ | ||
gcc/libiberty/cp-demangle.c \ | ||
demangle.c | ||
POST_JS = demangle.post.js | ||
EXTERN_POST_JS = demangle.extern.post.js | ||
OUTPUT = demangle.wasm.js | ||
|
||
all: $(OUTPUT) | ||
|
||
$(OUTPUT): $(SRC_FILES) $(POST_JS) | ||
$(EMCC) $(CFLAGS) $(SRC_FILES) $(LDFLAGS) --post-js $(POST_JS) --extern-post-js $(EXTERN_POST_JS) --no-entry -o $@ | ||
|
||
clean: | ||
rm -f $(OUTPUT) | ||
|
||
.PHONY: all clean |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# demangle | ||
|
||
A wrapper function on top of demangling functions from the `GNU libiberty`, | ||
using emscripten. | ||
|
||
# Build dependencies | ||
|
||
## emscripten 4.0.0 | ||
|
||
Follow the official `emsdk` installation instructions: | ||
|
||
https://emscripten.org/docs/getting_started/downloads.html#installation-instructions-using-the-emsdk-recommended | ||
|
||
And make sure you have `emcc` in your PATH. | ||
|
||
# Source dependencies | ||
|
||
## GCC | ||
|
||
Make sure to fetch `gcc` sources. | ||
|
||
* `git clone https://github.com/gcc-mirror/gcc` | ||
* `git reset --hard 40754a3b9bef83bf4da0675fcb378e8cd1675602` | ||
|
||
# Build instructions | ||
|
||
`make` to produce a single CommonJS module that contains also contain the base64 encoded wasm file. | ||
`make TEST=1` to produce both a ES6 module AND the wasm file. | ||
|
||
Using `make TEST=1` produce a file that can be used by `node` for testing purposes. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#include "gcc/include/demangle.h" | ||
|
||
#include <string.h> | ||
|
||
static char *non_microsoft_demangle(const char *mangled) { | ||
int is_itanium_symbol = strncmp(mangled, "_Z", 2) == 0; | ||
if (is_itanium_symbol) { | ||
// Note: __cxa_demangle default is DMGL_PARAMS | DMGL_TYPES | ||
return cplus_demangle_v3(mangled, DMGL_PARAMS | DMGL_TYPES); | ||
} | ||
|
||
int is_rust_symbol = strncmp(mangled, "_R", 2) == 0; | ||
if (is_rust_symbol) { | ||
// Note: rust_demangle uses only DMGL_VERBOSE and DMGL_NO_RECURSE_LIMIT, | ||
// so no need to pass any options in our case. | ||
return rust_demangle(mangled, DMGL_NO_OPTS); | ||
} | ||
|
||
return NULL; | ||
} | ||
|
||
// Logic is inspired by llvm::demangle. | ||
// It is the caller's responsibility to free the string which is returned. | ||
char *demangle(const char *mangled) { | ||
char *demangled = non_microsoft_demangle(mangled); | ||
if (demangled) { | ||
return demangled; | ||
} | ||
|
||
if (mangled[0] == '_') { | ||
demangled = non_microsoft_demangle(&mangled[1]); | ||
if (demangled) { | ||
return demangled; | ||
} | ||
} | ||
|
||
return NULL; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/** | ||
* DO NOT USE THIS FILE DIRECTLY. | ||
* | ||
* This file is only used as --extern-post-js of emcc. | ||
*/ | ||
module.exports = Module | ||
module.exports.default = Module |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/** | ||
* DO NOT USE THIS FILE DIRECTLY. | ||
* | ||
* This file is only used as --post-js of emcc. | ||
* | ||
* This file provides a higher level demangle function ready to use | ||
* in JavaScript. | ||
*/ | ||
Module['wasm_demangle'] = function(mangled) { | ||
/* | ||
* We are manually calling the lower-level generated functions | ||
* instead of using `cwrap` because we need to `free` the pointer | ||
* returned by `_demangle`. | ||
*/ | ||
const param_ptr = stringToUTF8OnStack(mangled); | ||
const result_ptr = _demangle(param_ptr); | ||
const result = UTF8ToString(result_ptr); | ||
if (result_ptr !== null && result_ptr !== undefined) { | ||
_free(result_ptr); | ||
} | ||
return result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import {loadDemangling} from './demangle' | ||
|
||
test('demangle', async () => { | ||
const demangle = await loadDemangling() | ||
|
||
expect(demangle('a')).toBe('a') | ||
expect(demangle('someUnobfuscatedFunction')).toBe('someUnobfuscatedFunction') | ||
|
||
// C++ mangling | ||
expect(demangle('__ZNK7Support6ColorFeqERKS0_')).toBe( | ||
'Support::ColorF::operator==(Support::ColorF const&) const', | ||
) | ||
// Running a second time to test the cache | ||
expect(demangle('__ZNK7Support6ColorFeqERKS0_')).toBe( | ||
'Support::ColorF::operator==(Support::ColorF const&) const', | ||
) | ||
|
||
// Rust v0 mangling | ||
expect(demangle('_RNvCskwGfYPst2Cb_3foo16example_function')).toBe('foo::example_function') | ||
|
||
// Rust legacy mangling | ||
expect(demangle('_ZN3std2fs8Metadata7created17h8df207f105c5d474E')).toBe( | ||
'std::fs::Metadata::created::h8df207f105c5d474', | ||
) | ||
|
||
// False positive | ||
expect(demangle('_ZoomIn')).toBe('_ZoomIn') | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import createWasmDemangleModule from './demangle.wasm' | ||
|
||
const wasmDemangleModulePromise = createWasmDemangleModule().then(module => module) | ||
|
||
const cache = new Map<string, string>() | ||
|
||
export async function loadDemangling(): Promise<(name: string) => string> { | ||
// This function converts a mangled C++ name such as "__ZNK7Support6ColorFeqERKS0_" | ||
// into a human-readable symbol (in this case "Support::ColorF::==(Support::ColorF&)") | ||
const wasmDemangleModule = await wasmDemangleModulePromise | ||
return cached(wasmDemangleModule.wasm_demangle) | ||
} | ||
|
||
function cached(demangle: (name: string) => string): (name: string) => string { | ||
return (name: string): string => { | ||
let result = cache.get(name) | ||
if (result !== undefined) { | ||
name = result | ||
} else { | ||
result = demangle(name) | ||
result = result === '' ? name : result | ||
cache.set(name, result) | ||
name = result | ||
} | ||
return name | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
interface WasmDemangleModule { | ||
wasm_demangle(mangled: string): string | ||
} | ||
|
||
export default function ModuleFactory(options?: unknown): Promise<WasmDemangleModule> |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export {loadDemangling} from './demangle' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters