diff options
Diffstat (limited to 'src/tools')
| -rw-r--r-- | src/tools/execution-results.h | 33 | ||||
| -rw-r--r-- | src/tools/fuzzing.h | 29 |
2 files changed, 55 insertions, 7 deletions
diff --git a/src/tools/execution-results.h b/src/tools/execution-results.h index ca4b819d9..935aff4cc 100644 --- a/src/tools/execution-results.h +++ b/src/tools/execution-results.h @@ -24,20 +24,37 @@ namespace wasm { +typedef std::vector<Literal> Loggings; + +// Logs every single import call parameter. +struct LoggingExternalInterface : public ShellExternalInterface { + Loggings& loggings; + + LoggingExternalInterface(Loggings& loggings) : loggings(loggings) {} + + Literal callImport(Function* import, LiteralList& arguments) override { + std::cout << "[LoggingExternalInterface logging"; + loggings.push_back(Literal()); // buffer with a None between calls + for (auto argument : arguments) { + std::cout << ' ' << argument; + loggings.push_back(argument); + } + std::cout << "]\n"; + return Literal(); + } +}; + // gets execution results from a wasm module. this is useful for fuzzing // // we can only get results when there are no imports. we then call each method // that has a result, with some values struct ExecutionResults { std::map<Name, Literal> results; + Loggings loggings; // get results of execution void get(Module& wasm) { - if (ImportInfo(wasm).getNumImports() > 0) { - std::cout << "[fuzz-exec] imports, so quitting\n"; - return; - } - ShellExternalInterface interface; + LoggingExternalInterface interface(loggings); try { ModuleInstance instance(wasm, &interface); // execute all exported methods (that are therefore preserved through opts) @@ -84,6 +101,10 @@ struct ExecutionResults { abort(); } } + if (loggings != other.loggings) { + std::cout << "logging not identical!\n"; + abort(); + } return true; } @@ -92,7 +113,7 @@ struct ExecutionResults { } Literal run(Function* func, Module& wasm) { - ShellExternalInterface interface; + LoggingExternalInterface interface(loggings); try { ModuleInstance instance(wasm, &interface); return run(func, wasm, instance); diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index 3b1a418b5..7954229c7 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -128,6 +128,7 @@ public: setupMemory(); setupTable(); setupGlobals(); + addImportLoggingSupport(); // keep adding functions until we run out of input while (!finishedInput) { auto* func = addFunction(); @@ -184,10 +185,13 @@ private: // Whether to emit atomic waits (which in single-threaded mode, may hang...) static const bool ATOMIC_WAITS = false; - // after we finish the input, we start going through it again, but xoring + // After we finish the input, we start going through it again, but xoring // so it's not identical int xorFactor = 0; + // The chance to emit a logging operation for a none expression. We + // randomize this in each function. + unsigned LOGGING_PERCENT = 0; void readData(std::vector<char> input) { bytes.swap(input); @@ -300,6 +304,19 @@ private: wasm.addExport(export_); } + void addImportLoggingSupport() { + for (auto type : { i32, i64, f32, f64 }) { + auto* func = new Function; + Name name = std::string("log-") + printType(type); + func->name = name; + func->module = "fuzzing-support"; + func->base = name; + func->params.push_back(type); + func->result = none; + wasm.addFunction(func); + } + } + Expression* makeHangLimitCheck() { return builder.makeSequence( builder.makeIf( @@ -364,6 +381,7 @@ private: std::map<Type, std::vector<Index>> typeLocals; // type => list of locals with that type Function* addFunction() { + LOGGING_PERCENT = upToSquared(100); Index num = wasm.functions.size(); func = new Function; func->name = std::string("func_") + std::to_string(num); @@ -711,6 +729,8 @@ private: Expression* _makenone() { auto choice = upTo(100); + if (choice < LOGGING_PERCENT) return makeLogging(); + choice = upTo(100); if (choice < 50) return makeSetLocal(none); if (choice < 60) return makeBlock(none); if (choice < 70) return makeIf(none); @@ -1496,6 +1516,13 @@ private: } } + // special makers + + Expression* makeLogging() { + auto type = pick(i32, i64, f32, f64); + return builder.makeCall(std::string("log-") + printType(type), { make(type) }, none); + } + // special getters Type getType() { |
