summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/tools/wasmdump.c71
-rw-r--r--src/wasm-binary-reader-objdump.c195
-rw-r--r--src/wasm-binary-reader-objdump.h12
-rw-r--r--src/wasm-binary-reader.c6
-rw-r--r--src/wasm-binary-reader.h2
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, &section_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 */