diff options
Diffstat (limited to 'src/binary-reader-objdump.cc')
-rw-r--r-- | src/binary-reader-objdump.cc | 936 |
1 files changed, 499 insertions, 437 deletions
diff --git a/src/binary-reader-objdump.cc b/src/binary-reader-objdump.cc index bb251fa2..c6698289 100644 --- a/src/binary-reader-objdump.cc +++ b/src/binary-reader-objdump.cc @@ -23,7 +23,7 @@ #include <vector> -#include "binary-reader.h" +#include "binary-reader-nop.h" #include "literal.h" namespace wabt { @@ -32,36 +32,48 @@ namespace { typedef std::vector<uint32_t> Uint32Vector; -struct Context { - ObjdumpOptions* options; - Stream* out_stream; - const uint8_t* data; - size_t size; - Opcode current_opcode; - size_t current_opcode_offset; - size_t last_opcode_end; - int indent_level; - bool print_details; - bool header_printed; - int section_found; - +class BinaryReaderObjdumpBase : public BinaryReaderNop { + public: + BinaryReaderObjdumpBase(const uint8_t* data, + size_t size, + ObjdumpOptions* options); + + virtual Result OnRelocCount(uint32_t count, + BinarySection section_code, + StringSlice section_name); + virtual Result OnReloc(RelocType type, + uint32_t offset, + uint32_t index, + int32_t addend); + + protected: + bool ShouldPrintDetails(); + void PrintDetails(const char* fmt, ...); + + ObjdumpOptions* options = nullptr; + const uint8_t* data = nullptr; + size_t size = 0; + bool print_details = false; + BinarySection reloc_section = BinarySection::Invalid; uint32_t section_starts[kBinarySectionCount]; - BinarySection reloc_section; - - uint32_t next_reloc; }; -} // namespace +BinaryReaderObjdumpBase::BinaryReaderObjdumpBase(const uint8_t* data, + size_t size, + ObjdumpOptions* options) + : options(options), data(data), size(size) { + WABT_ZERO_MEMORY(section_starts); +} -static bool should_print_details(Context* ctx) { - if (ctx->options->mode != ObjdumpMode::Details) +bool BinaryReaderObjdumpBase::ShouldPrintDetails() { + if (options->mode != ObjdumpMode::Details) return false; - return ctx->print_details; + return print_details; } -static void WABT_PRINTF_FORMAT(2, 3) - print_details(Context* ctx, const char* fmt, ...) { - if (!should_print_details(ctx)) +void WABT_PRINTF_FORMAT(2, 3) + BinaryReaderObjdumpBase::PrintDetails(const char* fmt, ...) { + if (!ShouldPrintDetails()) return; va_list args; va_start(args, fmt); @@ -69,40 +81,224 @@ static void WABT_PRINTF_FORMAT(2, 3) va_end(args); } -static Result begin_section(BinaryReaderContext* ctx, - BinarySection section_code, - uint32_t size) { - Context* context = static_cast<Context*>(ctx->user_data); - context->section_starts[static_cast<size_t>(section_code)] = ctx->offset; +Result BinaryReaderObjdumpBase::OnRelocCount(uint32_t count, + BinarySection section_code, + StringSlice section_name) { + reloc_section = section_code; + PrintDetails(" - section: %s\n", get_section_name(section_code)); + return Result::Ok; +} + +Result BinaryReaderObjdumpBase::OnReloc(RelocType type, + uint32_t offset, + uint32_t index, + int32_t addend) { + uint32_t total_offset = + section_starts[static_cast<size_t>(reloc_section)] + offset; + PrintDetails(" - %-18s idx=%#-4x addend=%#-4x offset=%#x(file=%#x)\n", + get_reloc_type_name(type), index, addend, offset, total_offset); + return Result::Ok; +} + +class BinaryReaderObjdumpPrepass : public BinaryReaderObjdumpBase { + public: + BinaryReaderObjdumpPrepass(const uint8_t* data, + size_t size, + ObjdumpOptions* options); + + virtual Result OnFunctionName(uint32_t function_index, + StringSlice function_name); + virtual Result OnReloc(RelocType type, + uint32_t offset, + uint32_t index, + int32_t addend); +}; + +BinaryReaderObjdumpPrepass::BinaryReaderObjdumpPrepass(const uint8_t* data, + size_t size, + ObjdumpOptions* options) + : BinaryReaderObjdumpBase(data, size, options) {} + +Result BinaryReaderObjdumpPrepass::OnFunctionName(uint32_t index, + StringSlice name) { + if (options->mode == ObjdumpMode::Prepass) { + options->function_names.resize(index + 1); + options->function_names[index] = string_slice_to_string(name); + } else { + PrintDetails(" - func[%d] " PRIstringslice "\n", index, + WABT_PRINTF_STRING_SLICE_ARG(name)); + } + return Result::Ok; +} + +Result BinaryReaderObjdumpPrepass::OnReloc(RelocType type, + uint32_t offset, + uint32_t index, + int32_t addend) { + BinaryReaderObjdumpBase::OnReloc(type, offset, index, addend); + if (reloc_section == BinarySection::Code) { + options->code_relocations.emplace_back(type, offset, index, addend); + } + return Result::Ok; +} + +class BinaryReaderObjdump : public BinaryReaderObjdumpBase { + public: + BinaryReaderObjdump(const uint8_t* data, + size_t size, + ObjdumpOptions* options); + + virtual Result BeginModule(uint32_t version); + virtual Result EndModule(); + + virtual Result BeginSection(BinarySection section_type, uint32_t size); + + virtual Result BeginCustomSection(uint32_t size, StringSlice section_name); + + virtual Result OnTypeCount(uint32_t count); + virtual Result OnType(uint32_t index, + uint32_t param_count, + Type* param_types, + uint32_t result_count, + Type* result_types); + + virtual Result OnImportCount(uint32_t count); + virtual Result OnImportFunc(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t func_index, + uint32_t sig_index); + virtual Result OnImportTable(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t table_index, + Type elem_type, + const Limits* elem_limits); + virtual Result OnImportMemory(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t memory_index, + const Limits* page_limits); + virtual Result OnImportGlobal(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t global_index, + Type type, + bool mutable_); + + virtual Result OnFunctionCount(uint32_t count); + virtual Result OnFunction(uint32_t index, uint32_t sig_index); + + virtual Result OnTableCount(uint32_t count); + virtual Result OnTable(uint32_t index, + Type elem_type, + const Limits* elem_limits); + + virtual Result OnMemoryCount(uint32_t count); + virtual Result OnMemory(uint32_t index, const Limits* limits); + + virtual Result OnGlobalCount(uint32_t count); + virtual Result BeginGlobal(uint32_t index, Type type, bool mutable_); + + virtual Result OnExportCount(uint32_t count); + virtual Result OnExport(uint32_t index, + ExternalKind kind, + uint32_t item_index, + StringSlice name); + + virtual Result OnFunctionBodyCount(uint32_t count); + virtual Result BeginFunctionBody(uint32_t index); + + virtual Result OnOpcode(Opcode Opcode); + virtual Result OnOpcodeBare(); + virtual Result OnOpcodeUint32(uint32_t value); + virtual Result OnOpcodeUint32Uint32(uint32_t value, uint32_t value2); + virtual Result OnOpcodeUint64(uint64_t value); + virtual Result OnOpcodeF32(uint32_t value); + virtual Result OnOpcodeF64(uint64_t value); + virtual Result OnOpcodeBlockSig(uint32_t num_types, Type* sig_types); + + virtual Result OnBrTableExpr(uint32_t num_targets, + uint32_t* target_depths, + uint32_t default_target_depth); + virtual Result OnEndExpr(); + virtual Result OnEndFunc(); + + virtual Result OnElemSegmentCount(uint32_t count); + virtual Result BeginElemSegment(uint32_t index, uint32_t table_index); + virtual Result OnElemSegmentFunctionIndex(uint32_t index, + uint32_t func_index); + + virtual Result OnDataSegmentCount(uint32_t count); + virtual Result BeginDataSegment(uint32_t index, uint32_t memory_index); + virtual Result OnDataSegmentData(uint32_t index, + const void* data, + uint32_t size); + + virtual Result OnFunctionName(uint32_t function_index, + StringSlice function_name); + virtual Result OnLocalName(uint32_t function_index, + uint32_t local_index, + StringSlice local_name); + + virtual Result OnInitExprF32ConstExpr(uint32_t index, uint32_t value); + virtual Result OnInitExprF64ConstExpr(uint32_t index, uint64_t value); + virtual Result OnInitExprGetGlobalExpr(uint32_t index, uint32_t global_index); + virtual Result OnInitExprI32ConstExpr(uint32_t index, uint32_t value); + virtual Result OnInitExprI64ConstExpr(uint32_t index, uint64_t value); + + private: + Result OnCount(uint32_t count); + void LogOpcode(const uint8_t* data, size_t data_size, const char* fmt, ...); + + Stream* out_stream = nullptr; + Opcode current_opcode = Opcode::Unreachable; + size_t current_opcode_offset = 0; + size_t last_opcode_end = 0; + int indent_level = 0; + bool header_printed = false; + int section_found = false; + uint32_t next_reloc = 0; +}; + +BinaryReaderObjdump::BinaryReaderObjdump(const uint8_t* data, + size_t size, + ObjdumpOptions* options) + : BinaryReaderObjdumpBase(data, size, options), + out_stream(init_stdout_stream()) {} + +Result BinaryReaderObjdump::BeginSection(BinarySection section_code, + uint32_t size) { + section_starts[static_cast<size_t>(section_code)] = state->offset; const char* name = get_section_name(section_code); - bool section_match = !context->options->section_name || - !strcasecmp(context->options->section_name, name); + bool section_match = + !options->section_name || !strcasecmp(options->section_name, name); if (section_match) - context->section_found = true; + section_found = true; - switch (context->options->mode) { + switch (options->mode) { case ObjdumpMode::Prepass: break; case ObjdumpMode::Headers: printf("%9s start=%#010" PRIzx " end=%#010" PRIzx " (size=%#010x) ", name, - ctx->offset, ctx->offset + size, size); + state->offset, state->offset + size, size); break; case ObjdumpMode::Details: if (section_match) { if (section_code != BinarySection::Code) printf("%s:\n", name); - context->print_details = true; + print_details = true; } else { - context->print_details = false; + print_details = false; } break; case ObjdumpMode::RawData: if (section_match) { printf("\nContents of section %s:\n", name); - write_memory_dump(context->out_stream, context->data + ctx->offset, - size, ctx->offset, PrintChars::Yes, nullptr, nullptr); + write_memory_dump(out_stream, data + state->offset, size, state->offset, + PrintChars::Yes, nullptr, nullptr); } break; case ObjdumpMode::Disassemble: @@ -111,40 +307,36 @@ static Result begin_section(BinaryReaderContext* ctx, return Result::Ok; } -static Result begin_custom_section(BinaryReaderContext* ctx, - uint32_t size, - StringSlice section_name) { - Context* context = static_cast<Context*>(ctx->user_data); - print_details(context, " - name: \"" PRIstringslice "\"\n", - WABT_PRINTF_STRING_SLICE_ARG(section_name)); - if (context->options->mode == ObjdumpMode::Headers) { +Result BinaryReaderObjdump::BeginCustomSection(uint32_t size, + StringSlice section_name) { + PrintDetails(" - name: \"" PRIstringslice "\"\n", + WABT_PRINTF_STRING_SLICE_ARG(section_name)); + if (options->mode == ObjdumpMode::Headers) { printf("\"" PRIstringslice "\"\n", WABT_PRINTF_STRING_SLICE_ARG(section_name)); } return Result::Ok; } -static Result on_count(uint32_t count, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (ctx->options->mode == ObjdumpMode::Headers) { +Result BinaryReaderObjdump::OnCount(uint32_t count) { + if (options->mode == ObjdumpMode::Headers) { printf("count: %d\n", count); } return Result::Ok; } -static Result begin_module(uint32_t version, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (ctx->options->print_header) { - const char* basename = strrchr(ctx->options->infile, '/'); +Result BinaryReaderObjdump::BeginModule(uint32_t version) { + if (options->print_header) { + const char* basename = strrchr(options->infile, '/'); if (basename) basename++; else - basename = ctx->options->infile; + basename = options->infile; printf("%s:\tfile format wasm %#08x\n", basename, version); - ctx->header_printed = true; + header_printed = true; } - switch (ctx->options->mode) { + switch (options->mode) { case ObjdumpMode::Headers: printf("\n"); printf("Sections:\n\n"); @@ -165,11 +357,10 @@ static Result begin_module(uint32_t version, void* user_data) { return Result::Ok; } -static Result end_module(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (ctx->options->section_name) { - if (!ctx->section_found) { - printf("Section not found: %s\n", ctx->options->section_name); +Result BinaryReaderObjdump::EndModule() { + if (options->section_name) { + if (!section_found) { + printf("Section not found: %s\n", options->section_name); return Result::Error; } } @@ -177,44 +368,44 @@ static Result end_module(void* user_data) { return Result::Ok; } -static Result on_opcode(BinaryReaderContext* ctx, Opcode opcode) { - Context* context = static_cast<Context*>(ctx->user_data); +Result BinaryReaderObjdump::OnOpcode(Opcode opcode) { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; - if (context->options->debug) { + if (options->debug) { const char* opcode_name = get_opcode_name(opcode); - printf("on_opcode: %#" PRIzx ": %s\n", ctx->offset, opcode_name); + printf("on_opcode: %#" PRIzx ": %s\n", state->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]; + if (last_opcode_end) { + if (state->offset != last_opcode_end + 1) { + uint8_t missing_opcode = data[last_opcode_end]; const char* opcode_name = get_opcode_name(static_cast<Opcode>(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); + state->offset, last_opcode_end + 1, data[last_opcode_end], + opcode_name); return Result::Error; } } - context->current_opcode_offset = ctx->offset; - context->current_opcode = opcode; + current_opcode_offset = state->offset; + current_opcode = opcode; return Result::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; +void BinaryReaderObjdump::LogOpcode(const uint8_t* data, + size_t data_size, + const char* fmt, + ...) { + size_t offset = current_opcode_offset; // Print binary data printf(" %06" PRIzx ": %02x", offset - 1, - static_cast<unsigned>(ctx->current_opcode)); + static_cast<unsigned>(current_opcode)); for (size_t i = 0; i < data_size && i < IMMEDIATE_OCTET_COUNT; i++, offset++) { printf(" %02x", data[offset]); @@ -225,14 +416,14 @@ static void log_opcode(Context* ctx, printf(" | "); // Print disassemble - int indent_level = ctx->indent_level; - if (ctx->current_opcode == Opcode::Else) + int indent_level = this->indent_level; + if (current_opcode == Opcode::Else) indent_level--; for (int j = 0; j < indent_level; j++) { printf(" "); } - const char* opcode_name = get_opcode_name(ctx->current_opcode); + const char* opcode_name = get_opcode_name(current_opcode); printf("%s", opcode_name); if (fmt) { printf(" "); @@ -244,15 +435,15 @@ static void log_opcode(Context* ctx, printf("\n"); - ctx->last_opcode_end = ctx->current_opcode_offset + data_size; + last_opcode_end = current_opcode_offset + data_size; - if (ctx->options->relocs) { - if (ctx->next_reloc < ctx->options->code_relocations.size()) { - Reloc* reloc = &ctx->options->code_relocations[ctx->next_reloc]; + if (options->relocs) { + if (next_reloc < options->code_relocations.size()) { + Reloc* reloc = &options->code_relocations[next_reloc]; size_t code_start = - ctx->section_starts[static_cast<size_t>(BinarySection::Code)]; + section_starts[static_cast<size_t>(BinarySection::Code)]; size_t abs_offset = code_start + reloc->offset; - if (ctx->last_opcode_end > abs_offset) { + if (last_opcode_end > abs_offset) { printf(" %06" PRIzx ": %-18s %d", abs_offset, get_reloc_type_name(reloc->type), reloc->index); switch (reloc->type) { @@ -265,85 +456,92 @@ static void log_opcode(Context* ctx, break; } printf("\n"); - ctx->next_reloc++; + next_reloc++; } } } } -static Result on_opcode_bare(BinaryReaderContext* ctx) { - Context* context = static_cast<Context*>(ctx->user_data); - log_opcode(context, ctx->data, 0, nullptr); +Result BinaryReaderObjdump::OnOpcodeBare() { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; + LogOpcode(data, 0, nullptr); return Result::Ok; } -static Result on_opcode_uint32(BinaryReaderContext* ctx, uint32_t value) { - Context* context = static_cast<Context*>(ctx->user_data); - size_t immediate_len = ctx->offset - context->current_opcode_offset; - log_opcode(context, ctx->data, immediate_len, "%#x", value); +Result BinaryReaderObjdump::OnOpcodeUint32(uint32_t value) { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; + size_t immediate_len = state->offset - current_opcode_offset; + LogOpcode(data, immediate_len, "%#x", value); return Result::Ok; } -static Result on_opcode_uint32_uint32(BinaryReaderContext* ctx, - uint32_t value, - uint32_t value2) { - Context* context = static_cast<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); +Result BinaryReaderObjdump::OnOpcodeUint32Uint32(uint32_t value, + uint32_t value2) { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; + size_t immediate_len = state->offset - current_opcode_offset; + LogOpcode(data, immediate_len, "%lu %lu", value, value2); return Result::Ok; } -static Result on_opcode_uint64(BinaryReaderContext* ctx, uint64_t value) { - Context* context = static_cast<Context*>(ctx->user_data); - size_t immediate_len = ctx->offset - context->current_opcode_offset; - log_opcode(context, ctx->data, immediate_len, "%d", value); +Result BinaryReaderObjdump::OnOpcodeUint64(uint64_t value) { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; + size_t immediate_len = state->offset - current_opcode_offset; + LogOpcode(data, immediate_len, "%d", value); return Result::Ok; } -static Result on_opcode_f32(BinaryReaderContext* ctx, uint32_t value) { - Context* context = static_cast<Context*>(ctx->user_data); - size_t immediate_len = ctx->offset - context->current_opcode_offset; +Result BinaryReaderObjdump::OnOpcodeF32(uint32_t value) { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; + size_t immediate_len = state->offset - current_opcode_offset; char buffer[WABT_MAX_FLOAT_HEX]; write_float_hex(buffer, sizeof(buffer), value); - log_opcode(context, ctx->data, immediate_len, buffer); + LogOpcode(data, immediate_len, buffer); return Result::Ok; } -static Result on_opcode_f64(BinaryReaderContext* ctx, uint64_t value) { - Context* context = static_cast<Context*>(ctx->user_data); - size_t immediate_len = ctx->offset - context->current_opcode_offset; +Result BinaryReaderObjdump::OnOpcodeF64(uint64_t value) { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; + size_t immediate_len = state->offset - current_opcode_offset; char buffer[WABT_MAX_DOUBLE_HEX]; write_double_hex(buffer, sizeof(buffer), value); - log_opcode(context, ctx->data, immediate_len, buffer); + LogOpcode(data, immediate_len, buffer); return Result::Ok; } -Result on_br_table_expr(BinaryReaderContext* ctx, - uint32_t num_targets, - uint32_t* target_depths, - uint32_t default_target_depth) { - Context* context = static_cast<Context*>(ctx->user_data); - size_t immediate_len = ctx->offset - context->current_opcode_offset; +Result BinaryReaderObjdump::OnBrTableExpr(uint32_t num_targets, + uint32_t* target_depths, + uint32_t default_target_depth) { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; + size_t immediate_len = state->offset - current_opcode_offset; /* TODO(sbc): Print targets */ - log_opcode(context, ctx->data, immediate_len, nullptr); + LogOpcode(data, immediate_len, nullptr); return Result::Ok; } -static Result on_end_func(void* user_data) { - Context* context = static_cast<Context*>(user_data); - log_opcode(context, nullptr, 0, nullptr); +Result BinaryReaderObjdump::OnEndFunc() { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; + LogOpcode(nullptr, 0, nullptr); return Result::Ok; } -static Result on_end_expr(void* user_data) { - Context* context = static_cast<Context*>(user_data); - context->indent_level--; - assert(context->indent_level >= 0); - log_opcode(context, nullptr, 0, nullptr); +Result BinaryReaderObjdump::OnEndExpr() { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; + indent_level--; + assert(indent_level >= 0); + LogOpcode(nullptr, 0, nullptr); return Result::Ok; } -static const char* type_name(Type type) { +const char* type_name(Type type) { switch (type) { case Type::I32: return "i32"; @@ -363,27 +561,26 @@ static const char* type_name(Type type) { } } -static Result on_opcode_block_sig(BinaryReaderContext* ctx, - uint32_t num_types, - Type* sig_types) { - Context* context = static_cast<Context*>(ctx->user_data); +Result BinaryReaderObjdump::OnOpcodeBlockSig(uint32_t num_types, + Type* sig_types) { if (num_types) - log_opcode(context, ctx->data, 1, "%s", type_name(*sig_types)); + LogOpcode(data, 1, "%s", type_name(*sig_types)); else - log_opcode(context, ctx->data, 1, nullptr); - context->indent_level++; + LogOpcode(data, 1, nullptr); + indent_level++; return Result::Ok; } -static Result on_signature(uint32_t index, - uint32_t param_count, - Type* param_types, - uint32_t result_count, - Type* result_types, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderObjdump::OnTypeCount(uint32_t count) { + return OnCount(count); +} - if (!should_print_details(ctx)) +Result BinaryReaderObjdump::OnType(uint32_t index, + uint32_t param_count, + Type* param_types, + uint32_t result_count, + Type* result_types) { + if (!ShouldPrintDetails()) return Result::Ok; printf(" - [%d] (", index); for (uint32_t i = 0; i < param_count; i++) { @@ -401,380 +598,245 @@ static Result on_signature(uint32_t index, return Result::Ok; } -static Result on_function_signature(uint32_t index, - uint32_t sig_index, - void* user_data) { - print_details(static_cast<Context*>(user_data), " - func[%d] sig=%d\n", index, - sig_index); +Result BinaryReaderObjdump::OnFunctionCount(uint32_t count) { + return OnCount(count); +} + +Result BinaryReaderObjdump::OnFunction(uint32_t index, uint32_t sig_index) { + PrintDetails(" - func[%d] sig=%d\n", index, sig_index); return Result::Ok; } -static Result begin_function_body(BinaryReaderContext* context, - uint32_t index) { - Context* ctx = static_cast<Context*>(context->user_data); +Result BinaryReaderObjdump::OnFunctionBodyCount(uint32_t count) { + return OnCount(count); +} - if (ctx->options->mode == ObjdumpMode::Disassemble) { - if (index < ctx->options->function_names.size() && - !ctx->options->function_names[index].empty()) - printf("%06" PRIzx " <%s>:\n", context->offset, - ctx->options->function_names[index].c_str()); +Result BinaryReaderObjdump::BeginFunctionBody(uint32_t index) { + if (options->mode == ObjdumpMode::Disassemble) { + if (index < options->function_names.size() && + !options->function_names[index].empty()) + printf("%06" PRIzx " <%s>:\n", state->offset, + options->function_names[index].c_str()); else - printf("%06" PRIzx " func[%d]:\n", context->offset, index); + printf("%06" PRIzx " func[%d]:\n", state->offset, index); } - ctx->last_opcode_end = 0; + last_opcode_end = 0; return Result::Ok; } -static Result on_import_func(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t func_index, - uint32_t sig_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, - " - func[%d] sig=%d <- " PRIstringslice "." PRIstringslice "\n", - func_index, sig_index, - WABT_PRINTF_STRING_SLICE_ARG(module_name), - WABT_PRINTF_STRING_SLICE_ARG(field_name)); +Result BinaryReaderObjdump::OnImportCount(uint32_t count) { + return OnCount(count); +} + +Result BinaryReaderObjdump::OnImportFunc(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t func_index, + uint32_t sig_index) { + PrintDetails(" - func[%d] sig=%d <- " PRIstringslice "." PRIstringslice "\n", + func_index, sig_index, WABT_PRINTF_STRING_SLICE_ARG(module_name), + WABT_PRINTF_STRING_SLICE_ARG(field_name)); return Result::Ok; } -static Result on_import_table(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t table_index, - Type elem_type, - const Limits* elem_limits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details( - ctx, " - " PRIstringslice "." PRIstringslice - " -> table elem_type=%s init=%" PRId64 " max=%" PRId64 "\n", - WABT_PRINTF_STRING_SLICE_ARG(module_name), - WABT_PRINTF_STRING_SLICE_ARG(field_name), - get_type_name(elem_type), elem_limits->initial, elem_limits->max); +Result BinaryReaderObjdump::OnImportTable(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t table_index, + Type elem_type, + const Limits* elem_limits) { + PrintDetails(" - " PRIstringslice "." PRIstringslice + " -> table elem_type=%s init=%" PRId64 " max=%" PRId64 "\n", + WABT_PRINTF_STRING_SLICE_ARG(module_name), + WABT_PRINTF_STRING_SLICE_ARG(field_name), + get_type_name(elem_type), elem_limits->initial, + elem_limits->max); return Result::Ok; } -static Result on_import_memory(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t memory_index, - const Limits* page_limits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - " PRIstringslice "." PRIstringslice " -> memory\n", - WABT_PRINTF_STRING_SLICE_ARG(module_name), - WABT_PRINTF_STRING_SLICE_ARG(field_name)); +Result BinaryReaderObjdump::OnImportMemory(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t memory_index, + const Limits* page_limits) { + PrintDetails(" - " PRIstringslice "." PRIstringslice " -> memory\n", + WABT_PRINTF_STRING_SLICE_ARG(module_name), + WABT_PRINTF_STRING_SLICE_ARG(field_name)); return Result::Ok; } -static Result on_import_global(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t global_index, - Type type, - bool mutable_, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - global[%d] %s mutable=%d <- " PRIstringslice - "." PRIstringslice "\n", - global_index, get_type_name(type), mutable_, - WABT_PRINTF_STRING_SLICE_ARG(module_name), - WABT_PRINTF_STRING_SLICE_ARG(field_name)); - return Result::Ok; -} - -static Result on_memory(uint32_t index, - const Limits* page_limits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - memory[%d] pages: initial=%" PRId64, index, - page_limits->initial); +Result BinaryReaderObjdump::OnImportGlobal(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t global_index, + Type type, + bool mutable_) { + PrintDetails(" - global[%d] %s mutable=%d <- " PRIstringslice + "." PRIstringslice "\n", + global_index, get_type_name(type), mutable_, + WABT_PRINTF_STRING_SLICE_ARG(module_name), + WABT_PRINTF_STRING_SLICE_ARG(field_name)); + return Result::Ok; +} + +Result BinaryReaderObjdump::OnMemoryCount(uint32_t count) { + return OnCount(count); +} + +Result BinaryReaderObjdump::OnMemory(uint32_t index, + const Limits* page_limits) { + PrintDetails(" - memory[%d] pages: initial=%" PRId64, index, + page_limits->initial); if (page_limits->has_max) - print_details(ctx, " max=%" PRId64, page_limits->max); - print_details(ctx, "\n"); + PrintDetails(" max=%" PRId64, page_limits->max); + PrintDetails("\n"); return Result::Ok; } -static Result on_table(uint32_t index, - Type elem_type, - const Limits* elem_limits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - table[%d] type=%s initial=%" PRId64, index, - get_type_name(elem_type), elem_limits->initial); +Result BinaryReaderObjdump::OnTableCount(uint32_t count) { + return OnCount(count); +} + +Result BinaryReaderObjdump::OnTable(uint32_t index, + Type elem_type, + const Limits* elem_limits) { + PrintDetails(" - table[%d] type=%s initial=%" PRId64, index, + get_type_name(elem_type), elem_limits->initial); if (elem_limits->has_max) - print_details(ctx, " max=%" PRId64, elem_limits->max); - print_details(ctx, "\n"); + PrintDetails(" max=%" PRId64, elem_limits->max); + PrintDetails("\n"); return Result::Ok; } -static Result on_export(uint32_t index, - ExternalKind kind, - uint32_t item_index, - StringSlice name, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - %s[%d] ", get_kind_name(kind), item_index); - print_details(ctx, PRIstringslice, WABT_PRINTF_STRING_SLICE_ARG(name)); - print_details(ctx, "\n"); +Result BinaryReaderObjdump::OnExportCount(uint32_t count) { + return OnCount(count); +} + +Result BinaryReaderObjdump::OnExport(uint32_t index, + ExternalKind kind, + uint32_t item_index, + StringSlice name) { + PrintDetails(" - %s[%d] ", get_kind_name(kind), item_index); + PrintDetails(PRIstringslice, WABT_PRINTF_STRING_SLICE_ARG(name)); + PrintDetails("\n"); return Result::Ok; } -static Result on_elem_segment_function_index(uint32_t index, - uint32_t func_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - func[%d]\n", func_index); +Result BinaryReaderObjdump::OnElemSegmentFunctionIndex(uint32_t index, + uint32_t func_index) { + PrintDetails(" - func[%d]\n", func_index); return Result::Ok; } -static Result begin_elem_segment(uint32_t index, - uint32_t table_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - segment[%d] table=%d\n", index, table_index); +Result BinaryReaderObjdump::OnElemSegmentCount(uint32_t count) { + return OnCount(count); +} + +Result BinaryReaderObjdump::BeginElemSegment(uint32_t index, + uint32_t table_index) { + PrintDetails(" - segment[%d] table=%d\n", index, table_index); return Result::Ok; } -static Result begin_global(uint32_t index, - Type type, - bool mutable_, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - global[%d] %s mutable=%d", index, get_type_name(type), - mutable_); +Result BinaryReaderObjdump::OnGlobalCount(uint32_t count) { + return OnCount(count); +} + +Result BinaryReaderObjdump::BeginGlobal(uint32_t index, + Type type, + bool mutable_) { + PrintDetails(" - global[%d] %s mutable=%d", index, get_type_name(type), + mutable_); return Result::Ok; } -static Result on_init_expr_f32_const_expr(uint32_t index, - uint32_t value, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderObjdump::OnInitExprF32ConstExpr(uint32_t index, + uint32_t value) { char buffer[WABT_MAX_FLOAT_HEX]; write_float_hex(buffer, sizeof(buffer), value); - print_details(ctx, " - init f32=%s\n", buffer); + PrintDetails(" - init f32=%s\n", buffer); return Result::Ok; } -static Result on_init_expr_f64_const_expr(uint32_t index, - uint64_t value, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderObjdump::OnInitExprF64ConstExpr(uint32_t index, + uint64_t value) { char buffer[WABT_MAX_DOUBLE_HEX]; write_float_hex(buffer, sizeof(buffer), value); - print_details(ctx, " - init f64=%s\n", buffer); + PrintDetails(" - init f64=%s\n", buffer); return Result::Ok; } -static Result on_init_expr_get_global_expr(uint32_t index, - uint32_t global_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - init global=%d\n", global_index); +Result BinaryReaderObjdump::OnInitExprGetGlobalExpr(uint32_t index, + uint32_t global_index) { + PrintDetails(" - init global=%d\n", global_index); return Result::Ok; } -static Result on_init_expr_i32_const_expr(uint32_t index, - uint32_t value, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - init i32=%d\n", value); +Result BinaryReaderObjdump::OnInitExprI32ConstExpr(uint32_t index, + uint32_t value) { + PrintDetails(" - init i32=%d\n", value); return Result::Ok; } -static Result on_init_expr_i64_const_expr(uint32_t index, - uint64_t value, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - init i64=%" PRId64 "\n", value); +Result BinaryReaderObjdump::OnInitExprI64ConstExpr(uint32_t index, + uint64_t value) { + PrintDetails(" - init i64=%" PRId64 "\n", value); return Result::Ok; } -static Result on_function_name(uint32_t index, - StringSlice name, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (ctx->options->mode == ObjdumpMode::Prepass) { - ctx->options->function_names.resize(index+1); - ctx->options->function_names[index] = string_slice_to_string(name); - } else { - print_details(ctx, " - func[%d] " PRIstringslice "\n", index, - WABT_PRINTF_STRING_SLICE_ARG(name)); - } +Result BinaryReaderObjdump::OnFunctionName(uint32_t index, StringSlice name) { + PrintDetails(" - func[%d] " PRIstringslice "\n", index, + WABT_PRINTF_STRING_SLICE_ARG(name)); return Result::Ok; } -static Result on_local_name(uint32_t func_index, - uint32_t local_index, - StringSlice name, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderObjdump::OnLocalName(uint32_t func_index, + uint32_t local_index, + StringSlice name) { if (name.length) { - print_details(ctx, " - func[%d] local[%d] " PRIstringslice "\n", func_index, - local_index, WABT_PRINTF_STRING_SLICE_ARG(name)); + PrintDetails(" - func[%d] local[%d] " PRIstringslice "\n", func_index, + local_index, WABT_PRINTF_STRING_SLICE_ARG(name)); } return Result::Ok; } -Result on_reloc_count(uint32_t count, - BinarySection section_code, - StringSlice section_name, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->reloc_section = section_code; - print_details(ctx, " - section: %s\n", get_section_name(section_code)); - return Result::Ok; -} - -Result on_reloc(RelocType type, - uint32_t offset, - uint32_t index, - int32_t addend, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - uint32_t total_offset = - ctx->section_starts[static_cast<size_t>(ctx->reloc_section)] + offset; - print_details(ctx, " - %-18s idx=%#-4x addend=%#-4x offset=%#x(file=%#x)\n", - get_reloc_type_name(type), index, addend, offset, total_offset); - if (ctx->options->mode == ObjdumpMode::Prepass && - ctx->reloc_section == BinarySection::Code) { - ctx->options->code_relocations.emplace_back(type, offset, index, addend); - } - return Result::Ok; +Result BinaryReaderObjdump::OnDataSegmentCount(uint32_t count) { + return OnCount(count); } -static Result begin_data_segment(uint32_t index, - uint32_t memory_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - memory[%d]", memory_index); +Result BinaryReaderObjdump::BeginDataSegment(uint32_t index, + uint32_t memory_index) { + PrintDetails(" - memory[%d]", memory_index); return Result::Ok; } -static Result on_data_segment_data(uint32_t index, - const void* src_data, - uint32_t size, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (should_print_details(ctx)) { - write_memory_dump(ctx->out_stream, src_data, size, 0, PrintChars::Yes, - " - ", nullptr); +Result BinaryReaderObjdump::OnDataSegmentData(uint32_t index, + const void* src_data, + uint32_t size) { + if (ShouldPrintDetails()) { + write_memory_dump(out_stream, src_data, size, 0, PrintChars::Yes, " - ", + nullptr); } return Result::Ok; } +} // namespace + Result read_binary_objdump(const uint8_t* data, size_t size, ObjdumpOptions* options) { - Context context; - WABT_ZERO_MEMORY(context); - context.header_printed = false; - context.print_details = false; - context.section_found = false; - context.data = data; - context.size = size; - context.options = options; - context.out_stream = init_stdout_stream(); - - BinaryReader reader; - WABT_ZERO_MEMORY(reader); - if (options->mode == ObjdumpMode::Prepass) { - reader.on_function_name = on_function_name; - reader.on_reloc_count = on_reloc_count; - reader.on_reloc = on_reloc; - } else { - reader.begin_module = begin_module; - reader.end_module = end_module; - - reader.begin_section = begin_section; - - // User section - reader.begin_custom_section = begin_custom_section; - - // Signature section - reader.on_signature_count = on_count; - reader.on_signature = on_signature; - - // Import section - reader.on_import_count = on_count; - reader.on_import_func = on_import_func; - reader.on_import_table = on_import_table; - reader.on_import_memory = on_import_memory; - reader.on_import_global = on_import_global; - - // Function sigs section - reader.on_function_signatures_count = on_count; - reader.on_function_signature = on_function_signature; - - // Table section - reader.on_table_count = on_count; - reader.on_table = on_table; - - // Memory section - reader.on_memory_count = on_count; - reader.on_memory = on_memory; - - // Globl seciont - reader.begin_global = begin_global; - reader.on_global_count = on_count; - - // Export section - reader.on_export_count = on_count; - reader.on_export = on_export; - - // Body section - reader.on_function_bodies_count = on_count; - reader.begin_function_body = begin_function_body; - - // Elems section - reader.begin_elem_segment = begin_elem_segment; - reader.on_elem_segment_count = on_count; - reader.on_elem_segment_function_index = on_elem_segment_function_index; - - // Data section - reader.begin_data_segment = begin_data_segment; - reader.on_data_segment_data = on_data_segment_data; - reader.on_data_segment_count = on_count; - - // Known "User" sections: - // - Names section - reader.on_function_name = on_function_name; - reader.on_local_name = on_local_name; - - reader.on_reloc_count = on_reloc_count; - reader.on_reloc = on_reloc; - - reader.on_init_expr_i32_const_expr = on_init_expr_i32_const_expr; - reader.on_init_expr_i64_const_expr = on_init_expr_i64_const_expr; - reader.on_init_expr_f32_const_expr = on_init_expr_f32_const_expr; - reader.on_init_expr_f64_const_expr = on_init_expr_f64_const_expr; - reader.on_init_expr_get_global_expr = on_init_expr_get_global_expr; - } - - if (options->mode == ObjdumpMode::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_f32 = on_opcode_f32; - reader.on_opcode_f64 = on_opcode_f64; - reader.on_opcode_block_sig = on_opcode_block_sig; - reader.on_end_expr = on_end_expr; - reader.on_end_func = on_end_func; - reader.on_br_table_expr = on_br_table_expr; - } - - reader.user_data = &context; - ReadBinaryOptions read_options = WABT_READ_BINARY_OPTIONS_DEFAULT; read_options.read_debug_names = true; read_options.log_stream = options->log_stream; - return read_binary(data, size, &reader, 1, &read_options); + + if (options->mode == ObjdumpMode::Prepass) { + BinaryReaderObjdumpPrepass reader(data, size, options); + return read_binary(data, size, &reader, &read_options); + } else { + BinaryReaderObjdump reader(data, size, options); + return read_binary(data, size, &reader, &read_options); + } } } // namespace wabt |