diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/tools/wasmdump.c | 71 | ||||
-rw-r--r-- | src/wasm-binary-reader-objdump.c | 195 | ||||
-rw-r--r-- | src/wasm-binary-reader-objdump.h | 12 | ||||
-rw-r--r-- | src/wasm-binary-reader.c | 6 | ||||
-rw-r--r-- | src/wasm-binary-reader.h | 2 |
5 files changed, 245 insertions, 41 deletions
diff --git a/src/tools/wasmdump.c b/src/tools/wasmdump.c index 4a6fa0ca..5d7c46dc 100644 --- a/src/tools/wasmdump.c +++ b/src/tools/wasmdump.c @@ -28,9 +28,13 @@ #define PROGRAM_NAME "wasmdump" +#define NOPE WASM_OPTION_NO_ARGUMENT +#define YEP WASM_OPTION_HAS_ARGUMENT + enum { FLAG_HEADERS, FLAG_RAW, + FLAG_SECTION, FLAG_DISASSEMBLE, FLAG_VERBOSE, FLAG_DEBUG, @@ -45,26 +49,21 @@ static const char s_description[] = " $ wasmdump test.wasm\n"; static WasmOption s_options[] = { - {FLAG_HEADERS, 'h', "headers", NULL, WASM_OPTION_NO_ARGUMENT, - "print headers"}, - {FLAG_RAW, 'r', "raw", NULL, WASM_OPTION_NO_ARGUMENT, - "print raw section contents"}, - {FLAG_DISASSEMBLE, 'd', "disassemble", NULL, WASM_OPTION_NO_ARGUMENT, - "disassemble function bodies"}, - {FLAG_DEBUG, '\0', "debug", NULL, WASM_OPTION_NO_ARGUMENT, - "disassemble function bodies"}, - {FLAG_VERBOSE, 'v', "verbose", NULL, WASM_OPTION_NO_ARGUMENT, - "Verbose output"}, - {FLAG_HELP, 'h', "help", NULL, WASM_OPTION_NO_ARGUMENT, - "print this help message"}, + {FLAG_HEADERS, 'h', "headers", NULL, NOPE, "print headers"}, + {FLAG_SECTION, 'j', "section", NULL, YEP, "select just one section"}, + {FLAG_RAW, 'r', "raw", NULL, NOPE, "print raw section contents"}, + {FLAG_DISASSEMBLE, 'd', "disassemble", NULL, NOPE, "disassemble function bodies"}, + {FLAG_DEBUG, '\0', "debug", NULL, NOPE, "disassemble function bodies"}, + {FLAG_VERBOSE, 'v', "verbose", NULL, NOPE, "Verbose output"}, + {FLAG_HELP, 'h', "help", NULL, NOPE, "print this help message"}, }; + WASM_STATIC_ASSERT(NUM_FLAGS == WASM_ARRAY_SIZE(s_options)); -static const char* s_infile; static WasmObjdumpOptions s_objdump_options; static void on_argument(struct WasmOptionParser* parser, const char* argument) { - s_infile = argument; + s_objdump_options.infile = argument; } static void on_option(struct WasmOptionParser* parser, @@ -90,6 +89,10 @@ static void on_option(struct WasmOptionParser* parser, s_objdump_options.verbose = WASM_TRUE; break; + case FLAG_SECTION: + s_objdump_options.section_name = argument; + break; + case FLAG_HELP: wasm_print_help(parser, PROGRAM_NAME); exit(0); @@ -113,7 +116,7 @@ static void parse_options(int argc, char** argv) { parser.on_error = on_option_error; wasm_parse_options(&parser, argc, argv); - if (!s_infile) { + if (!s_objdump_options.infile) { wasm_print_help(&parser, PROGRAM_NAME); WASM_FATAL("No filename given.\n"); } @@ -127,11 +130,45 @@ int main(int argc, char** argv) { void* data; size_t size; - WasmResult result = wasm_read_file(allocator, s_infile, &data, &size); + WasmResult result = wasm_read_file(allocator, s_objdump_options.infile, &data, &size); if (WASM_FAILED(result)) return result; - result = wasm_read_binary_objdump(allocator, data, size, &s_objdump_options); + // Perform serveral passed over the binary in order to print out different + // types of information. + + s_objdump_options.print_header = 1; + + // Pass 1: Print the section headers + if (s_objdump_options.headers) { + s_objdump_options.mode = WASM_DUMP_HEADERS; + result = wasm_read_binary_objdump(allocator, data, size, &s_objdump_options); + if (WASM_FAILED(result)) + goto done; + s_objdump_options.print_header = 0; + } + // Pass 2: Print extra information based on section type + if (s_objdump_options.verbose || s_objdump_options.section_name) { + s_objdump_options.mode = WASM_DUMP_DETAILS; + result = wasm_read_binary_objdump(allocator, data, size, &s_objdump_options); + if (WASM_FAILED(result)) + goto done; + s_objdump_options.print_header = 0; + } + if (s_objdump_options.disassemble) { + s_objdump_options.mode = WASM_DUMP_DISASSEMBLE; + result = wasm_read_binary_objdump(allocator, data, size, &s_objdump_options); + if (WASM_FAILED(result)) + goto done; + s_objdump_options.print_header = 0; + } + // Pass 3: Dump to raw contents of the sections + if (s_objdump_options.raw) { + s_objdump_options.mode = WASM_DUMP_RAW_DATA; + result = wasm_read_binary_objdump(allocator, data, size, &s_objdump_options); + } + +done: wasm_free(allocator, data); return result; } diff --git a/src/wasm-binary-reader-objdump.c b/src/wasm-binary-reader-objdump.c index eb26106b..ad2f621a 100644 --- a/src/wasm-binary-reader-objdump.c +++ b/src/wasm-binary-reader-objdump.c @@ -17,6 +17,7 @@ #include "wasm-binary-reader-objdump.h" #include <assert.h> +#include <inttypes.h> #include <string.h> #include <stdio.h> @@ -31,11 +32,21 @@ typedef struct Context { size_t current_opcode_offset; size_t last_opcode_end; int indent_level; + WasmBool print_details; + WasmBool header_printed; + int section_found; } Context; + +static WasmBool should_print_details(Context* ctx) { + if (ctx->options->mode != WASM_DUMP_DETAILS) + return WASM_FALSE; + return ctx->print_details; +} + static void WASM_PRINTF_FORMAT(2, 3) print_details(Context* ctx, const char* fmt, ...) { - if (!ctx->options->verbose) + if (!should_print_details(ctx)) return; va_list args; va_start(args, fmt); @@ -53,15 +64,28 @@ static WasmResult begin_section(Context* ctx, const char* name, size_t offset, size_t size) { - if (ctx->options->headers) { - printf("%-12s start=%#010" PRIzx " end=%#010" PRIzx " (size=%#010" PRIzx - ")\n", - name, offset, offset + size, size); - } - if (ctx->options->raw) { - printf("\n"); - wasm_write_memory_dump(ctx->out_stream, ctx->data + offset, size, offset, - WASM_PRINT_CHARS, NULL); + switch (ctx->options->mode) { + case WASM_DUMP_HEADERS: + printf("%9s start=%#010" PRIzx " end=%#010" PRIzx " (size=%#010" PRIzx + ") ", + name, offset, offset + size, size); + break; + case WASM_DUMP_DETAILS: + if (!ctx->options->section_name || !strcasecmp(ctx->options->section_name, name)) { + printf("%s:\n", name); + ctx->print_details = WASM_TRUE; + ctx->section_found = WASM_TRUE; + } else { + ctx->print_details = WASM_FALSE; + } + break; + case WASM_DUMP_RAW_DATA: + printf("\nContents of section %s:\n", name); + wasm_write_memory_dump(ctx->out_stream, ctx->data + offset, size, offset, + WASM_PRINT_CHARS, NULL); + break; + case WASM_DUMP_DISASSEMBLE: + break; } return WASM_OK; } @@ -81,7 +105,53 @@ SEGSTART(names, "NAMES") static WasmResult on_count(uint32_t count, void* user_data) { Context* ctx = user_data; - print_details(ctx, " - count: %d\n", count); + if (ctx->options->mode == WASM_DUMP_HEADERS) { + printf("count: %d\n", count); + } + return WASM_OK; +} + +static WasmResult begin_module(uint32_t version, void* user_data) { + Context* ctx = user_data; + if (ctx->options->print_header) { + const char *basename = strrchr(ctx->options->infile, '/'); + if (basename) + basename++; + else + basename = ctx->options->infile; + printf("%s:\tfile format wasm %#08x\n", basename, version); + ctx->header_printed = WASM_TRUE; + } + + switch (ctx->options->mode) { + case WASM_DUMP_HEADERS: + printf("\n"); + printf("Sections:\n"); + break; + case WASM_DUMP_DETAILS: + printf("\n"); + printf("Section Details:\n"); + break; + case WASM_DUMP_DISASSEMBLE: + printf("\n"); + printf("Code Disassembly:\n"); + break; + case WASM_DUMP_RAW_DATA: + break; + } + + return WASM_OK; +} + +static WasmResult end_module(void *user_data) { + Context* ctx = user_data; + if (ctx->options->mode == WASM_DUMP_DETAILS && ctx->options->section_name) { + if (!ctx->section_found) { + printf("Section not found: %s\n", ctx->options->section_name); + return WASM_ERROR; + } + } + return WASM_OK; } @@ -244,7 +314,7 @@ static WasmResult on_signature(uint32_t index, void* user_data) { Context* ctx = user_data; - if (!ctx->options->verbose) + if (!should_print_details(ctx)) return WASM_OK; printf(" - [%d] (", index); uint32_t i; @@ -272,16 +342,30 @@ static WasmResult on_function_signature(uint32_t index, static WasmResult begin_function_body(uint32_t index, void* user_data) { Context* ctx = user_data; - if (ctx->options->verbose || ctx->options->disassemble) + + if (should_print_details(ctx)) + printf(" - func %d\n", index); + if (ctx->options->mode == WASM_DUMP_DISASSEMBLE) printf("func %d\n", index); + ctx->last_opcode_end = 0; return WASM_OK; } +static WasmResult on_import(uint32_t index, + WasmStringSlice module_name, + WasmStringSlice field_name, + void* user_data) { + print_details(user_data, " - " PRIstringslice " " PRIstringslice "\n", + WASM_PRINTF_STRING_SLICE_ARG(module_name), + WASM_PRINTF_STRING_SLICE_ARG(field_name)); + return WASM_OK; +} + static WasmResult on_import_func(uint32_t index, uint32_t sig_index, void* user_data) { - print_details(user_data, "- func sig=%d\n", sig_index); + print_details(user_data, " - func sig=%d\n", sig_index); return WASM_OK; } @@ -289,16 +373,18 @@ static WasmResult on_import_table(uint32_t index, WasmType elem_type, const WasmLimits* elem_limits, void* user_data) { - /* TODO(sbc): print more useful information about the table here */ - print_details(user_data, "- table elem_type=%s\n", - wasm_get_type_name(elem_type)); + print_details(user_data, + " - table elem_type=%s init=%" PRId64 " max=%" PRId64 "\n", + wasm_get_type_name(elem_type), + elem_limits->initial, + elem_limits->max); return WASM_OK; } static WasmResult on_import_memory(uint32_t index, const WasmLimits* page_limits, void* user_data) { - print_details(user_data, "- memory\n"); + print_details(user_data, " - memory\n"); return WASM_OK; } @@ -321,7 +407,12 @@ static WasmResult on_table(uint32_t index, WasmType elem_type, const WasmLimits* elem_limits, void* user_data) { - print_details(user_data, "- table %d\n", index); + print_details(user_data, + " - [%d] type=%#x init=%" PRId64 " max=%" PRId64 " \n", + index, + elem_type, + elem_limits->initial, + elem_limits->has_max ? elem_limits->max : 0); return WASM_OK; } @@ -336,12 +427,64 @@ static WasmResult on_export(uint32_t index, return WASM_OK; } +static WasmResult on_elem_segment_function_index(uint32_t index, + uint32_t func_index, + void* user_data) { + print_details(user_data, " - [%d] -> %d\n", index, func_index); + return WASM_OK; +} + +static WasmResult begin_elem_segment(uint32_t index, + uint32_t table_index, + void* user_data) { + print_details(user_data, " - segment [%d] table=%d\n", index, table_index); + return WASM_OK; +} + +static WasmResult on_init_expr_f32_const_expr(uint32_t index, + uint32_t value, + void* user_data) { + print_details(user_data, " - init f32=%d\n", value); + return WASM_OK; +} + +static WasmResult on_init_expr_f64_const_expr(uint32_t index, + uint64_t value, + void* user_data) { + print_details(user_data, " - init f64=%" PRId64 "\n", value); + return WASM_OK; +} + +static WasmResult on_init_expr_get_global_expr(uint32_t index, + uint32_t global_index, + void* user_data) { + print_details(user_data, " - init global=%d\n", global_index); + return WASM_OK; +} + +static WasmResult on_init_expr_i32_const_expr(uint32_t index, + uint32_t value, + void* user_data) { + print_details(user_data, " - init i32=%d\n", value); + return WASM_OK; +} + +static WasmResult on_init_expr_i64_const_expr(uint32_t index, + uint64_t value, + void* user_data) { + print_details(user_data, " - init i64=%" PRId64 "\n", value); + return WASM_OK; +} + static void on_error(WasmBinaryReaderContext* ctx, const char* message) { wasm_default_binary_error_callback(ctx->offset, message, ctx->user_data); } static WasmBinaryReader s_binary_reader = { .user_data = NULL, + + .begin_module = begin_module, + .end_module = end_module, .on_error = on_error, // Signature sections @@ -352,6 +495,7 @@ static WasmBinaryReader s_binary_reader = { // Import section .begin_import_section = begin_import_section, .on_import_count = on_count, + .on_import = on_import, .on_import_func = on_import_func, .on_import_table = on_import_table, .on_import_memory = on_import_memory, @@ -391,7 +535,9 @@ static WasmBinaryReader s_binary_reader = { // Elems section .begin_elem_section = begin_elem_section, + .begin_elem_segment = begin_elem_segment, .on_elem_segment_count = on_count, + .on_elem_segment_function_index = on_elem_segment_function_index, // Data section .begin_data_section = begin_data_section, @@ -400,6 +546,12 @@ static WasmBinaryReader s_binary_reader = { // Names section .begin_names_section = begin_names_section, .on_function_names_count = on_count, + + .on_init_expr_i32_const_expr = on_init_expr_i32_const_expr, + .on_init_expr_i64_const_expr = on_init_expr_i64_const_expr, + .on_init_expr_f32_const_expr = on_init_expr_f32_const_expr, + .on_init_expr_f64_const_expr = on_init_expr_f64_const_expr, + .on_init_expr_get_global_expr = on_init_expr_get_global_expr, }; WasmResult wasm_read_binary_objdump(struct WasmAllocator* allocator, @@ -411,12 +563,15 @@ WasmResult wasm_read_binary_objdump(struct WasmAllocator* allocator, reader = s_binary_reader; Context context; WASM_ZERO_MEMORY(context); + context.header_printed = WASM_FALSE; + context.print_details = WASM_FALSE; + context.section_found = WASM_FALSE; context.data = data; context.size = size; context.options = options; context.out_stream = wasm_init_stdout_stream(); - if (options->disassemble) { + if (options->mode == WASM_DUMP_DISASSEMBLE) { reader.on_opcode = on_opcode; reader.on_opcode_bare = on_opcode_bare; reader.on_opcode_uint32 = on_opcode_uint32; diff --git a/src/wasm-binary-reader-objdump.h b/src/wasm-binary-reader-objdump.h index c0318f14..06a19118 100644 --- a/src/wasm-binary-reader-objdump.h +++ b/src/wasm-binary-reader-objdump.h @@ -24,15 +24,27 @@ struct WasmAllocator; struct WasmModule; struct WasmReadBinaryOptions; +typedef enum WasmObjdumpMode { + WASM_DUMP_HEADERS, + WASM_DUMP_DETAILS, + WASM_DUMP_DISASSEMBLE, + WASM_DUMP_RAW_DATA, +} WasmObjdumpMode; + typedef struct WasmObjdumpOptions { WasmBool headers; WasmBool verbose; WasmBool raw; WasmBool disassemble; WasmBool debug; + WasmObjdumpMode mode; + const char* infile; + const char* section_name; + WasmBool print_header; } WasmObjdumpOptions; WASM_EXTERN_C_BEGIN + WasmResult wasm_read_binary_objdump(struct WasmAllocator* allocator, const uint8_t* data, size_t size, diff --git a/src/wasm-binary-reader.c b/src/wasm-binary-reader.c index 21b2169d..950b6752 100644 --- a/src/wasm-binary-reader.c +++ b/src/wasm-binary-reader.c @@ -589,7 +589,7 @@ static void logging_on_error(WasmBinaryReaderContext* ctx, FORWARD0(name); \ } -LOGGING0(begin_module) +LOGGING_UINT32(begin_module) LOGGING0(end_module) LOGGING_BEGIN(signature_section) LOGGING_UINT32(on_signature_count) @@ -1706,8 +1706,6 @@ WasmResult wasm_read_binary(WasmAllocator* allocator, wasm_reserve_uint32s(allocator, &ctx->target_depths, INITIAL_BR_TABLE_TARGET_CAPACITY); - CALLBACK0(begin_module); - uint32_t magic; in_u32(ctx, &magic, "magic"); RAISE_ERROR_UNLESS(magic == WASM_BINARY_MAGIC, "bad magic value"); @@ -1717,6 +1715,8 @@ WasmResult wasm_read_binary(WasmAllocator* allocator, "bad wasm file version: %#x (expected %#x)", version, WASM_BINARY_VERSION); + CALLBACK(begin_module, version); + /* type */ uint32_t section_size; if (skip_until_section(ctx, WASM_BINARY_SECTION_TYPE, §ion_size)) { diff --git a/src/wasm-binary-reader.h b/src/wasm-binary-reader.h index 59bfffcf..424203e9 100644 --- a/src/wasm-binary-reader.h +++ b/src/wasm-binary-reader.h @@ -46,7 +46,7 @@ typedef struct WasmBinaryReader { void (*on_error)(WasmBinaryReaderContext* ctx, const char* message); /* module */ - WasmResult (*begin_module)(void* user_data); + WasmResult (*begin_module)(uint32_t version, void* user_data); WasmResult (*end_module)(void* user_data); /* signatures section */ |