summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/wasm-binary-reader-ast.c13
-rw-r--r--src/wasm-binary-reader-interpreter.c18
-rw-r--r--src/wasm-binary-reader-objdump.c434
-rw-r--r--src/wasm-binary-reader-objdump.h43
-rw-r--r--src/wasm-binary-reader.c135
-rw-r--r--src/wasm-binary-reader.h45
-rw-r--r--src/wasm-common.c7
-rw-r--r--src/wasm-common.h7
-rw-r--r--src/wasmdump.c137
9 files changed, 752 insertions, 87 deletions
diff --git a/src/wasm-binary-reader-ast.c b/src/wasm-binary-reader-ast.c
index 796f42eb..33b19d7e 100644
--- a/src/wasm-binary-reader-ast.c
+++ b/src/wasm-binary-reader-ast.c
@@ -128,7 +128,8 @@ static WasmResult append_expr(Context* ctx, WasmExpr* expr) {
static void handle_error(Context* ctx, uint32_t offset, const char* message) {
if (ctx->error_handler->on_error) {
- ctx->error_handler->on_error(offset, message, ctx->error_handler->user_data);
+ ctx->error_handler->on_error(offset, message,
+ ctx->error_handler->user_data);
}
}
@@ -535,11 +536,11 @@ static WasmResult on_br_if_expr(uint32_t depth, void* user_data) {
return append_expr(ctx, expr);
}
-static WasmResult on_br_table_expr(uint32_t num_targets,
+static WasmResult on_br_table_expr(WasmBinaryReaderContext* context,
+ uint32_t num_targets,
uint32_t* target_depths,
- uint32_t default_target_depth,
- void* user_data) {
- Context* ctx = user_data;
+ uint32_t default_target_depth) {
+ Context* ctx = context->user_data;
WasmExpr* expr = wasm_new_br_table_expr(ctx->allocator);
wasm_reserve_vars(ctx->allocator, &expr->br_table.targets, num_targets);
expr->br_table.targets.size = num_targets;
@@ -574,7 +575,7 @@ static WasmResult on_call_indirect_expr(uint32_t sig_index, void* user_data) {
static WasmResult on_compare_expr(WasmOpcode opcode, void* user_data) {
Context* ctx = user_data;
- WasmExpr *expr = wasm_new_compare_expr(ctx->allocator);
+ WasmExpr* expr = wasm_new_compare_expr(ctx->allocator);
expr->compare.opcode = opcode;
return append_expr(ctx, expr);
}
diff --git a/src/wasm-binary-reader-interpreter.c b/src/wasm-binary-reader-interpreter.c
index bc18030c..3155d98f 100644
--- a/src/wasm-binary-reader-interpreter.c
+++ b/src/wasm-binary-reader-interpreter.c
@@ -320,8 +320,7 @@ static WasmResult emit_func_offset(Context* ctx,
return WASM_OK;
}
-static void on_error(WasmBinaryReaderContext* ctx,
- const char* message) {
+static void on_error(WasmBinaryReaderContext* ctx, const char* message) {
handle_error(ctx->offset, message, ctx->user_data);
}
@@ -510,8 +509,7 @@ static WasmResult on_init_expr_get_global_expr(uint32_t index,
void* user_data) {
Context* ctx = user_data;
assert(global_index < ctx->module->globals.size);
- WasmInterpreterGlobal* ref_global =
- &ctx->module->globals.data[global_index];
+ WasmInterpreterGlobal* ref_global = &ctx->module->globals.data[global_index];
ctx->init_expr_value = ref_global->typed_value;
return WASM_OK;
}
@@ -719,8 +717,8 @@ static WasmResult check_n_types(Context* ctx,
for (i = 0; i < expected->size; ++i) {
WasmType actual =
ctx->type_stack.data[ctx->type_stack.size - expected->size + i];
- CHECK_RESULT(check_type(ctx, expected->data[expected->size - i - 1],
- actual, desc));
+ CHECK_RESULT(
+ check_type(ctx, expected->data[expected->size - i - 1], actual, desc));
}
return WASM_OK;
}
@@ -1049,11 +1047,11 @@ static WasmResult on_br_if_expr(uint32_t depth, void* user_data) {
return WASM_OK;
}
-static WasmResult on_br_table_expr(uint32_t num_targets,
+static WasmResult on_br_table_expr(WasmBinaryReaderContext* context,
+ uint32_t num_targets,
uint32_t* target_depths,
- uint32_t default_target_depth,
- void* user_data) {
- Context* ctx = user_data;
+ uint32_t default_target_depth) {
+ Context* ctx = context->user_data;
CHECK_RESULT(pop_and_check_1_type(ctx, WASM_TYPE_I32, "br_table"));
CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_BR_TABLE));
CHECK_RESULT(emit_i32(ctx, num_targets));
diff --git a/src/wasm-binary-reader-objdump.c b/src/wasm-binary-reader-objdump.c
new file mode 100644
index 00000000..c940b227
--- /dev/null
+++ b/src/wasm-binary-reader-objdump.c
@@ -0,0 +1,434 @@
+/*
+ * Copyright 2016 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wasm-binary-reader-objdump.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "wasm-binary-reader.h"
+
+typedef struct Context {
+ const WasmObjdumpOptions* options;
+ WasmStream* out_stream;
+ const uint8_t* data;
+ size_t size;
+ WasmOpcode current_opcode;
+ size_t current_opcode_offset;
+ size_t last_opcode_end;
+ int indent_level;
+} Context;
+
+static void WASM_PRINTF_FORMAT(2, 3)
+ print_details(Context* ctx, const char* fmt, ...) {
+ if (!ctx->options->verbose)
+ return;
+ va_list args;
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+}
+
+#define SEGSTART(segname, name) \
+ static WasmResult begin_##segname##_section(WasmBinaryReaderContext* ctx, \
+ uint32_t size) { \
+ return begin_section(ctx->user_data, name, ctx->offset, size); \
+ }
+
+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);
+ }
+ return WASM_OK;
+}
+
+SEGSTART(signature, "TYPE")
+SEGSTART(import, "IMPORT")
+SEGSTART(function_signatures, "FUNCTION")
+SEGSTART(table, "TABLE")
+SEGSTART(memory, "MEMORY")
+SEGSTART(global, "GLOBAL")
+SEGSTART(export, "EXPORT")
+SEGSTART(start, "START")
+SEGSTART(function_bodies, "CODE")
+SEGSTART(elem, "ELEM")
+SEGSTART(data, "DATA")
+SEGSTART(names, "NAMES")
+
+static WasmResult on_count(uint32_t count, void* user_data) {
+ Context* ctx = user_data;
+ print_details(ctx, " - count: %d\n", count);
+ return WASM_OK;
+}
+
+static WasmResult on_opcode(WasmBinaryReaderContext* ctx, WasmOpcode opcode) {
+ Context* context = ctx->user_data;
+
+ if (context->options->debug) {
+ const char* opcode_name = wasm_get_opcode_name(opcode);
+ printf("on_opcode: %#" PRIzx ": %s\n", ctx->offset, opcode_name);
+ }
+
+ if (context->last_opcode_end) {
+ if (ctx->offset != context->last_opcode_end + 1) {
+ uint8_t missing_opcode = ctx->data[context->last_opcode_end];
+ const char* opcode_name = wasm_get_opcode_name(missing_opcode);
+ fprintf(stderr, "warning: %#" PRIzx " missing opcode callback at %#" PRIzx
+ " (%#02x=%s)\n",
+ ctx->offset, context->last_opcode_end + 1,
+ ctx->data[context->last_opcode_end], opcode_name);
+ return WASM_ERROR;
+ }
+ }
+
+ context->current_opcode_offset = ctx->offset;
+ context->current_opcode = opcode;
+ return WASM_OK;
+}
+
+#define IMMEDIATE_OCTET_COUNT 9
+
+static void log_opcode(Context* ctx,
+ const uint8_t* data,
+ size_t data_size,
+ const char* fmt,
+ ...) {
+ size_t offset = ctx->current_opcode_offset;
+
+ // Print binary data
+ printf(" %06zx: %02x", offset - 1, ctx->current_opcode);
+ size_t i;
+ for (i = 0; i < data_size && i < IMMEDIATE_OCTET_COUNT; i++, offset++) {
+ printf(" %02x", data[offset]);
+ }
+ for (i = data_size + 1; i < IMMEDIATE_OCTET_COUNT; i++) {
+ printf(" ");
+ }
+ printf(" | ");
+
+ // Print disassemble
+ int j;
+ int indent_level = ctx->indent_level;
+ if (ctx->current_opcode == WASM_OPCODE_ELSE)
+ indent_level--;
+ for (j = 0; j < indent_level; j++) {
+ printf(" ");
+ }
+
+ const char* opcode_name = wasm_get_opcode_name(ctx->current_opcode);
+ printf("%s", opcode_name);
+ if (fmt) {
+ printf(" ");
+ va_list args;
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ }
+
+ printf("\n");
+
+ ctx->last_opcode_end = ctx->current_opcode_offset + data_size;
+}
+
+static WasmResult on_opcode_bare(WasmBinaryReaderContext* ctx) {
+ Context* context = ctx->user_data;
+ log_opcode(context, ctx->data, 0, NULL);
+ return WASM_OK;
+}
+
+static WasmResult on_opcode_uint32(WasmBinaryReaderContext* ctx,
+ uint32_t value) {
+ Context* context = ctx->user_data;
+ size_t immediate_len = ctx->offset - context->current_opcode_offset;
+ log_opcode(context, ctx->data, immediate_len, "%#x", value);
+ return WASM_OK;
+}
+
+static WasmResult on_opcode_uint32_uint32(WasmBinaryReaderContext* ctx,
+ uint32_t value,
+ uint32_t value2) {
+ Context* context = ctx->user_data;
+ size_t immediate_len = ctx->offset - context->current_opcode_offset;
+ log_opcode(context, ctx->data, immediate_len, "%lu %lu", value, value2);
+ return WASM_OK;
+}
+
+static WasmResult on_opcode_uint64(WasmBinaryReaderContext* ctx,
+ uint64_t value) {
+ Context* context = ctx->user_data;
+ size_t immediate_len = ctx->offset - context->current_opcode_offset;
+ log_opcode(context, ctx->data, immediate_len, "%d", value);
+ return WASM_OK;
+}
+
+WasmResult on_br_table_expr(WasmBinaryReaderContext* ctx,
+ uint32_t num_targets,
+ uint32_t* target_depths,
+ uint32_t default_target_depth) {
+ Context* context = ctx->user_data;
+ size_t immediate_len = ctx->offset - context->current_opcode_offset;
+ /* TODO(sbc): Print targets */
+ log_opcode(context, ctx->data, immediate_len, NULL);
+ return WASM_OK;
+}
+
+static WasmResult on_end_expr(void* user_data) {
+ Context* context = user_data;
+ context->indent_level--;
+ assert(context->indent_level >= 0);
+ log_opcode(context, NULL, 0, NULL);
+ return WASM_OK;
+}
+
+static const char* wasm_type_name(WasmType type) {
+ switch (type) {
+ case WASM_TYPE_I32:
+ return "i32";
+
+ case WASM_TYPE_I64:
+ return "i64";
+
+ case WASM_TYPE_F32:
+ return "f32";
+
+ case WASM_TYPE_F64:
+ return "f64";
+
+ default:
+ assert(0);
+ return "INVALID TYPE";
+ }
+}
+
+static WasmResult on_opcode_block_sig(WasmBinaryReaderContext* ctx,
+ uint32_t num_types,
+ WasmType* sig_types) {
+ Context* context = ctx->user_data;
+ if (num_types)
+ log_opcode(context, ctx->data, 1, "%s", wasm_type_name(*sig_types));
+ else
+ log_opcode(context, ctx->data, 1, NULL);
+ context->indent_level++;
+ return WASM_OK;
+}
+
+static WasmResult on_signature(uint32_t index,
+ uint32_t param_count,
+ WasmType* param_types,
+ uint32_t result_count,
+ WasmType* result_types,
+ void* user_data) {
+ Context* ctx = user_data;
+
+ if (!ctx->options->verbose)
+ return WASM_OK;
+ printf(" - [%d] (", index);
+ uint32_t i;
+ for (i = 0; i < param_count; i++) {
+ if (i != 0) {
+ printf(", ");
+ }
+ printf("%s", wasm_type_name(param_types[i]));
+ }
+ printf(") -> ");
+ if (result_count)
+ printf("%s", wasm_type_name(result_types[0]));
+ else
+ printf("nil");
+ printf("\n");
+ return WASM_OK;
+}
+
+static WasmResult on_function_signature(uint32_t index,
+ uint32_t sig_index,
+ void* user_data) {
+ print_details(user_data, " - [%d] sig=%d\n", index, sig_index);
+ return WASM_OK;
+}
+
+static WasmResult begin_function_body(uint32_t index, void* user_data) {
+ Context* ctx = user_data;
+ if (ctx->options->verbose || ctx->options->disassemble)
+ printf("func %d\n", index);
+ ctx->last_opcode_end = 0;
+ 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);
+ return WASM_OK;
+}
+
+static WasmResult on_import_table(uint32_t index,
+ uint32_t 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=%d\n", elem_type);
+ return WASM_OK;
+}
+
+static WasmResult on_import_memory(uint32_t index,
+ const WasmLimits* page_limits,
+ void* user_data) {
+ print_details(user_data, "- memory\n");
+ return WASM_OK;
+}
+
+static WasmResult on_import_global(uint32_t index,
+ WasmType type,
+ WasmBool mutable_,
+ void* user_data) {
+ print_details(user_data, "- global\n");
+ return WASM_OK;
+}
+
+static WasmResult on_memory(uint32_t index,
+ const WasmLimits* page_limits,
+ void* user_data) {
+ print_details(user_data, "- memory %d\n", index);
+ return WASM_OK;
+}
+
+static WasmResult on_table(uint32_t index,
+ uint32_t elem_type,
+ const WasmLimits* elem_limits,
+ void* user_data) {
+ print_details(user_data, "- table %d\n", index);
+ return WASM_OK;
+}
+
+static WasmResult on_export(uint32_t index,
+ WasmExternalKind kind,
+ uint32_t item_index,
+ WasmStringSlice name,
+ void* user_data) {
+ print_details(user_data, " - [%d] %s ", item_index, wasm_get_kind_name(kind));
+ print_details(user_data, PRIstringslice, WASM_PRINTF_STRING_SLICE_ARG(name));
+ print_details(user_data, "\n");
+ 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,
+ .on_error = on_error,
+
+ // Signature sections
+ .begin_signature_section = begin_signature_section,
+ .on_signature_count = on_count,
+ .on_signature = on_signature,
+
+ // Import section
+ .begin_import_section = begin_import_section,
+ .on_import_count = on_count,
+ .on_import_func = on_import_func,
+ .on_import_table = on_import_table,
+ .on_import_memory = on_import_memory,
+ .on_import_global = on_import_global,
+
+ // Function sigs section
+ .begin_function_signatures_section = begin_function_signatures_section,
+ .on_function_signatures_count = on_count,
+ .on_function_signature = on_function_signature,
+
+ // Table section
+ .begin_table_section = begin_table_section,
+ .on_table_count = on_count,
+ .on_table = on_table,
+
+ // Memory section
+ .begin_memory_section = begin_memory_section,
+ .on_memory_count = on_count,
+ .on_memory = on_memory,
+
+ // Globl seciont
+ .begin_global_section = begin_global_section,
+ .on_global_count = on_count,
+
+ // Export section
+ .begin_export_section = begin_export_section,
+ .on_export_count = on_count,
+ .on_export = on_export,
+
+ // Start section
+ .begin_start_section = begin_start_section,
+
+ // Body section
+ .begin_function_bodies_section = begin_function_bodies_section,
+ .on_function_bodies_count = on_count,
+ .begin_function_body = begin_function_body,
+
+ // Elems section
+ .begin_elem_section = begin_elem_section,
+ .on_elem_segment_count = on_count,
+
+ // Data section
+ .begin_data_section = begin_data_section,
+ .on_data_segment_count = on_count,
+
+ // Names section
+ .begin_names_section = begin_names_section,
+ .on_function_names_count = on_count,
+};
+
+WasmResult wasm_read_binary_objdump(struct WasmAllocator* allocator,
+ const uint8_t* data,
+ size_t size,
+ const WasmObjdumpOptions* options) {
+ WasmBinaryReader reader;
+ WASM_ZERO_MEMORY(reader);
+ reader = s_binary_reader;
+ Context context;
+ WASM_ZERO_MEMORY(context);
+ context.data = data;
+ context.size = size;
+ context.options = options;
+ context.out_stream = wasm_init_stdout_stream();
+
+ if (options->disassemble) {
+ reader.on_opcode = on_opcode;
+ reader.on_opcode_bare = on_opcode_bare;
+ reader.on_opcode_uint32 = on_opcode_uint32;
+ reader.on_opcode_uint32_uint32 = on_opcode_uint32_uint32;
+ reader.on_opcode_uint64 = on_opcode_uint64;
+ reader.on_opcode_block_sig = on_opcode_block_sig;
+ reader.on_end_expr = on_end_expr;
+ reader.on_br_table_expr = on_br_table_expr;
+ }
+
+ reader.user_data = &context;
+ WasmReadBinaryOptions read_options = WASM_READ_BINARY_OPTIONS_DEFAULT;
+ read_options.read_debug_names = WASM_TRUE;
+
+ return wasm_read_binary(allocator, data, size, &reader, 1, &read_options);
+}
diff --git a/src/wasm-binary-reader-objdump.h b/src/wasm-binary-reader-objdump.h
new file mode 100644
index 00000000..c0318f14
--- /dev/null
+++ b/src/wasm-binary-reader-objdump.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WASM_BINARY_READER_OBJDUMP_H_
+#define WASM_BINARY_READER_OBJDUMP_H_
+
+#include "wasm-common.h"
+#include "wasm-stream.h"
+
+struct WasmAllocator;
+struct WasmModule;
+struct WasmReadBinaryOptions;
+
+typedef struct WasmObjdumpOptions {
+ WasmBool headers;
+ WasmBool verbose;
+ WasmBool raw;
+ WasmBool disassemble;
+ WasmBool debug;
+} WasmObjdumpOptions;
+
+WASM_EXTERN_C_BEGIN
+WasmResult wasm_read_binary_objdump(struct WasmAllocator* allocator,
+ const uint8_t* data,
+ size_t size,
+ const WasmObjdumpOptions* options);
+
+WASM_EXTERN_C_END
+
+#endif /* WASM_BINARY_READER_OBJDUMP_H_ */
diff --git a/src/wasm-binary-reader.c b/src/wasm-binary-reader.c
index b9d40262..378f5927 100644
--- a/src/wasm-binary-reader.c
+++ b/src/wasm-binary-reader.c
@@ -43,19 +43,19 @@ typedef uint32_t Uint32;
WASM_DEFINE_VECTOR(type, WasmType)
WASM_DEFINE_VECTOR(uint32, Uint32);
-#define CALLBACK_CTX(member, ...) \
- RAISE_ERROR_UNLESS( \
- WASM_SUCCEEDED( \
- ctx->reader->member \
- ? ctx->reader->member(get_user_context(ctx), __VA_ARGS__)\
- : WASM_OK), \
+#define CALLBACK_CTX(member, ...) \
+ RAISE_ERROR_UNLESS( \
+ WASM_SUCCEEDED( \
+ ctx->reader->member \
+ ? ctx->reader->member(get_user_context(ctx), __VA_ARGS__) \
+ : WASM_OK), \
#member " callback failed")
-#define CALLBACK_CTX0(member) \
- RAISE_ERROR_UNLESS( \
- WASM_SUCCEEDED(ctx->reader->member \
- ? ctx->reader->member(get_user_context(ctx)) \
- : WASM_OK), \
+#define CALLBACK_CTX0(member) \
+ RAISE_ERROR_UNLESS( \
+ WASM_SUCCEEDED(ctx->reader->member \
+ ? ctx->reader->member(get_user_context(ctx)) \
+ : WASM_OK), \
#member " callback failed")
#define CALLBACK_SECTION(member) CALLBACK_CTX(member, section_size)
@@ -79,16 +79,18 @@ WASM_DEFINE_VECTOR(uint32, Uint32);
return ctx->reader->member ? ctx->reader->member(ctx->reader->user_data) \
: WASM_OK
-#define FORWARD_CTX0(member) \
- if (!ctx->reader->member) return WASM_OK; \
- WasmBinaryReaderContext new_ctx = *reader_context;\
- new_ctx.user_data = ctx->reader->user_data; \
+#define FORWARD_CTX0(member) \
+ if (!ctx->reader->member) \
+ return WASM_OK; \
+ WasmBinaryReaderContext new_ctx = *context; \
+ new_ctx.user_data = ctx->reader->user_data; \
return ctx->reader->member(&new_ctx);
-#define FORWARD_CTX(member, ...) \
- if (!ctx->reader->member) return WASM_OK; \
- WasmBinaryReaderContext new_ctx = *reader_context;\
- new_ctx.user_data = ctx->reader->user_data; \
+#define FORWARD_CTX(member, ...) \
+ if (!ctx->reader->member) \
+ return WASM_OK; \
+ WasmBinaryReaderContext new_ctx = *context; \
+ new_ctx.user_data = ctx->reader->user_data; \
return ctx->reader->member(&new_ctx, __VA_ARGS__);
#define FORWARD(member, ...) \
@@ -110,11 +112,6 @@ WASM_STATIC_ASSERT(WASM_ARRAY_SIZE(s_type_names) == WASM_NUM_TYPES);
static const char* s_section_name[] = {WASM_FOREACH_BINARY_SECTION(V)};
#undef V
-static const char* s_external_kind_name[] = {"func", "table", "memory",
- "global"};
-WASM_STATIC_ASSERT(WASM_ARRAY_SIZE(s_external_kind_name) ==
- WASM_NUM_EXTERNAL_KINDS);
-
typedef struct Context {
const uint8_t* data;
size_t size;
@@ -400,8 +397,7 @@ static uint32_t num_total_globals(Context* ctx) {
static WasmBool handle_unknown_section(Context* ctx,
WasmStringSlice* section_name,
uint32_t section_size) {
- if (ctx->options->read_debug_names &&
- ctx->name_section_ok &&
+ if (ctx->options->read_debug_names && ctx->name_section_ok &&
strncmp(section_name->start, WASM_BINARY_SECTION_NAME,
section_name->length) == 0) {
CALLBACK_SECTION(begin_names_section);
@@ -482,7 +478,6 @@ static void destroy_context(WasmAllocator* allocator, Context* ctx) {
wasm_destroy_uint32_vector(allocator, &ctx->target_depths);
}
-
/* Logging */
static void indent(LoggingContext* ctx) {
@@ -526,20 +521,21 @@ static void logging_on_error(WasmBinaryReaderContext* ctx,
}
}
-#define LOGGING_BEGIN(name) \
- static WasmResult logging_begin_##name(WasmBinaryReaderContext* reader_context, uint32_t size) { \
- LoggingContext* ctx = reader_context->user_data; \
- LOGF("begin_" #name "\n"); \
- indent(ctx); \
- FORWARD_CTX(begin_##name, size); \
+#define LOGGING_BEGIN(name) \
+ static WasmResult logging_begin_##name(WasmBinaryReaderContext* context, \
+ uint32_t size) { \
+ LoggingContext* ctx = context->user_data; \
+ LOGF("begin_" #name "\n"); \
+ indent(ctx); \
+ FORWARD_CTX(begin_##name, size); \
}
-#define LOGGING_END(name) \
- static WasmResult logging_end_##name(WasmBinaryReaderContext* reader_context) { \
- LoggingContext* ctx = reader_context->user_data; \
- dedent(ctx); \
- LOGF("end_" #name "\n"); \
- FORWARD_CTX0(end_##name); \
+#define LOGGING_END(name) \
+ static WasmResult logging_end_##name(WasmBinaryReaderContext* context) { \
+ LoggingContext* ctx = context->user_data; \
+ dedent(ctx); \
+ LOGF("end_" #name "\n"); \
+ FORWARD_CTX0(end_##name); \
}
#define LOGGING_UINT32(name) \
@@ -782,7 +778,7 @@ static WasmResult logging_on_export(uint32_t index,
LoggingContext* ctx = user_data;
LOGF("on_export(index: %u, kind: %s, item_index: %u, name: \"" PRIstringslice
"\")\n",
- index, s_external_kind_name[kind], item_index,
+ index, wasm_get_kind_name(kind), item_index,
WASM_PRINTF_STRING_SLICE_ARG(name));
FORWARD(on_export, index, kind, item_index, name);
}
@@ -828,11 +824,11 @@ static WasmResult logging_on_br_if_expr(uint32_t depth, void* user_data) {
FORWARD(on_br_if_expr, depth);
}
-static WasmResult logging_on_br_table_expr(uint32_t num_targets,
+static WasmResult logging_on_br_table_expr(WasmBinaryReaderContext* context,
+ uint32_t num_targets,
uint32_t* target_depths,
- uint32_t default_target_depth,
- void* user_data) {
- LoggingContext* ctx = user_data;
+ uint32_t default_target_depth) {
+ LoggingContext* ctx = context->user_data;
LOGF("on_br_table_expr(num_targets: %u, depths: [", num_targets);
uint32_t i;
for (i = 0; i < num_targets; ++i) {
@@ -841,7 +837,8 @@ static WasmResult logging_on_br_table_expr(uint32_t num_targets,
LOGF_NOINDENT(", ");
}
LOGF_NOINDENT("], default: %u)\n", default_target_depth);
- FORWARD(on_br_table_expr, num_targets, target_depths, default_target_depth);
+ FORWARD_CTX(on_br_table_expr, num_targets, target_depths,
+ default_target_depth);
}
static WasmResult logging_on_f32_const_expr(uint32_t value_bits,
@@ -1245,6 +1242,7 @@ static void read_function_body(Context* ctx,
switch (opcode) {
case WASM_OPCODE_UNREACHABLE:
CALLBACK0(on_unreachable_expr);
+ CALLBACK_CTX0(on_opcode_bare);
break;
case WASM_OPCODE_BLOCK: {
@@ -1254,6 +1252,7 @@ static void read_function_body(Context* ctx,
"expected valid block signature type");
uint32_t num_types = sig_type == WASM_TYPE_VOID ? 0 : 1;
CALLBACK(on_block_expr, num_types, &sig_type);
+ CALLBACK_CTX(on_opcode_block_sig, num_types, &sig_type);
break;
}
@@ -1264,6 +1263,7 @@ static void read_function_body(Context* ctx,
"expected valid block signature type");
uint32_t num_types = sig_type == WASM_TYPE_VOID ? 0 : 1;
CALLBACK(on_loop_expr, num_types, &sig_type);
+ CALLBACK_CTX(on_opcode_block_sig, num_types, &sig_type);
break;
}
@@ -1274,21 +1274,25 @@ static void read_function_body(Context* ctx,
"expected valid block signature type");
uint32_t num_types = sig_type == WASM_TYPE_VOID ? 0 : 1;
CALLBACK(on_if_expr, num_types, &sig_type);
+ CALLBACK_CTX(on_opcode_block_sig, num_types, &sig_type);
break;
}
case WASM_OPCODE_ELSE:
CALLBACK0(on_else_expr);
+ CALLBACK_CTX0(on_opcode_bare);
break;
case WASM_OPCODE_SELECT:
CALLBACK0(on_select_expr);
+ CALLBACK_CTX0(on_opcode_bare);
break;
case WASM_OPCODE_BR: {
uint32_t depth;
in_u32_leb128(ctx, &depth, "br depth");
CALLBACK(on_br_expr, depth);
+ CALLBACK_CTX(on_opcode_uint32, depth);
break;
}
@@ -1296,6 +1300,7 @@ static void read_function_body(Context* ctx,
uint32_t depth;
in_u32_leb128(ctx, &depth, "br_if depth");
CALLBACK(on_br_if_expr, depth);
+ CALLBACK_CTX(on_opcode_uint32, depth);
break;
}
@@ -1303,8 +1308,7 @@ static void read_function_body(Context* ctx,
uint32_t num_targets;
in_u32_leb128(ctx, &num_targets, "br_table target count");
if (num_targets > ctx->target_depths.capacity) {
- wasm_reserve_uint32s(allocator, &ctx->target_depths,
- num_targets);
+ wasm_reserve_uint32s(allocator, &ctx->target_depths, num_targets);
ctx->target_depths.size = num_targets;
}
@@ -1319,21 +1323,24 @@ static void read_function_body(Context* ctx,
in_u32_leb128(ctx, &default_target_depth,
"br_table default target depth");
- CALLBACK(on_br_table_expr, num_targets, ctx->target_depths.data,
- default_target_depth);
+ CALLBACK_CTX(on_br_table_expr, num_targets, ctx->target_depths.data,
+ default_target_depth);
break;
}
case WASM_OPCODE_RETURN:
CALLBACK0(on_return_expr);
+ CALLBACK_CTX0(on_opcode_bare);
break;
case WASM_OPCODE_NOP:
CALLBACK0(on_nop_expr);
+ CALLBACK_CTX0(on_opcode_bare);
break;
case WASM_OPCODE_DROP:
CALLBACK0(on_drop_expr);
+ CALLBACK_CTX0(on_opcode_bare);
break;
case WASM_OPCODE_END:
@@ -1347,6 +1354,7 @@ static void read_function_body(Context* ctx,
uint32_t value = 0;
in_i32_leb128(ctx, &value, "i32.const value");
CALLBACK(on_i32_const_expr, value);
+ CALLBACK_CTX(on_opcode_uint32, value);
break;
}
@@ -1354,6 +1362,7 @@ static void read_function_body(Context* ctx,
uint64_t value = 0;
in_i64_leb128(ctx, &value, "i64.const value");
CALLBACK(on_i64_const_expr, value);
+ CALLBACK_CTX(on_opcode_uint64, value);
break;
}
@@ -1361,6 +1370,7 @@ static void read_function_body(Context* ctx,
uint32_t value_bits = 0;
in_f32(ctx, &value_bits, "f32.const value");
CALLBACK(on_f32_const_expr, value_bits);
+ CALLBACK_CTX(on_opcode_uint32, value_bits);
break;
}
@@ -1368,6 +1378,7 @@ static void read_function_body(Context* ctx,
uint64_t value_bits = 0;
in_f64(ctx, &value_bits, "f64.const value");
CALLBACK(on_f64_const_expr, value_bits);
+ CALLBACK_CTX(on_opcode_uint64, value_bits);
break;
}
@@ -1375,6 +1386,7 @@ static void read_function_body(Context* ctx,
uint32_t global_index;
in_u32_leb128(ctx, &global_index, "get_global global index");
CALLBACK(on_get_global_expr, global_index);
+ CALLBACK_CTX(on_opcode_uint32, global_index);
break;
}
@@ -1382,6 +1394,7 @@ static void read_function_body(Context* ctx,
uint32_t local_index;
in_u32_leb128(ctx, &local_index, "get_local local index");
CALLBACK(on_get_local_expr, local_index);
+ CALLBACK_CTX(on_opcode_uint32, local_index);
break;
}
@@ -1389,6 +1402,7 @@ static void read_function_body(Context* ctx,
uint32_t global_index;
in_u32_leb128(ctx, &global_index, "set_global global index");
CALLBACK(on_set_global_expr, global_index);
+ CALLBACK_CTX(on_opcode_uint32, global_index);
break;
}
@@ -1396,6 +1410,7 @@ static void read_function_body(Context* ctx,
uint32_t local_index;
in_u32_leb128(ctx, &local_index, "set_local local index");
CALLBACK(on_set_local_expr, local_index);
+ CALLBACK_CTX(on_opcode_uint32, local_index);
break;
}
@@ -1405,6 +1420,7 @@ static void read_function_body(Context* ctx,
RAISE_ERROR_UNLESS(func_index < num_total_funcs(ctx),
"invalid call_function function index");
CALLBACK(on_call_expr, func_index);
+ CALLBACK_CTX(on_opcode_uint32, func_index);
break;
}
@@ -1414,6 +1430,7 @@ static void read_function_body(Context* ctx,
RAISE_ERROR_UNLESS(sig_index < ctx->num_signatures,
"invalid call_indirect signature index");
CALLBACK(on_call_indirect_expr, sig_index);
+ CALLBACK_CTX(on_opcode_uint32, sig_index);
break;
}
@@ -1421,6 +1438,7 @@ static void read_function_body(Context* ctx,
uint32_t local_index;
in_u32_leb128(ctx, &local_index, "tee_local local index");
CALLBACK(on_tee_local_expr, local_index);
+ CALLBACK_CTX(on_opcode_uint32, local_index);
break;
}
@@ -1444,6 +1462,7 @@ static void read_function_body(Context* ctx,
in_u32_leb128(ctx, &offset, "load offset");
CALLBACK(on_load_expr, opcode, alignment_log2, offset);
+ CALLBACK_CTX(on_opcode_uint32_uint32, alignment_log2, offset);
break;
}
@@ -1462,15 +1481,18 @@ static void read_function_body(Context* ctx,
in_u32_leb128(ctx, &offset, "store offset");
CALLBACK(on_store_expr, opcode, alignment_log2, offset);
+ CALLBACK_CTX(on_opcode_uint32_uint32, alignment_log2, offset);
break;
}
case WASM_OPCODE_CURRENT_MEMORY:
CALLBACK0(on_current_memory_expr);
+ CALLBACK_CTX0(on_opcode_bare);
break;
case WASM_OPCODE_GROW_MEMORY:
CALLBACK0(on_grow_memory_expr);
+ CALLBACK_CTX0(on_opcode_bare);
break;
case WASM_OPCODE_I32_ADD:
@@ -1518,6 +1540,7 @@ static void read_function_body(Context* ctx,
case WASM_OPCODE_F64_MAX:
case WASM_OPCODE_F64_COPYSIGN:
CALLBACK(on_binary_expr, opcode);
+ CALLBACK_CTX0(on_opcode_bare);
break;
case WASM_OPCODE_I32_EQ:
@@ -1553,6 +1576,7 @@ static void read_function_body(Context* ctx,
case WASM_OPCODE_F64_GT:
case WASM_OPCODE_F64_GE:
CALLBACK(on_compare_expr, opcode);
+ CALLBACK_CTX0(on_opcode_bare);
break;
case WASM_OPCODE_I32_CLZ:
@@ -1576,6 +1600,7 @@ static void read_function_body(Context* ctx,
case WASM_OPCODE_F64_NEAREST:
case WASM_OPCODE_F64_SQRT:
CALLBACK(on_unary_expr, opcode);
+ CALLBACK_CTX0(on_opcode_bare);
break;
case WASM_OPCODE_I32_TRUNC_S_F32:
@@ -1606,6 +1631,7 @@ static void read_function_body(Context* ctx,
case WASM_OPCODE_I32_EQZ:
case WASM_OPCODE_I64_EQZ:
CALLBACK(on_convert_expr, opcode);
+ CALLBACK_CTX0(on_opcode_bare);
break;
default:
@@ -1614,8 +1640,7 @@ static void read_function_body(Context* ctx,
}
RAISE_ERROR_UNLESS(ctx->offset == end_offset,
"function body longer than given size");
- RAISE_ERROR_UNLESS(seen_end_opcode,
- "function body must end with END opcode");
+ RAISE_ERROR_UNLESS(seen_end_opcode, "function body must end with END opcode");
}
WasmResult wasm_read_binary(WasmAllocator* allocator,
@@ -1659,8 +1684,8 @@ WasmResult wasm_read_binary(WasmAllocator* allocator,
uint32_t version;
in_u32(ctx, &version, "version");
RAISE_ERROR_UNLESS(version == WASM_BINARY_VERSION,
- "bad wasm file version: %#x (expected %#x)",
- version, WASM_BINARY_VERSION);
+ "bad wasm file version: %#x (expected %#x)", version,
+ WASM_BINARY_VERSION);
/* type */
uint32_t section_size;
@@ -1763,7 +1788,6 @@ WasmResult wasm_read_binary(WasmAllocator* allocator,
default:
RAISE_ERROR("invalid import kind: %d", kind);
}
-
}
CALLBACK_CTX0(end_import_section);
}
@@ -1912,8 +1936,7 @@ WasmResult wasm_read_binary(WasmAllocator* allocator,
uint32_t j, num_function_indexes;
in_u32_leb128(ctx, &num_function_indexes,
"elem segment function index count");
- CALLBACK(on_elem_segment_function_index_count, i,
- num_function_indexes);
+ CALLBACK(on_elem_segment_function_index_count, i, num_function_indexes);
for (j = 0; j < num_function_indexes; ++j) {
uint32_t func_index;
in_u32_leb128(ctx, &func_index, "elem segment function index");
diff --git a/src/wasm-binary-reader.h b/src/wasm-binary-reader.h
index 35874386..3dcc576e 100644
--- a/src/wasm-binary-reader.h
+++ b/src/wasm-binary-reader.h
@@ -51,7 +51,8 @@ typedef struct WasmBinaryReader {
/* signatures section */
/* TODO(binji): rename to "type" section */
- WasmResult (*begin_signature_section)(WasmBinaryReaderContext* ctx, uint32_t size);
+ WasmResult (*begin_signature_section)(WasmBinaryReaderContext* ctx,
+ uint32_t size);
WasmResult (*on_signature_count)(uint32_t count, void* user_data);
WasmResult (*on_signature)(uint32_t index,
uint32_t param_count,
@@ -62,7 +63,8 @@ typedef struct WasmBinaryReader {
WasmResult (*end_signature_section)(WasmBinaryReaderContext* ctx);
/* import section */
- WasmResult (*begin_import_section)(WasmBinaryReaderContext* ctx, uint32_t size);
+ WasmResult (*begin_import_section)(WasmBinaryReaderContext* ctx,
+ uint32_t size);
WasmResult (*on_import_count)(uint32_t count, void* user_data);
WasmResult (*on_import)(uint32_t index,
WasmStringSlice module_name,
@@ -86,7 +88,8 @@ typedef struct WasmBinaryReader {
/* function signatures section */
/* TODO(binji): rename to "function" section */
- WasmResult (*begin_function_signatures_section)(WasmBinaryReaderContext* ctx, uint32_t size);
+ WasmResult (*begin_function_signatures_section)(WasmBinaryReaderContext* ctx,
+ uint32_t size);
WasmResult (*on_function_signatures_count)(uint32_t count, void* user_data);
WasmResult (*on_function_signature)(uint32_t index,
uint32_t sig_index,
@@ -94,7 +97,8 @@ typedef struct WasmBinaryReader {
WasmResult (*end_function_signatures_section)(WasmBinaryReaderContext* ctx);
/* table section */
- WasmResult (*begin_table_section)(WasmBinaryReaderContext* ctx, uint32_t size);
+ WasmResult (*begin_table_section)(WasmBinaryReaderContext* ctx,
+ uint32_t size);
WasmResult (*on_table_count)(uint32_t count, void* user_data);
WasmResult (*on_table)(uint32_t index,
uint32_t elem_type,
@@ -103,7 +107,8 @@ typedef struct WasmBinaryReader {
WasmResult (*end_table_section)(WasmBinaryReaderContext* ctx);
/* memory section */
- WasmResult (*begin_memory_section)(WasmBinaryReaderContext* ctx, uint32_t size);
+ WasmResult (*begin_memory_section)(WasmBinaryReaderContext* ctx,
+ uint32_t size);
WasmResult (*on_memory_count)(uint32_t count, void* user_data);
WasmResult (*on_memory)(uint32_t index,
const WasmLimits* limits,
@@ -111,7 +116,8 @@ typedef struct WasmBinaryReader {
WasmResult (*end_memory_section)(WasmBinaryReaderContext* ctx);
/* global section */
- WasmResult (*begin_global_section)(WasmBinaryReaderContext* ctx, uint32_t size);
+ WasmResult (*begin_global_section)(WasmBinaryReaderContext* ctx,
+ uint32_t size);
WasmResult (*on_global_count)(uint32_t count, void* user_data);
WasmResult (*begin_global)(uint32_t index,
WasmType type,
@@ -123,7 +129,8 @@ typedef struct WasmBinaryReader {
WasmResult (*end_global_section)(WasmBinaryReaderContext* ctx);
/* exports section */
- WasmResult (*begin_export_section)(WasmBinaryReaderContext* ctx, uint32_t size);
+ WasmResult (*begin_export_section)(WasmBinaryReaderContext* ctx,
+ uint32_t size);
WasmResult (*on_export_count)(uint32_t count, void* user_data);
WasmResult (*on_export)(uint32_t index,
WasmExternalKind kind,
@@ -133,13 +140,15 @@ typedef struct WasmBinaryReader {
WasmResult (*end_export_section)(WasmBinaryReaderContext* ctx);
/* start section */
- WasmResult (*begin_start_section)(WasmBinaryReaderContext* ctx, uint32_t size);
+ WasmResult (*begin_start_section)(WasmBinaryReaderContext* ctx,
+ uint32_t size);
WasmResult (*on_start_function)(uint32_t func_index, void* user_data);
WasmResult (*end_start_section)(WasmBinaryReaderContext* ctx);
/* function bodies section */
/* TODO(binji): rename to code section */
- WasmResult (*begin_function_bodies_section)(WasmBinaryReaderContext* ctx, uint32_t size);
+ WasmResult (*begin_function_bodies_section)(WasmBinaryReaderContext* ctx,
+ uint32_t size);
WasmResult (*on_function_bodies_count)(uint32_t count, void* user_data);
WasmResult (*begin_function_body_pass)(uint32_t index,
uint32_t pass,
@@ -154,16 +163,25 @@ typedef struct WasmBinaryReader {
/* function expressions; called between begin_function_body and
end_function_body */
WasmResult (*on_opcode)(WasmBinaryReaderContext* ctx, WasmOpcode Opcode);
+ WasmResult (*on_opcode_bare)(WasmBinaryReaderContext* ctx);
+ WasmResult (*on_opcode_uint32)(WasmBinaryReaderContext* ctx, uint32_t value);
+ WasmResult (*on_opcode_uint32_uint32)(WasmBinaryReaderContext* ctx,
+ uint32_t value,
+ uint32_t value2);
+ WasmResult (*on_opcode_uint64)(WasmBinaryReaderContext* ctx, uint64_t value);
+ WasmResult (*on_opcode_block_sig)(WasmBinaryReaderContext* ctx,
+ uint32_t num_types,
+ WasmType* sig_types);
WasmResult (*on_binary_expr)(WasmOpcode opcode, void* user_data);
WasmResult (*on_block_expr)(uint32_t num_types,
WasmType* sig_types,
void* user_data);
WasmResult (*on_br_expr)(uint32_t depth, void* user_data);
WasmResult (*on_br_if_expr)(uint32_t depth, void* user_data);
- WasmResult (*on_br_table_expr)(uint32_t num_targets,
+ WasmResult (*on_br_table_expr)(WasmBinaryReaderContext* ctx,
+ uint32_t num_targets,
uint32_t* target_depths,
- uint32_t default_target_depth,
- void* user_data);
+ uint32_t default_target_depth);
WasmResult (*on_call_expr)(uint32_t func_index, void* user_data);
WasmResult (*on_call_import_expr)(uint32_t import_index, void* user_data);
WasmResult (*on_call_indirect_expr)(uint32_t sig_index, void* user_data);
@@ -241,7 +259,8 @@ typedef struct WasmBinaryReader {
WasmResult (*end_data_section)(WasmBinaryReaderContext* ctx);
/* names section */
- WasmResult (*begin_names_section)(WasmBinaryReaderContext* ctx, uint32_t size);
+ WasmResult (*begin_names_section)(WasmBinaryReaderContext* ctx,
+ uint32_t size);
WasmResult (*on_function_names_count)(uint32_t count, void* user_data);
WasmResult (*on_function_name)(uint32_t index,
WasmStringSlice name,
diff --git a/src/wasm-common.c b/src/wasm-common.c
index 9a70e6f1..1df2e335 100644
--- a/src/wasm-common.c
+++ b/src/wasm-common.c
@@ -34,10 +34,13 @@
WasmOpcodeInfo g_wasm_opcode_info[] = {WASM_FOREACH_OPCODE(V)};
#undef V
+const char* g_wasm_kind_name[] = {"func", "table", "memory", "global"};
+WASM_STATIC_ASSERT(WASM_ARRAY_SIZE(g_wasm_kind_name) ==
+ WASM_NUM_EXTERNAL_KINDS);
+
WasmBool wasm_is_naturally_aligned(WasmOpcode opcode, uint32_t alignment) {
uint32_t opcode_align = wasm_get_opcode_memory_size(opcode);
- return alignment == WASM_USE_NATURAL_ALIGNMENT ||
- alignment == opcode_align;
+ return alignment == WASM_USE_NATURAL_ALIGNMENT || alignment == opcode_align;
}
uint32_t wasm_get_opcode_alignment(WasmOpcode opcode, uint32_t alignment) {
diff --git a/src/wasm-common.h b/src/wasm-common.h
index 71f8a044..365572da 100644
--- a/src/wasm-common.h
+++ b/src/wasm-common.h
@@ -151,6 +151,13 @@ typedef enum WasmExternalKind {
WASM_NUM_EXTERNAL_KINDS,
} WasmExternalKind;
+extern const char* g_wasm_kind_name[];
+
+static WASM_INLINE const char* wasm_get_kind_name(WasmExternalKind kind) {
+ assert(kind < WASM_NUM_EXTERNAL_KINDS);
+ return g_wasm_kind_name[kind];
+}
+
typedef struct WasmLimits {
uint64_t initial;
uint64_t max;
diff --git a/src/wasmdump.c b/src/wasmdump.c
new file mode 100644
index 00000000..4a6fa0ca
--- /dev/null
+++ b/src/wasmdump.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2016 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wasm-allocator.h"
+#include "wasm-common.h"
+#include "wasm-option-parser.h"
+#include "wasm-stream.h"
+#include "wasm-writer.h"
+#include "wasm-binary-reader.h"
+#include "wasm-binary-reader-objdump.h"
+
+#define PROGRAM_NAME "wasmdump"
+
+enum {
+ FLAG_HEADERS,
+ FLAG_RAW,
+ FLAG_DISASSEMBLE,
+ FLAG_VERBOSE,
+ FLAG_DEBUG,
+ FLAG_HELP,
+ NUM_FLAGS
+};
+
+static const char s_description[] =
+ " Print information about the contents of a wasm binary file.\n"
+ "\n"
+ "examples:\n"
+ " $ 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"},
+};
+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;
+}
+
+static void on_option(struct WasmOptionParser* parser,
+ struct WasmOption* option,
+ const char* argument) {
+ switch (option->id) {
+ case FLAG_HEADERS:
+ s_objdump_options.headers = WASM_TRUE;
+ break;
+
+ case FLAG_RAW:
+ s_objdump_options.raw = WASM_TRUE;
+ break;
+
+ case FLAG_DEBUG:
+ s_objdump_options.debug = WASM_TRUE;
+
+ case FLAG_DISASSEMBLE:
+ s_objdump_options.disassemble = WASM_TRUE;
+ break;
+
+ case FLAG_VERBOSE:
+ s_objdump_options.verbose = WASM_TRUE;
+ break;
+
+ case FLAG_HELP:
+ wasm_print_help(parser, PROGRAM_NAME);
+ exit(0);
+ break;
+ }
+}
+
+static void on_option_error(struct WasmOptionParser* parser,
+ const char* message) {
+ WASM_FATAL("%s\n", message);
+}
+
+static void parse_options(int argc, char** argv) {
+ WasmOptionParser parser;
+ WASM_ZERO_MEMORY(parser);
+ parser.description = s_description;
+ parser.options = s_options;
+ parser.num_options = WASM_ARRAY_SIZE(s_options);
+ parser.on_option = on_option;
+ parser.on_argument = on_argument;
+ parser.on_error = on_option_error;
+ wasm_parse_options(&parser, argc, argv);
+
+ if (!s_infile) {
+ wasm_print_help(&parser, PROGRAM_NAME);
+ WASM_FATAL("No filename given.\n");
+ }
+}
+
+int main(int argc, char** argv) {
+ wasm_init_stdio();
+
+ parse_options(argc, argv);
+ WasmAllocator* allocator = &g_wasm_libc_allocator;
+
+ void* data;
+ size_t size;
+ WasmResult result = wasm_read_file(allocator, s_infile, &data, &size);
+ if (WASM_FAILED(result))
+ return result;
+
+ result = wasm_read_binary_objdump(allocator, data, size, &s_objdump_options);
+ wasm_free(allocator, data);
+ return result;
+}