wasm: add flag to dump modules

Flags --dump_wasm_module and --dump_wasm_module_path=/path/to/folder allow us to run a bunch of tests and capture all of the wasm module files including the ones that come from the .js and .cc tests which are built on the fly, as well as the asm2wasm tests.

The files are all uniquely named `HASH.{ok,failed}.wasm`.

This will be especilly useful for fuzz testing, but could also be used for other tests including non-V8 tests.

For now I manually hacked tools/testrunner/local/execution.py so that tools/run-tests.py can output the modules. We may want to ad a flag to run-tests.py proper if this turns out to be useful.

R=bradnelson@chromium.org, titzer@chromium.org, kcc@chromium.org

Review URL: https://codereview.chromium.org/1816583003

Cr-Commit-Position: refs/heads/master@{#34968}
This commit is contained in:
jfb 2016-03-21 14:41:22 -07:00 committed by Commit bot
parent cca5c3f630
commit ed76b66aab
6 changed files with 58 additions and 29 deletions

View File

@ -429,9 +429,10 @@ bool OS::Remove(const char* path) {
return (remove(path) == 0);
}
char OS::DirectorySeparator() { return '/'; }
bool OS::isDirectorySeparator(const char ch) {
return ch == '/';
return ch == DirectorySeparator();
}

View File

@ -574,6 +574,7 @@ bool OS::Remove(const char* path) {
return (DeleteFileA(path) != 0);
}
char OS::DirectorySeparator() { return '\\'; }
bool OS::isDirectorySeparator(const char ch) {
return ch == '/' || ch == '\\';

View File

@ -142,6 +142,7 @@ class OS {
static FILE* FOpen(const char* path, const char* mode);
static bool Remove(const char* path);
static char DirectorySeparator();
static bool isDirectorySeparator(const char ch);
// Opens a temporary file, the file is auto removed on close.

View File

@ -476,9 +476,8 @@ DEFINE_BOOL(wasm_loop_assignment_analysis, false,
DEFINE_BOOL(enable_simd_asmjs, false, "enable SIMD.js in asm.js stdlib")
DEFINE_BOOL(dump_asmjs_wasm, false, "dump Asm.js to WASM module bytes")
DEFINE_STRING(asmjs_wasm_dumpfile, "asmjs.wasm",
"file to dump asm wasm conversion result to")
DEFINE_BOOL(dump_wasm_module, false, "dump WASM module bytes")
DEFINE_STRING(dump_wasm_module_path, NULL, "directory to dump wasm modules to")
DEFINE_INT(typed_array_max_size_in_heap, 64,
"threshold for in-heap typed array")

View File

@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/wasm/module-decoder.h"
#include "src/base/functional.h"
#include "src/base/platform/platform.h"
#include "src/macro-assembler.h"
#include "src/objects.h"
#include "src/v8.h"
#include "src/wasm/decoder.h"
#include "src/wasm/module-decoder.h"
namespace v8 {
namespace internal {
@ -40,6 +43,31 @@ class ModuleDecoder : public Decoder {
pc_ = limit_; // On error, terminate section decoding loop.
}
static void DumpModule(WasmModule* module, ModuleResult result) {
std::string path;
if (FLAG_dump_wasm_module_path) {
path = FLAG_dump_wasm_module_path;
if (path.size() &&
!base::OS::isDirectorySeparator(path[path.size() - 1])) {
path += base::OS::DirectorySeparator();
}
}
// File are named `HASH.{ok,failed}.wasm`.
size_t hash = base::hash_range(module->module_start, module->module_end);
char buf[32] = {'\0'};
#if V8_OS_WIN && _MSC_VER < 1900
#define snprintf sprintf_s
#endif
snprintf(buf, sizeof(buf) - 1, "%016zx.%s.wasm", hash,
result.ok() ? "ok" : "failed");
std::string name(buf);
if (FILE* wasm_file = base::OS::FOpen((path + name).c_str(), "wb")) {
fwrite(module->module_start, module->module_end - module->module_start, 1,
wasm_file);
fclose(wasm_file);
}
}
// Decodes an entire module.
ModuleResult DecodeModule(WasmModule* module, bool verify_functions = true) {
pc_ = start_;
@ -61,17 +89,19 @@ class ModuleDecoder : public Decoder {
"expected magic word %02x %02x %02x %02x, "
"found %02x %02x %02x %02x",
BYTES(kWasmMagic), BYTES(magic_word));
return toResult(module);
goto done;
}
pos = pc_;
uint32_t magic_version = consume_u32("wasm version");
if (magic_version != kWasmVersion) {
error(pos, pos,
"expected version %02x %02x %02x %02x, "
"found %02x %02x %02x %02x",
BYTES(kWasmVersion), BYTES(magic_version));
return toResult(module);
{
uint32_t magic_version = consume_u32("wasm version");
if (magic_version != kWasmVersion) {
error(pos, pos,
"expected version %02x %02x %02x %02x, "
"found %02x %02x %02x %02x",
BYTES(kWasmVersion), BYTES(magic_version));
goto done;
}
}
// Decode the module sections.
@ -366,7 +396,12 @@ class ModuleDecoder : public Decoder {
}
}
return toResult(module);
done:
ModuleResult result = toResult(module);
if (FLAG_dump_wasm_module) {
DumpModule(module, result);
}
return result;
}
uint32_t SafeReserve(uint32_t count) {
@ -399,13 +434,13 @@ class ModuleDecoder : public Decoder {
FunctionResult DecodeSingleFunction(ModuleEnv* module_env,
WasmFunction* function) {
pc_ = start_;
function->sig = consume_sig(); // read signature
function->name_offset = 0; // ---- name
function->name_length = 0; // ---- name length
function->code_start_offset = off(pc_); // ---- code start
function->code_end_offset = off(limit_); // ---- code end
function->exported = false; // ---- exported
function->external = false; // ---- external
function->sig = consume_sig(); // read signature
function->name_offset = 0; // ---- name
function->name_length = 0; // ---- name length
function->code_start_offset = off(pc_); // ---- code start
function->code_end_offset = off(limit_); // ---- code end
function->exported = false; // ---- exported
function->external = false; // ---- external
if (ok()) VerifyFunctionBody(0, module_env, function);

View File

@ -152,14 +152,6 @@ v8::internal::wasm::WasmModuleIndex* TranslateAsmModule(
info->literal(), foreign, &typer)
.Run();
if (i::FLAG_dump_asmjs_wasm) {
FILE* wasm_file = fopen(i::FLAG_asmjs_wasm_dumpfile, "wb");
if (wasm_file) {
fwrite(module->Begin(), module->End() - module->Begin(), 1, wasm_file);
fclose(wasm_file);
}
}
return module;
}