summaryrefslogtreecommitdiff
path: root/src/tools/wasm2c-wrapper.h
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2020-10-23 16:01:40 -0700
committerGitHub <noreply@github.com>2020-10-23 16:01:40 -0700
commit2dc156d1d3af7f3eb40bdce7c20aa84c98d50c15 (patch)
tree3a25edf7a1acc183ad57918ecd0c7a9ebe36199c /src/tools/wasm2c-wrapper.h
parent0daa41c4af29f7a2695e8356e610cf88dea10d7f (diff)
downloadbinaryen-2dc156d1d3af7f3eb40bdce7c20aa84c98d50c15.tar.gz
binaryen-2dc156d1d3af7f3eb40bdce7c20aa84c98d50c15.tar.bz2
binaryen-2dc156d1d3af7f3eb40bdce7c20aa84c98d50c15.zip
Fuzzer: Fix wasm2c name mangling (#3228)
This is necessary for cases where the input has an export name that needs mangling, like a name with - (common in the spec test suite).
Diffstat (limited to 'src/tools/wasm2c-wrapper.h')
-rw-r--r--src/tools/wasm2c-wrapper.h83
1 files changed, 56 insertions, 27 deletions
diff --git a/src/tools/wasm2c-wrapper.h b/src/tools/wasm2c-wrapper.h
index 6ea473d7a..8fa317a18 100644
--- a/src/tools/wasm2c-wrapper.h
+++ b/src/tools/wasm2c-wrapper.h
@@ -25,6 +25,58 @@
namespace wasm {
+// Mangle a name in (hopefully) exactly the same way wasm2c does.
+static std::string wasm2cMangle(Name name, Signature sig) {
+ const char escapePrefix = 'Z';
+ std::string mangled = "Z_";
+ const char* original = name.str;
+ unsigned char c;
+ while ((c = *original++)) {
+ if ((isalnum(c) && c != escapePrefix) || c == '_') {
+ // This character is ok to emit as it is.
+ mangled += c;
+ } else {
+ // This must be escaped, as prefix + hex character code.
+ mangled += escapePrefix;
+ std::stringstream ss;
+ ss << std::hex << std::uppercase << unsigned(c);
+ mangled += ss.str();
+ }
+ }
+
+ // Emit the result and params.
+ mangled += "Z_";
+
+ auto wasm2cSignature = [](Type type) {
+ TODO_SINGLE_COMPOUND(type);
+ switch (type.getBasic()) {
+ case Type::none:
+ return 'v';
+ case Type::i32:
+ return 'i';
+ case Type::i64:
+ return 'j';
+ case Type::f32:
+ return 'f';
+ case Type::f64:
+ return 'd';
+ default:
+ Fatal() << "unhandled wasm2c wrapper signature type: " << type;
+ }
+ };
+
+ mangled += wasm2cSignature(sig.results);
+ if (sig.params.isTuple()) {
+ for (const auto& param : sig.params) {
+ mangled += wasm2cSignature(param);
+ }
+ } else {
+ mangled += wasm2cSignature(sig.params);
+ }
+
+ return mangled;
+}
+
static std::string generateWasm2CWrapper(Module& wasm) {
// First, emit implementations of the wasm's imports so that the wasm2c code
// can call them. The names use wasm2c's name mangling.
@@ -142,35 +194,12 @@ int main(int argc, char** argv) {
}
}
- // Emit the callee's name with wasm2c name mangling.
- ret += std::string("(*Z_") + exp->name.str + "Z_";
+ // Call the export.
+ ret += "(*";
- auto wasm2cSignature = [](Type type) {
- TODO_SINGLE_COMPOUND(type);
- switch (type.getBasic()) {
- case Type::none:
- return 'v';
- case Type::i32:
- return 'i';
- case Type::i64:
- return 'j';
- case Type::f32:
- return 'f';
- case Type::f64:
- return 'd';
- default:
- Fatal() << "unhandled wasm2c wrapper signature type: " << type;
- }
- };
+ // Emit the callee's name with wasm2c name mangling.
+ ret += wasm2cMangle(exp->name, func->sig);
- ret += wasm2cSignature(result);
- if (func->sig.params.isTuple()) {
- for (const auto& param : func->sig.params) {
- ret += wasm2cSignature(param);
- }
- } else {
- ret += wasm2cSignature(func->sig.params);
- }
ret += ")(";
// Emit the parameters (all 0s, like the other wrappers).