summaryrefslogtreecommitdiffstats
path: root/third_party/wasm2c/src/binary-reader-objdump.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/wasm2c/src/binary-reader-objdump.cc')
-rw-r--r--third_party/wasm2c/src/binary-reader-objdump.cc2408
1 files changed, 2408 insertions, 0 deletions
diff --git a/third_party/wasm2c/src/binary-reader-objdump.cc b/third_party/wasm2c/src/binary-reader-objdump.cc
new file mode 100644
index 0000000000..96ece0689d
--- /dev/null
+++ b/third_party/wasm2c/src/binary-reader-objdump.cc
@@ -0,0 +1,2408 @@
+/*
+ * 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 "wabt/binary-reader-objdump.h"
+
+#include <algorithm>
+#include <cassert>
+#include <cinttypes>
+#include <cstdio>
+#include <cstring>
+#include <vector>
+
+#if HAVE_STRCASECMP
+#include <strings.h>
+#endif
+
+#include "wabt/binary-reader-nop.h"
+#include "wabt/filenames.h"
+#include "wabt/literal.h"
+#include "wabt/string-util.h"
+
+namespace wabt {
+
+namespace {
+
+class BinaryReaderObjdumpBase : public BinaryReaderNop {
+ public:
+ BinaryReaderObjdumpBase(const uint8_t* data,
+ size_t size,
+ ObjdumpOptions* options,
+ ObjdumpState* state);
+
+ bool OnError(const Error&) override;
+
+ Result BeginModule(uint32_t version) override;
+ Result BeginSection(Index section_index,
+ BinarySection section_type,
+ Offset size) override;
+
+ Result OnOpcode(Opcode Opcode) override;
+ Result OnRelocCount(Index count, Index section_index) override;
+
+ protected:
+ std::string_view GetTypeName(Index index) const;
+ std::string_view GetFunctionName(Index index) const;
+ std::string_view GetGlobalName(Index index) const;
+ std::string_view GetLocalName(Index function_index, Index local_index) const;
+ std::string_view GetSectionName(Index index) const;
+ std::string_view GetTagName(Index index) const;
+ std::string_view GetSymbolName(Index index) const;
+ std::string_view GetSegmentName(Index index) const;
+ std::string_view GetTableName(Index index) const;
+ void PrintRelocation(const Reloc& reloc, Offset offset) const;
+ Offset GetPrintOffset(Offset offset) const;
+ Offset GetSectionStart(BinarySection section_code) const {
+ return section_starts_[static_cast<size_t>(section_code)];
+ }
+
+ ObjdumpOptions* options_;
+ ObjdumpState* objdump_state_;
+ const uint8_t* data_;
+ size_t size_;
+ bool print_details_ = false;
+ BinarySection reloc_section_ = BinarySection::Invalid;
+ Offset section_starts_[kBinarySectionCount];
+ // Map of section index to section type
+ std::vector<BinarySection> section_types_;
+ bool section_found_ = false;
+ std::string module_name_;
+ Opcode current_opcode = Opcode::Unreachable;
+
+ std::unique_ptr<FileStream> err_stream_;
+};
+
+BinaryReaderObjdumpBase::BinaryReaderObjdumpBase(const uint8_t* data,
+ size_t size,
+ ObjdumpOptions* options,
+ ObjdumpState* objdump_state)
+ : options_(options),
+ objdump_state_(objdump_state),
+ data_(data),
+ size_(size),
+ err_stream_(FileStream::CreateStderr()) {
+ ZeroMemory(section_starts_);
+}
+
+Result BinaryReaderObjdumpBase::BeginSection(Index section_index,
+ BinarySection section_code,
+ Offset size) {
+ section_starts_[static_cast<size_t>(section_code)] = state->offset;
+ section_types_.push_back(section_code);
+ return Result::Ok;
+}
+
+bool BinaryReaderObjdumpBase::OnError(const Error&) {
+ // Tell the BinaryReader that this error is "handled" for all passes other
+ // than the prepass. When the error is handled the default message will be
+ // suppressed.
+ return options_->mode != ObjdumpMode::Prepass;
+}
+
+Result BinaryReaderObjdumpBase::BeginModule(uint32_t version) {
+ switch (options_->mode) {
+ case ObjdumpMode::Headers:
+ printf("\n");
+ printf("Sections:\n\n");
+ break;
+ case ObjdumpMode::Details:
+ printf("\n");
+ printf("Section Details:\n\n");
+ break;
+ case ObjdumpMode::Disassemble:
+ printf("\n");
+ printf("Code Disassembly:\n\n");
+ break;
+ case ObjdumpMode::Prepass: {
+ std::string_view basename = GetBasename(options_->filename);
+ if (basename == "-") {
+ basename = "<stdin>";
+ }
+ printf("%s:\tfile format wasm %#x\n", std::string(basename).c_str(),
+ version);
+ break;
+ }
+ case ObjdumpMode::RawData:
+ break;
+ }
+
+ return Result::Ok;
+}
+
+std::string_view BinaryReaderObjdumpBase::GetTypeName(Index index) const {
+ return objdump_state_->type_names.Get(index);
+}
+
+std::string_view BinaryReaderObjdumpBase::GetFunctionName(Index index) const {
+ return objdump_state_->function_names.Get(index);
+}
+
+std::string_view BinaryReaderObjdumpBase::GetGlobalName(Index index) const {
+ return objdump_state_->global_names.Get(index);
+}
+
+std::string_view BinaryReaderObjdumpBase::GetLocalName(
+ Index function_index,
+ Index local_index) const {
+ return objdump_state_->local_names.Get(function_index, local_index);
+}
+
+std::string_view BinaryReaderObjdumpBase::GetSectionName(Index index) const {
+ return objdump_state_->section_names.Get(index);
+}
+
+std::string_view BinaryReaderObjdumpBase::GetTagName(Index index) const {
+ return objdump_state_->tag_names.Get(index);
+}
+
+std::string_view BinaryReaderObjdumpBase::GetSegmentName(Index index) const {
+ return objdump_state_->segment_names.Get(index);
+}
+
+std::string_view BinaryReaderObjdumpBase::GetTableName(Index index) const {
+ return objdump_state_->table_names.Get(index);
+}
+
+std::string_view BinaryReaderObjdumpBase::GetSymbolName(
+ Index symbol_index) const {
+ if (symbol_index >= objdump_state_->symtab.size())
+ return "<illegal_symbol_index>";
+ ObjdumpSymbol& sym = objdump_state_->symtab[symbol_index];
+ switch (sym.kind) {
+ case SymbolType::Function:
+ return GetFunctionName(sym.index);
+ case SymbolType::Data:
+ return sym.name;
+ case SymbolType::Global:
+ return GetGlobalName(sym.index);
+ case SymbolType::Section:
+ return GetSectionName(sym.index);
+ case SymbolType::Tag:
+ return GetTagName(sym.index);
+ case SymbolType::Table:
+ return GetTableName(sym.index);
+ }
+ WABT_UNREACHABLE;
+}
+
+void BinaryReaderObjdumpBase::PrintRelocation(const Reloc& reloc,
+ Offset offset) const {
+ printf(" %06" PRIzx ": %-18s %" PRIindex, offset,
+ GetRelocTypeName(reloc.type), reloc.index);
+ if (reloc.addend) {
+ printf(" + %d", reloc.addend);
+ }
+ if (reloc.type != RelocType::TypeIndexLEB) {
+ printf(" <" PRIstringview ">",
+ WABT_PRINTF_STRING_VIEW_ARG(GetSymbolName(reloc.index)));
+ }
+ printf("\n");
+}
+
+Offset BinaryReaderObjdumpBase::GetPrintOffset(Offset offset) const {
+ return options_->section_offsets
+ ? offset - GetSectionStart(BinarySection::Code)
+ : offset;
+}
+
+Result BinaryReaderObjdumpBase::OnOpcode(Opcode opcode) {
+ current_opcode = opcode;
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpBase::OnRelocCount(Index count, Index section_index) {
+ if (section_index >= section_types_.size()) {
+ err_stream_->Writef("invalid relocation section index: %" PRIindex "\n",
+ section_index);
+ reloc_section_ = BinarySection::Invalid;
+ return Result::Error;
+ }
+ reloc_section_ = section_types_[section_index];
+ return Result::Ok;
+}
+
+class BinaryReaderObjdumpPrepass : public BinaryReaderObjdumpBase {
+ public:
+ using BinaryReaderObjdumpBase::BinaryReaderObjdumpBase;
+
+ Result BeginSection(Index section_index,
+ BinarySection section_code,
+ Offset size) override {
+ BinaryReaderObjdumpBase::BeginSection(section_index, section_code, size);
+ if (section_code != BinarySection::Custom) {
+ objdump_state_->section_names.Set(section_index,
+ wabt::GetSectionName(section_code));
+ }
+ return Result::Ok;
+ }
+
+ Result BeginCustomSection(Index section_index,
+ Offset size,
+ std::string_view section_name) override {
+ objdump_state_->section_names.Set(section_index, section_name);
+ return Result::Ok;
+ }
+
+ Result OnFunctionName(Index index, std::string_view name) override {
+ SetFunctionName(index, name);
+ return Result::Ok;
+ }
+
+ Result OnFuncType(Index index,
+ Index param_count,
+ Type* param_types,
+ Index result_count,
+ Type* result_types) override {
+ objdump_state_->function_param_counts[index] = param_count;
+ return Result::Ok;
+ }
+
+ Result OnNameEntry(NameSectionSubsection type,
+ Index index,
+ std::string_view name) override {
+ switch (type) {
+ // TODO(sbc): remove OnFunctionName in favor of just using
+ // OnNameEntry so that this works
+ /*
+ case NameSectionSubsection::Function:
+ SetFunctionName(index, name);
+ break;
+ */
+ case NameSectionSubsection::Type:
+ SetTypeName(index, name);
+ break;
+ case NameSectionSubsection::Global:
+ SetGlobalName(index, name);
+ break;
+ case NameSectionSubsection::Table:
+ SetTableName(index, name);
+ break;
+ case NameSectionSubsection::DataSegment:
+ SetSegmentName(index, name);
+ break;
+ case NameSectionSubsection::Tag:
+ SetTagName(index, name);
+ break;
+ default:
+ break;
+ }
+ return Result::Ok;
+ }
+
+ Result OnLocalName(Index function_index,
+ Index local_index,
+ std::string_view local_name) override {
+ SetLocalName(function_index, local_index, local_name);
+ return Result::Ok;
+ }
+
+ Result OnSymbolCount(Index count) override {
+ objdump_state_->symtab.resize(count);
+ return Result::Ok;
+ }
+
+ Result OnDataSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index segment,
+ uint32_t offset,
+ uint32_t size) override {
+ objdump_state_->symtab[index] = {SymbolType::Data, std::string(name), 0};
+ return Result::Ok;
+ }
+
+ Result OnFunctionSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index func_index) override {
+ if (!name.empty()) {
+ SetFunctionName(func_index, name);
+ }
+ objdump_state_->symtab[index] = {SymbolType::Function, std::string(name),
+ func_index};
+ return Result::Ok;
+ }
+
+ Result OnGlobalSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index global_index) override {
+ if (!name.empty()) {
+ SetGlobalName(global_index, name);
+ }
+ objdump_state_->symtab[index] = {SymbolType::Global, std::string(name),
+ global_index};
+ return Result::Ok;
+ }
+
+ Result OnSectionSymbol(Index index,
+ uint32_t flags,
+ Index section_index) override {
+ objdump_state_->symtab[index] = {SymbolType::Section,
+ std::string(GetSectionName(section_index)),
+ section_index};
+ return Result::Ok;
+ }
+
+ Result OnTagSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index tag_index) override {
+ if (!name.empty()) {
+ SetTagName(tag_index, name);
+ }
+ objdump_state_->symtab[index] = {SymbolType::Tag, std::string(name),
+ tag_index};
+ return Result::Ok;
+ }
+
+ Result OnTableSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index table_index) override {
+ if (!name.empty()) {
+ SetTableName(table_index, name);
+ }
+ objdump_state_->symtab[index] = {SymbolType::Table, std::string(name),
+ table_index};
+ return Result::Ok;
+ }
+
+ Result OnImportFunc(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index func_index,
+ Index sig_index) override {
+ SetFunctionName(func_index, module_name + "." + field_name);
+ return Result::Ok;
+ }
+
+ Result OnImportTag(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index tag_index,
+ Index sig_index) override {
+ SetTagName(tag_index, module_name + "." + field_name);
+ return Result::Ok;
+ }
+
+ Result OnImportGlobal(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index global_index,
+ Type type,
+ bool mutable_) override {
+ SetGlobalName(global_index, module_name + "." + field_name);
+ return Result::Ok;
+ }
+
+ Result OnImportTable(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index table_index,
+ Type elem_type,
+ const Limits* elem_limits) override {
+ SetTableName(table_index, module_name + "." + field_name);
+ return Result::Ok;
+ }
+
+ Result OnExport(Index index,
+ ExternalKind kind,
+ Index item_index,
+ std::string_view name) override {
+ if (kind == ExternalKind::Func) {
+ SetFunctionName(item_index, name);
+ } else if (kind == ExternalKind::Global) {
+ SetGlobalName(item_index, name);
+ }
+ return Result::Ok;
+ }
+
+ Result OnReloc(RelocType type,
+ Offset offset,
+ Index index,
+ uint32_t addend) override;
+
+ Result OnModuleName(std::string_view name) override {
+ if (options_->mode == ObjdumpMode::Prepass) {
+ printf("module name: <" PRIstringview ">\n",
+ WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ return Result::Ok;
+ }
+
+ Result OnSegmentInfo(Index index,
+ std::string_view name,
+ Address alignment_log2,
+ uint32_t flags) override {
+ SetSegmentName(index, name);
+ return Result::Ok;
+ }
+
+ protected:
+ void SetTypeName(Index index, std::string_view name);
+ void SetFunctionName(Index index, std::string_view name);
+ void SetGlobalName(Index index, std::string_view name);
+ void SetLocalName(Index function_index,
+ Index local_index,
+ std::string_view name);
+ void SetTagName(Index index, std::string_view name);
+ void SetTableName(Index index, std::string_view name);
+ void SetSegmentName(Index index, std::string_view name);
+};
+
+void BinaryReaderObjdumpPrepass::SetTypeName(Index index,
+ std::string_view name) {
+ objdump_state_->type_names.Set(index, name);
+}
+
+void BinaryReaderObjdumpPrepass::SetFunctionName(Index index,
+ std::string_view name) {
+ objdump_state_->function_names.Set(index, name);
+}
+
+void BinaryReaderObjdumpPrepass::SetGlobalName(Index index,
+ std::string_view name) {
+ objdump_state_->global_names.Set(index, name);
+}
+
+void BinaryReaderObjdumpPrepass::SetLocalName(Index function_index,
+ Index local_index,
+ std::string_view name) {
+ objdump_state_->local_names.Set(function_index, local_index, name);
+}
+
+void BinaryReaderObjdumpPrepass::SetTagName(Index index,
+ std::string_view name) {
+ objdump_state_->tag_names.Set(index, name);
+}
+
+void BinaryReaderObjdumpPrepass::SetTableName(Index index,
+ std::string_view name) {
+ objdump_state_->table_names.Set(index, name);
+}
+
+void BinaryReaderObjdumpPrepass::SetSegmentName(Index index,
+ std::string_view name) {
+ objdump_state_->segment_names.Set(index, name);
+}
+
+Result BinaryReaderObjdumpPrepass::OnReloc(RelocType type,
+ Offset offset,
+ Index index,
+ uint32_t addend) {
+ BinaryReaderObjdumpBase::OnReloc(type, offset, index, addend);
+ if (reloc_section_ == BinarySection::Code) {
+ objdump_state_->code_relocations.emplace_back(type, offset, index, addend);
+ } else if (reloc_section_ == BinarySection::Data) {
+ objdump_state_->data_relocations.emplace_back(type, offset, index, addend);
+ }
+ return Result::Ok;
+}
+
+class BinaryReaderObjdumpDisassemble : public BinaryReaderObjdumpBase {
+ public:
+ using BinaryReaderObjdumpBase::BinaryReaderObjdumpBase;
+
+ std::string BlockSigToString(Type type) const;
+
+ Result BeginFunctionBody(Index index, Offset size) override;
+ Result EndFunctionBody(Index index) override;
+
+ Result OnLocalDeclCount(Index count) override;
+ Result OnLocalDecl(Index decl_index, Index count, Type type) override;
+
+ Result OnOpcode(Opcode Opcode) override;
+ Result OnOpcodeBare() override;
+ Result OnOpcodeIndex(Index value) override;
+ Result OnOpcodeIndexIndex(Index value, Index value2) override;
+ Result OnOpcodeUint32(uint32_t value) override;
+ Result OnOpcodeUint32Uint32(uint32_t value, uint32_t value2) override;
+ Result OnCallIndirectExpr(uint32_t sig_indix, uint32_t table_index) override;
+ Result OnOpcodeUint32Uint32Uint32(uint32_t value,
+ uint32_t value2,
+ uint32_t value3) override;
+ Result OnOpcodeUint32Uint32Uint32Uint32(uint32_t value,
+ uint32_t value2,
+ uint32_t value3,
+ uint32_t value4) override;
+ Result OnOpcodeUint64(uint64_t value) override;
+ Result OnOpcodeF32(uint32_t value) override;
+ Result OnOpcodeF64(uint64_t value) override;
+ Result OnOpcodeV128(v128 value) override;
+ Result OnOpcodeBlockSig(Type sig_type) override;
+ Result OnOpcodeType(Type type) override;
+
+ Result OnBrTableExpr(Index num_targets,
+ Index* target_depths,
+ Index default_target_depth) override;
+ Result OnDelegateExpr(Index) override;
+ Result OnEndExpr() override;
+
+ private:
+ void LogOpcode(const char* fmt, ...);
+
+ Offset current_opcode_offset = 0;
+ Offset last_opcode_end = 0;
+ int indent_level = 0;
+ Index next_reloc = 0;
+ Index current_function_index = 0;
+ Index local_index_ = 0;
+ bool in_function_body = false;
+ bool skip_next_opcode_ = false;
+};
+
+std::string BinaryReaderObjdumpDisassemble::BlockSigToString(Type type) const {
+ if (type.IsIndex()) {
+ return StringPrintf("type[%d]", type.GetIndex());
+ } else if (type == Type::Void) {
+ return "";
+ } else {
+ return type.GetName();
+ }
+}
+
+Result BinaryReaderObjdumpDisassemble::OnOpcode(Opcode opcode) {
+ BinaryReaderObjdumpBase::OnOpcode(opcode);
+ if (!in_function_body) {
+ return Result::Ok;
+ }
+ if (options_->debug) {
+ const char* opcode_name = opcode.GetName();
+ err_stream_->Writef("on_opcode: %#" PRIzx ": %s\n", state->offset,
+ opcode_name);
+ }
+
+ if (last_opcode_end) {
+ // Takes care of cases where opcode's bytes was a non-canonical leb128
+ // encoding. In this case, opcode.GetLength() under-reports the length,
+ // since it canonicalizes the opcode.
+ if (state->offset < last_opcode_end + opcode.GetLength()) {
+ Opcode missing_opcode = Opcode::FromCode(data_[last_opcode_end]);
+ const char* opcode_name = missing_opcode.GetName();
+ fprintf(stderr,
+ "error: %#" PRIzx " missing opcode callback at %#" PRIzx
+ " (%#02x=%s)\n",
+ state->offset, last_opcode_end + 1, data_[last_opcode_end],
+ opcode_name);
+ return Result::Error;
+ }
+ }
+
+ current_opcode_offset = state->offset;
+ return Result::Ok;
+}
+
+#define IMMEDIATE_OCTET_COUNT 9
+
+Result BinaryReaderObjdumpDisassemble::OnLocalDeclCount(Index count) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
+ current_opcode_offset = state->offset;
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::OnLocalDecl(Index decl_index,
+ Index count,
+ Type type) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
+ Offset offset = current_opcode_offset;
+ size_t data_size = state->offset - offset;
+
+ printf(" %06" PRIzx ":", GetPrintOffset(offset));
+ for (size_t i = 0; i < data_size && i < IMMEDIATE_OCTET_COUNT;
+ i++, offset++) {
+ printf(" %02x", data_[offset]);
+ }
+ for (size_t i = data_size; i < IMMEDIATE_OCTET_COUNT; i++) {
+ printf(" ");
+ }
+ printf(" | local[%" PRIindex, local_index_);
+
+ if (count != 1) {
+ printf("..%" PRIindex "", local_index_ + count - 1);
+ }
+ local_index_ += count;
+
+ printf("] type=%s\n", type.GetName().c_str());
+
+ last_opcode_end = current_opcode_offset + data_size;
+ current_opcode_offset = last_opcode_end;
+
+ return Result::Ok;
+}
+
+void BinaryReaderObjdumpDisassemble::LogOpcode(const char* fmt, ...) {
+ // BinaryReaderObjdumpDisassemble is only used to disassembly function bodies
+ // so this should never be called for instructions outside of function bodies
+ // (i.e. init expresions).
+ assert(in_function_body);
+ if (skip_next_opcode_) {
+ skip_next_opcode_ = false;
+ return;
+ }
+ const Offset immediate_len = state->offset - current_opcode_offset;
+ const Offset opcode_size = current_opcode.GetLength();
+ const Offset total_size = opcode_size + immediate_len;
+ // current_opcode_offset has already read past this opcode; rewind it by the
+ // size of this opcode, which may be more than one byte.
+ Offset offset = current_opcode_offset - opcode_size;
+ const Offset offset_end = offset + total_size;
+
+ bool first_line = true;
+ while (offset < offset_end) {
+ // Print bytes, but only display a maximum of IMMEDIATE_OCTET_COUNT on each
+ // line.
+ printf(" %06" PRIzx ":", GetPrintOffset(offset));
+ size_t i;
+ for (i = 0; offset < offset_end && i < IMMEDIATE_OCTET_COUNT;
+ ++i, ++offset) {
+ printf(" %02x", data_[offset]);
+ }
+ // Fill the rest of the remaining space with spaces.
+ for (; i < IMMEDIATE_OCTET_COUNT; ++i) {
+ printf(" ");
+ }
+ printf(" | ");
+
+ if (first_line) {
+ first_line = false;
+
+ // Print disassembly.
+ int indent_level = this->indent_level;
+ switch (current_opcode) {
+ case Opcode::Else:
+ case Opcode::Catch:
+ case Opcode::CatchAll:
+ indent_level--;
+ break;
+ default:
+ break;
+ }
+ for (int j = 0; j < indent_level; j++) {
+ printf(" ");
+ }
+
+ const char* opcode_name = current_opcode.GetName();
+ printf("%s", opcode_name);
+ if (fmt) {
+ printf(" ");
+ va_list args;
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ }
+ }
+
+ printf("\n");
+ }
+
+ last_opcode_end = state->offset;
+
+ // Print relocation after then full (potentially multi-line) instruction.
+ if (options_->relocs &&
+ next_reloc < objdump_state_->code_relocations.size()) {
+ const Reloc& reloc = objdump_state_->code_relocations[next_reloc];
+ Offset code_start = GetSectionStart(BinarySection::Code);
+ Offset abs_offset = code_start + reloc.offset;
+ if (last_opcode_end > abs_offset) {
+ PrintRelocation(reloc, abs_offset);
+ next_reloc++;
+ }
+ }
+}
+
+Result BinaryReaderObjdumpDisassemble::OnOpcodeBare() {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
+ LogOpcode(0, nullptr);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::OnOpcodeIndex(Index value) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
+ std::string_view name;
+ if (current_opcode == Opcode::Call &&
+ !(name = GetFunctionName(value)).empty()) {
+ LogOpcode("%d <" PRIstringview ">", value,
+ WABT_PRINTF_STRING_VIEW_ARG(name));
+ } else if (current_opcode == Opcode::Throw &&
+ !(name = GetTagName(value)).empty()) {
+ LogOpcode("%d <" PRIstringview ">", value,
+ WABT_PRINTF_STRING_VIEW_ARG(name));
+ } else if ((current_opcode == Opcode::GlobalGet ||
+ current_opcode == Opcode::GlobalSet) &&
+ !(name = GetGlobalName(value)).empty()) {
+ LogOpcode("%d <" PRIstringview ">", value,
+ WABT_PRINTF_STRING_VIEW_ARG(name));
+ } else if ((current_opcode == Opcode::LocalGet ||
+ current_opcode == Opcode::LocalSet) &&
+ !(name = GetLocalName(current_function_index, value)).empty()) {
+ LogOpcode("%d <" PRIstringview ">", value,
+ WABT_PRINTF_STRING_VIEW_ARG(name));
+ } else {
+ LogOpcode("%d", value);
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::OnOpcodeIndexIndex(Index value,
+ Index value2) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
+ LogOpcode("%" PRIindex " %" PRIindex, value, value2);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::OnOpcodeUint32(uint32_t value) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
+ std::string_view name;
+ if (current_opcode == Opcode::DataDrop &&
+ !(name = GetSegmentName(value)).empty()) {
+ LogOpcode("%d <" PRIstringview ">", value,
+ WABT_PRINTF_STRING_VIEW_ARG(name));
+ } else {
+ LogOpcode("%u", value);
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::OnOpcodeUint32Uint32(uint32_t value,
+ uint32_t value2) {
+ if (!in_function_body)
+ return Result::Ok;
+ std::string_view name;
+ if (current_opcode == Opcode::MemoryInit &&
+ !(name = GetSegmentName(value)).empty()) {
+ LogOpcode("%u %u <" PRIstringview ">", value, value2,
+ WABT_PRINTF_STRING_VIEW_ARG(name));
+ } else {
+ LogOpcode("%u %u", value, value2);
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::OnCallIndirectExpr(
+ uint32_t sig_index,
+ uint32_t table_index) {
+ std::string_view table_name = GetTableName(table_index);
+ std::string_view type_name = GetTypeName(sig_index);
+ if (!type_name.empty() && !table_name.empty()) {
+ LogOpcode("%u <" PRIstringview "> (type %u <" PRIstringview ">)",
+ table_index, WABT_PRINTF_STRING_VIEW_ARG(table_name), sig_index,
+ WABT_PRINTF_STRING_VIEW_ARG(type_name));
+ } else if (!table_name.empty()) {
+ LogOpcode("%u <" PRIstringview "> (type %u)", table_index,
+ WABT_PRINTF_STRING_VIEW_ARG(table_name), sig_index);
+ } else if (!type_name.empty()) {
+ LogOpcode("%u (type %u <" PRIstringview ">)", table_index, sig_index,
+ WABT_PRINTF_STRING_VIEW_ARG(type_name));
+ } else {
+ LogOpcode("%u (type %u)", table_index, sig_index);
+ }
+ skip_next_opcode_ = true;
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::OnOpcodeUint32Uint32Uint32(
+ uint32_t value,
+ uint32_t value2,
+ uint32_t value3) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
+ LogOpcode("%u %u %u", value, value2, value3);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::OnOpcodeUint32Uint32Uint32Uint32(
+ uint32_t value,
+ uint32_t value2,
+ uint32_t value3,
+ uint32_t value4) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
+ LogOpcode("%u %u %u %u", value, value2, value3, value4);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::OnOpcodeUint64(uint64_t value) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
+ LogOpcode("%" PRId64, value);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::OnOpcodeF32(uint32_t value) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
+ char buffer[WABT_MAX_FLOAT_HEX];
+ WriteFloatHex(buffer, sizeof(buffer), value);
+ LogOpcode(buffer);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::OnOpcodeF64(uint64_t value) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
+ char buffer[WABT_MAX_DOUBLE_HEX];
+ WriteDoubleHex(buffer, sizeof(buffer), value);
+ LogOpcode(buffer);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::OnOpcodeV128(v128 value) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
+ // v128 is always dumped as i32x4:
+ LogOpcode("0x%08x 0x%08x 0x%08x 0x%08x", value.u32(0), value.u32(1),
+ value.u32(2), value.u32(3));
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::OnOpcodeType(Type type) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
+ if (current_opcode == Opcode::SelectT) {
+ LogOpcode(type.GetName().c_str());
+ } else {
+ LogOpcode(type.GetRefKindName());
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::OnBrTableExpr(
+ Index num_targets,
+ Index* target_depths,
+ Index default_target_depth) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
+
+ std::string buffer = std::string();
+ for (Index i = 0; i < num_targets; i++) {
+ buffer.append(std::to_string(target_depths[i])).append(" ");
+ }
+ buffer.append(std::to_string(default_target_depth));
+
+ LogOpcode("%s", buffer.c_str());
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::OnDelegateExpr(Index depth) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
+ // Because `delegate` ends the block we need to dedent here, and
+ // we don't need to dedent it in LogOpcode.
+ if (indent_level > 0) {
+ indent_level--;
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::OnEndExpr() {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
+ if (indent_level > 0) {
+ indent_level--;
+ }
+ LogOpcode(0, nullptr);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::BeginFunctionBody(Index index,
+ Offset size) {
+ printf("%06" PRIzx " func[%" PRIindex "]", GetPrintOffset(state->offset),
+ index);
+ auto name = GetFunctionName(index);
+ if (!name.empty()) {
+ printf(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ printf(":\n");
+
+ last_opcode_end = 0;
+ in_function_body = true;
+ current_function_index = index;
+ local_index_ = objdump_state_->function_param_counts[index];
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::EndFunctionBody(Index index) {
+ assert(in_function_body);
+ in_function_body = false;
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::OnOpcodeBlockSig(Type sig_type) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
+ if (sig_type != Type::Void) {
+ LogOpcode("%s", BlockSigToString(sig_type).c_str());
+ } else {
+ LogOpcode(nullptr);
+ }
+ indent_level++;
+ return Result::Ok;
+}
+
+enum class InitExprType {
+ I32,
+ F32,
+ I64,
+ F64,
+ V128,
+ Global,
+ FuncRef,
+ // TODO: There isn't a nullref anymore, this just represents ref.null of some
+ // type T.
+ NullRef,
+};
+
+struct InitInst {
+ Opcode opcode;
+ union {
+ Index index;
+ uint32_t i32;
+ uint32_t f32;
+ uint64_t i64;
+ uint64_t f64;
+ v128 v128_v;
+ Type type;
+ } imm;
+};
+
+struct InitExpr {
+ InitExprType type;
+ std::vector<InitInst> insts;
+};
+
+class BinaryReaderObjdump : public BinaryReaderObjdumpBase {
+ public:
+ BinaryReaderObjdump(const uint8_t* data,
+ size_t size,
+ ObjdumpOptions* options,
+ ObjdumpState* state);
+
+ Result EndModule() override;
+ Result BeginSection(Index section_index,
+ BinarySection section_type,
+ Offset size) override;
+ Result BeginCustomSection(Index section_index,
+ Offset size,
+ std::string_view section_name) override;
+
+ Result OnTypeCount(Index count) override;
+ Result OnFuncType(Index index,
+ Index param_count,
+ Type* param_types,
+ Index result_count,
+ Type* result_types) override;
+ Result OnStructType(Index index, Index field_count, TypeMut* fields) override;
+ Result OnArrayType(Index index, TypeMut field) override;
+
+ Result OnImportCount(Index count) override;
+ Result OnImportFunc(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index func_index,
+ Index sig_index) override;
+ Result OnImportTable(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index table_index,
+ Type elem_type,
+ const Limits* elem_limits) override;
+ Result OnImportMemory(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index memory_index,
+ const Limits* page_limits) override;
+ Result OnImportGlobal(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index global_index,
+ Type type,
+ bool mutable_) override;
+ Result OnImportTag(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index tag_index,
+ Index sig_index) override;
+
+ Result OnFunctionCount(Index count) override;
+ Result OnFunction(Index index, Index sig_index) override;
+
+ Result OnTableCount(Index count) override;
+ Result OnTable(Index index,
+ Type elem_type,
+ const Limits* elem_limits) override;
+
+ Result OnMemoryCount(Index count) override;
+ Result OnMemory(Index index, const Limits* limits) override;
+
+ Result OnGlobalCount(Index count) override;
+ Result BeginGlobal(Index index, Type type, bool mutable_) override;
+
+ Result OnExportCount(Index count) override;
+ Result OnExport(Index index,
+ ExternalKind kind,
+ Index item_index,
+ std::string_view name) override;
+
+ Result OnStartFunction(Index func_index) override;
+ Result OnDataCount(Index count) override;
+
+ Result OnFunctionBodyCount(Index count) override;
+ Result BeginFunctionBody(Index index, Offset size) override;
+
+ Result OnElemSegmentCount(Index count) override;
+ Result BeginElemSegment(Index index,
+ Index table_index,
+ uint8_t flags) override;
+ Result OnElemSegmentElemType(Index index, Type elem_type) override;
+ Result OnElemSegmentElemExprCount(Index index, Index count) override;
+ Result OnElemSegmentElemExpr_RefNull(Index segment_index, Type type) override;
+ Result OnElemSegmentElemExpr_RefFunc(Index segment_index,
+ Index func_index) override;
+
+ void BeginInitExpr() { current_init_expr_.insts.clear(); }
+
+ Result BeginElemSegmentInitExpr(Index index) override {
+ reading_elem_init_expr_ = true;
+ BeginInitExpr();
+ return Result::Ok;
+ }
+
+ Result EndElemSegmentInitExpr(Index index) override { return EndInitExpr(); }
+
+ Result BeginDataSegmentInitExpr(Index index) override {
+ reading_data_init_expr_ = true;
+ BeginInitExpr();
+ return Result::Ok;
+ }
+
+ Result EndDataSegmentInitExpr(Index index) override { return EndInitExpr(); }
+
+ Result BeginGlobalInitExpr(Index index) override {
+ reading_global_init_expr_ = true;
+ BeginInitExpr();
+ return Result::Ok;
+ }
+
+ Result EndGlobalInitExpr(Index index) override { return EndInitExpr(); }
+
+ Result OnDataSegmentCount(Index count) override;
+ Result BeginDataSegment(Index index,
+ Index memory_index,
+ uint8_t flags) override;
+ Result OnDataSegmentData(Index index,
+ const void* data,
+ Address size) override;
+
+ Result OnModuleName(std::string_view name) override;
+ Result OnFunctionName(Index function_index,
+ std::string_view function_name) override;
+ Result OnLocalName(Index function_index,
+ Index local_index,
+ std::string_view local_name) override;
+ Result OnNameEntry(NameSectionSubsection type,
+ Index index,
+ std::string_view name) override;
+
+ Result OnDylinkInfo(uint32_t mem_size,
+ uint32_t mem_align_log2,
+ uint32_t table_size,
+ uint32_t table_align_log2) override;
+ Result OnDylinkNeededCount(Index count) override;
+ Result OnDylinkNeeded(std::string_view so_name) override;
+ Result OnDylinkImportCount(Index count) override;
+ Result OnDylinkExportCount(Index count) override;
+ Result OnDylinkImport(std::string_view module,
+ std::string_view name,
+ uint32_t flags) override;
+ Result OnDylinkExport(std::string_view name, uint32_t flags) override;
+
+ Result OnRelocCount(Index count, Index section_index) override;
+ Result OnReloc(RelocType type,
+ Offset offset,
+ Index index,
+ uint32_t addend) override;
+
+ Result OnFeature(uint8_t prefix, std::string_view name) override;
+
+ Result OnSymbolCount(Index count) override;
+ Result OnDataSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index segment,
+ uint32_t offset,
+ uint32_t size) override;
+ Result OnFunctionSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index func_index) override;
+ Result OnGlobalSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index global_index) override;
+ Result OnSectionSymbol(Index index,
+ uint32_t flags,
+ Index section_index) override;
+ Result OnTagSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index tag_index) override;
+ Result OnTableSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index table_index) override;
+ Result OnSegmentInfoCount(Index count) override;
+ Result OnSegmentInfo(Index index,
+ std::string_view name,
+ Address alignment_log2,
+ uint32_t flags) override;
+ Result OnInitFunctionCount(Index count) override;
+ Result OnInitFunction(uint32_t priority, Index symbol_index) override;
+ Result OnComdatCount(Index count) override;
+ Result OnComdatBegin(std::string_view name,
+ uint32_t flags,
+ Index count) override;
+ Result OnComdatEntry(ComdatType kind, Index index) override;
+
+ Result OnTagCount(Index count) override;
+ Result OnTagType(Index index, Index sig_index) override;
+
+ Result OnOpcode(Opcode Opcode) override;
+ Result OnI32ConstExpr(uint32_t value) override;
+ Result OnI64ConstExpr(uint64_t value) override;
+ Result OnF32ConstExpr(uint32_t value) override;
+ Result OnF64ConstExpr(uint64_t value) override;
+ Result OnGlobalGetExpr(Index global_index) override;
+ Result OnCodeMetadataCount(Index function_index, Index count) override;
+ Result OnCodeMetadata(Offset code_offset,
+ const void* data,
+ Address size) override;
+
+ private:
+ Result EndInitExpr();
+ bool ShouldPrintDetails();
+ void PrintDetails(const char* fmt, ...);
+ Result PrintSymbolFlags(uint32_t flags);
+ Result PrintSegmentFlags(uint32_t flags);
+ void PrintInitExpr(const InitExpr& expr, bool as_unsigned = false);
+ Result OnCount(Index count);
+
+ std::unique_ptr<FileStream> out_stream_;
+ Index elem_index_ = 0;
+ Index table_index_ = 0;
+ Index next_data_reloc_ = 0;
+ bool reading_elem_init_expr_ = false;
+ bool reading_data_init_expr_ = false;
+ bool reading_global_init_expr_ = false;
+ InitExpr current_init_expr_;
+ uint8_t data_flags_ = 0;
+ uint8_t elem_flags_ = 0;
+ Index data_mem_index_ = 0;
+ uint64_t data_offset_ = 0;
+ uint64_t elem_offset_ = 0;
+
+ bool ReadingInitExpr() {
+ return reading_elem_init_expr_ || reading_data_init_expr_ ||
+ reading_global_init_expr_;
+ }
+};
+
+BinaryReaderObjdump::BinaryReaderObjdump(const uint8_t* data,
+ size_t size,
+ ObjdumpOptions* options,
+ ObjdumpState* objdump_state)
+ : BinaryReaderObjdumpBase(data, size, options, objdump_state),
+ out_stream_(FileStream::CreateStdout()) {}
+
+Result BinaryReaderObjdump::BeginCustomSection(Index section_index,
+ Offset size,
+ std::string_view section_name) {
+ PrintDetails(" - name: \"" PRIstringview "\"\n",
+ WABT_PRINTF_STRING_VIEW_ARG(section_name));
+ if (options_->mode == ObjdumpMode::Headers) {
+ printf("\"" PRIstringview "\"\n",
+ WABT_PRINTF_STRING_VIEW_ARG(section_name));
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::BeginSection(Index section_index,
+ BinarySection section_code,
+ Offset size) {
+ BinaryReaderObjdumpBase::BeginSection(section_index, section_code, size);
+
+ // |section_name| and |match_name| are identical for known sections. For
+ // custom sections, |section_name| is "Custom", but |match_name| is the name
+ // of the custom section.
+ const char* section_name = wabt::GetSectionName(section_code);
+ std::string match_name(GetSectionName(section_index));
+
+ bool section_match = !options_->section_name ||
+ !strcasecmp(options_->section_name, match_name.c_str());
+ if (section_match) {
+ section_found_ = true;
+ }
+
+ switch (options_->mode) {
+ case ObjdumpMode::Headers:
+ printf("%9s start=%#010" PRIzx " end=%#010" PRIzx " (size=%#010" PRIoffset
+ ") ",
+ section_name, state->offset, state->offset + size, size);
+ break;
+ case ObjdumpMode::Details:
+ if (section_match) {
+ printf("%s", section_name);
+ // All known section types except the Start and DataCount sections have
+ // a count in which case this line gets completed in OnCount().
+ if (section_code == BinarySection::Start ||
+ section_code == BinarySection::DataCount ||
+ section_code == BinarySection::Custom) {
+ printf(":\n");
+ }
+ print_details_ = true;
+ } else {
+ print_details_ = false;
+ }
+ break;
+ case ObjdumpMode::RawData:
+ if (section_match) {
+ printf("\nContents of section %s:\n", section_name);
+ out_stream_->WriteMemoryDump(data_ + state->offset, size, state->offset,
+ PrintChars::Yes);
+ }
+ break;
+ case ObjdumpMode::Prepass:
+ case ObjdumpMode::Disassemble:
+ break;
+ }
+ return Result::Ok;
+}
+
+bool BinaryReaderObjdump::ShouldPrintDetails() {
+ if (options_->mode != ObjdumpMode::Details) {
+ return false;
+ }
+ return print_details_;
+}
+
+void WABT_PRINTF_FORMAT(2, 3) BinaryReaderObjdump::PrintDetails(const char* fmt,
+ ...) {
+ if (!ShouldPrintDetails()) {
+ return;
+ }
+ va_list args;
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+}
+
+Result BinaryReaderObjdump::OnCount(Index count) {
+ if (options_->mode == ObjdumpMode::Headers) {
+ printf("count: %" PRIindex "\n", count);
+ } else if (options_->mode == ObjdumpMode::Details && print_details_) {
+ printf("[%" PRIindex "]:\n", count);
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::EndModule() {
+ if (options_->section_name && !section_found_) {
+ err_stream_->Writef("Section not found: %s\n", options_->section_name);
+ return Result::Error;
+ }
+
+ if (options_->relocs && ShouldPrintDetails()) {
+ if (next_data_reloc_ != objdump_state_->data_relocations.size()) {
+ err_stream_->Writef("Data reloctions outside of segments!:\n");
+ for (size_t i = next_data_reloc_;
+ i < objdump_state_->data_relocations.size(); i++) {
+ const Reloc& reloc = objdump_state_->data_relocations[i];
+ PrintRelocation(reloc, reloc.offset);
+ }
+
+ return Result::Error;
+ }
+ }
+
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnTypeCount(Index count) {
+ return OnCount(count);
+}
+
+Result BinaryReaderObjdump::OnFuncType(Index index,
+ Index param_count,
+ Type* param_types,
+ Index result_count,
+ Type* result_types) {
+ if (!ShouldPrintDetails()) {
+ return Result::Ok;
+ }
+ printf(" - type[%" PRIindex "] (", index);
+ for (Index i = 0; i < param_count; i++) {
+ if (i != 0) {
+ printf(", ");
+ }
+ printf("%s", param_types[i].GetName().c_str());
+ }
+ printf(") -> ");
+ switch (result_count) {
+ case 0:
+ printf("nil");
+ break;
+ case 1:
+ printf("%s", result_types[0].GetName().c_str());
+ break;
+ default:
+ printf("(");
+ for (Index i = 0; i < result_count; i++) {
+ if (i != 0) {
+ printf(", ");
+ }
+ printf("%s", result_types[i].GetName().c_str());
+ }
+ printf(")");
+ break;
+ }
+ printf("\n");
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnStructType(Index index,
+ Index field_count,
+ TypeMut* fields) {
+ if (!ShouldPrintDetails()) {
+ return Result::Ok;
+ }
+ printf(" - type[%" PRIindex "] (struct", index);
+ for (Index i = 0; i < field_count; i++) {
+ if (fields[i].mutable_) {
+ printf(" (mut");
+ }
+ printf(" %s", fields[i].type.GetName().c_str());
+ if (fields[i].mutable_) {
+ printf(")");
+ }
+ }
+ printf(")\n");
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnArrayType(Index index, TypeMut field) {
+ if (!ShouldPrintDetails()) {
+ return Result::Ok;
+ }
+ printf(" - type[%" PRIindex "] (array", index);
+ if (field.mutable_) {
+ printf(" (mut");
+ }
+ printf(" %s", field.type.GetName().c_str());
+ if (field.mutable_) {
+ printf(")");
+ }
+ printf(")\n");
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnFunctionCount(Index count) {
+ return OnCount(count);
+}
+
+Result BinaryReaderObjdump::OnFunction(Index index, Index sig_index) {
+ PrintDetails(" - func[%" PRIindex "] sig=%" PRIindex, index, sig_index);
+ auto name = GetFunctionName(index);
+ if (!name.empty()) {
+ PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ PrintDetails("\n");
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnFunctionBodyCount(Index count) {
+ return OnCount(count);
+}
+
+Result BinaryReaderObjdump::BeginFunctionBody(Index index, Offset size) {
+ PrintDetails(" - func[%" PRIindex "] size=%" PRIzd, index, size);
+ auto name = GetFunctionName(index);
+ if (!name.empty()) {
+ PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ PrintDetails("\n");
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnStartFunction(Index func_index) {
+ if (options_->mode == ObjdumpMode::Headers) {
+ printf("start: %" PRIindex "\n", func_index);
+ } else {
+ PrintDetails(" - start function: %" PRIindex, func_index);
+ auto name = GetFunctionName(func_index);
+ if (!name.empty()) {
+ PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ PrintDetails("\n");
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnDataCount(Index count) {
+ if (options_->mode == ObjdumpMode::Headers) {
+ printf("count: %" PRIindex "\n", count);
+ } else {
+ PrintDetails(" - data count: %" PRIindex "\n", count);
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnImportCount(Index count) {
+ return OnCount(count);
+}
+
+Result BinaryReaderObjdump::OnImportFunc(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index func_index,
+ Index sig_index) {
+ PrintDetails(" - func[%" PRIindex "] sig=%" PRIindex, func_index, sig_index);
+ auto name = GetFunctionName(func_index);
+ if (!name.empty()) {
+ PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ PrintDetails(" <- " PRIstringview "." PRIstringview "\n",
+ WABT_PRINTF_STRING_VIEW_ARG(module_name),
+ WABT_PRINTF_STRING_VIEW_ARG(field_name));
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnImportTable(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index table_index,
+ Type elem_type,
+ const Limits* elem_limits) {
+ PrintDetails(" - table[%" PRIindex "] type=%s initial=%" PRId64, table_index,
+ elem_type.GetName().c_str(), elem_limits->initial);
+ if (elem_limits->has_max) {
+ PrintDetails(" max=%" PRId64, elem_limits->max);
+ }
+ PrintDetails(" <- " PRIstringview "." PRIstringview "\n",
+ WABT_PRINTF_STRING_VIEW_ARG(module_name),
+ WABT_PRINTF_STRING_VIEW_ARG(field_name));
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnImportMemory(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index memory_index,
+ const Limits* page_limits) {
+ PrintDetails(" - memory[%" PRIindex "] pages: initial=%" PRId64, memory_index,
+ page_limits->initial);
+ if (page_limits->has_max) {
+ PrintDetails(" max=%" PRId64, page_limits->max);
+ }
+ if (page_limits->is_shared) {
+ PrintDetails(" shared");
+ }
+ if (page_limits->is_64) {
+ PrintDetails(" i64");
+ }
+ PrintDetails(" <- " PRIstringview "." PRIstringview "\n",
+ WABT_PRINTF_STRING_VIEW_ARG(module_name),
+ WABT_PRINTF_STRING_VIEW_ARG(field_name));
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnImportGlobal(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index global_index,
+ Type type,
+ bool mutable_) {
+ PrintDetails(" - global[%" PRIindex "] %s mutable=%d", global_index,
+ type.GetName().c_str(), mutable_);
+ PrintDetails(" <- " PRIstringview "." PRIstringview "\n",
+ WABT_PRINTF_STRING_VIEW_ARG(module_name),
+ WABT_PRINTF_STRING_VIEW_ARG(field_name));
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnImportTag(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index tag_index,
+ Index sig_index) {
+ PrintDetails(" - tag[%" PRIindex "] sig=%" PRIindex, tag_index, sig_index);
+ auto name = GetTagName(tag_index);
+ if (!name.empty()) {
+ PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ PrintDetails(" <- " PRIstringview "." PRIstringview "\n",
+ WABT_PRINTF_STRING_VIEW_ARG(module_name),
+ WABT_PRINTF_STRING_VIEW_ARG(field_name));
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnMemoryCount(Index count) {
+ return OnCount(count);
+}
+
+Result BinaryReaderObjdump::OnMemory(Index index, const Limits* page_limits) {
+ PrintDetails(" - memory[%" PRIindex "] pages: initial=%" PRId64, index,
+ page_limits->initial);
+ if (page_limits->has_max) {
+ PrintDetails(" max=%" PRId64, page_limits->max);
+ }
+ if (page_limits->is_shared) {
+ PrintDetails(" shared");
+ }
+ if (page_limits->is_64) {
+ PrintDetails(" i64");
+ }
+ PrintDetails("\n");
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnTableCount(Index count) {
+ return OnCount(count);
+}
+
+Result BinaryReaderObjdump::OnTable(Index index,
+ Type elem_type,
+ const Limits* elem_limits) {
+ PrintDetails(" - table[%" PRIindex "] type=%s initial=%" PRId64, index,
+ elem_type.GetName().c_str(), elem_limits->initial);
+ if (elem_limits->has_max) {
+ PrintDetails(" max=%" PRId64, elem_limits->max);
+ }
+ auto name = GetTableName(index);
+ if (!name.empty()) {
+ PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ PrintDetails("\n");
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnExportCount(Index count) {
+ return OnCount(count);
+}
+
+Result BinaryReaderObjdump::OnExport(Index index,
+ ExternalKind kind,
+ Index item_index,
+ std::string_view name) {
+ PrintDetails(" - %s[%" PRIindex "]", GetKindName(kind), item_index);
+ if (kind == ExternalKind::Func) {
+ auto name = GetFunctionName(item_index);
+ if (!name.empty()) {
+ PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ }
+
+ PrintDetails(" -> \"" PRIstringview "\"\n",
+ WABT_PRINTF_STRING_VIEW_ARG(name));
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnElemSegmentElemExpr_RefNull(Index segment_index,
+ Type type) {
+ PrintDetails(" - elem[%" PRIu64 "] = ref.null %s\n",
+ elem_offset_ + elem_index_, type.GetName().c_str());
+ elem_index_++;
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnElemSegmentElemExpr_RefFunc(Index segment_index,
+ Index func_index) {
+ PrintDetails(" - elem[%" PRIu64 "] = func[%" PRIindex "]",
+ elem_offset_ + elem_index_, func_index);
+ auto name = GetFunctionName(func_index);
+ if (!name.empty()) {
+ PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ PrintDetails("\n");
+ elem_index_++;
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnElemSegmentCount(Index count) {
+ return OnCount(count);
+}
+
+Result BinaryReaderObjdump::BeginElemSegment(Index index,
+ Index table_index,
+ uint8_t flags) {
+ table_index_ = table_index;
+ elem_index_ = 0;
+ elem_flags_ = flags;
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnElemSegmentElemType(Index index, Type elem_type) {
+ // TODO: Add support for this.
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnElemSegmentElemExprCount(Index index,
+ Index count) {
+ PrintDetails(" - segment[%" PRIindex "] flags=%d table=%" PRIindex
+ " count=%" PRIindex,
+ index, elem_flags_, table_index_, count);
+ if (elem_flags_ & SegPassive) {
+ PrintDetails("\n");
+ } else {
+ PrintInitExpr(current_init_expr_, /*as_unsigned=*/true);
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnGlobalCount(Index count) {
+ return OnCount(count);
+}
+
+Result BinaryReaderObjdump::BeginGlobal(Index index, Type type, bool mutable_) {
+ PrintDetails(" - global[%" PRIindex "] %s mutable=%d", index,
+ type.GetName().c_str(), mutable_);
+ std::string_view name = GetGlobalName(index);
+ if (!name.empty()) {
+ PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ return Result::Ok;
+}
+
+void BinaryReaderObjdump::PrintInitExpr(const InitExpr& expr,
+ bool as_unsigned) {
+ assert(expr.insts.size() > 0);
+
+ // We have two different way to print init expressions. One for
+ // extended expressions involving more than one instruction, and
+ // a short form for the more traditional single instruction form.
+ if (expr.insts.size() > 1) {
+ PrintDetails(" - init (");
+ bool first = true;
+ for (auto& inst : expr.insts) {
+ if (!first) {
+ PrintDetails(", ");
+ }
+ first = false;
+ PrintDetails("%s", inst.opcode.GetName());
+ switch (inst.opcode) {
+ case Opcode::I32Const:
+ PrintDetails(" %d", inst.imm.i32);
+ break;
+ case Opcode::I64Const:
+ PrintDetails(" %" PRId64, inst.imm.i64);
+ break;
+ case Opcode::F32Const: {
+ char buffer[WABT_MAX_FLOAT_HEX];
+ WriteFloatHex(buffer, sizeof(buffer), inst.imm.f32);
+ PrintDetails(" %s\n", buffer);
+ break;
+ }
+ case Opcode::F64Const: {
+ char buffer[WABT_MAX_DOUBLE_HEX];
+ WriteDoubleHex(buffer, sizeof(buffer), inst.imm.f64);
+ PrintDetails(" %s\n", buffer);
+ break;
+ }
+ case Opcode::GlobalGet: {
+ PrintDetails(" %" PRIindex, inst.imm.index);
+ std::string_view name = GetGlobalName(inst.imm.index);
+ if (!name.empty()) {
+ PrintDetails(" <" PRIstringview ">",
+ WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ PrintDetails(")\n");
+ return;
+ }
+
+ switch (expr.type) {
+ case InitExprType::I32:
+ if (as_unsigned) {
+ PrintDetails(" - init i32=%u\n", expr.insts[0].imm.i32);
+ } else {
+ PrintDetails(" - init i32=%d\n", expr.insts[0].imm.i32);
+ }
+ break;
+ case InitExprType::I64:
+ if (as_unsigned) {
+ PrintDetails(" - init i64=%" PRIu64 "\n", expr.insts[0].imm.i64);
+ } else {
+ PrintDetails(" - init i64=%" PRId64 "\n", expr.insts[0].imm.i64);
+ }
+ break;
+ case InitExprType::F64: {
+ char buffer[WABT_MAX_DOUBLE_HEX];
+ WriteDoubleHex(buffer, sizeof(buffer), expr.insts[0].imm.f64);
+ PrintDetails(" - init f64=%s\n", buffer);
+ break;
+ }
+ case InitExprType::F32: {
+ char buffer[WABT_MAX_FLOAT_HEX];
+ WriteFloatHex(buffer, sizeof(buffer), expr.insts[0].imm.f32);
+ PrintDetails(" - init f32=%s\n", buffer);
+ break;
+ }
+ case InitExprType::V128: {
+ PrintDetails(
+ " - init v128=0x%08x 0x%08x 0x%08x 0x%08x \n",
+ expr.insts[0].imm.v128_v.u32(0), expr.insts[0].imm.v128_v.u32(1),
+ expr.insts[0].imm.v128_v.u32(2), expr.insts[0].imm.v128_v.u32(3));
+ break;
+ }
+ case InitExprType::Global: {
+ PrintDetails(" - init global=%" PRIindex, expr.insts[0].imm.index);
+ std::string_view name = GetGlobalName(expr.insts[0].imm.index);
+ if (!name.empty()) {
+ PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ PrintDetails("\n");
+ break;
+ }
+ case InitExprType::FuncRef: {
+ PrintDetails(" - init ref.func:%" PRIindex, expr.insts[0].imm.index);
+ std::string_view name = GetFunctionName(expr.insts[0].imm.index);
+ if (!name.empty()) {
+ PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ PrintDetails("\n");
+ break;
+ }
+ case InitExprType::NullRef:
+ PrintDetails(" - init null\n");
+ break;
+ break;
+ }
+}
+
+static void InitExprToConstOffset(const InitExpr& expr, uint64_t* out_offset) {
+ if (expr.insts.size() == 1) {
+ switch (expr.type) {
+ case InitExprType::I32:
+ *out_offset = expr.insts[0].imm.i32;
+ break;
+ case InitExprType::I64:
+ *out_offset = expr.insts[0].imm.i64;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+Result BinaryReaderObjdump::EndInitExpr() {
+ if (reading_data_init_expr_) {
+ reading_data_init_expr_ = false;
+ InitExprToConstOffset(current_init_expr_, &data_offset_);
+ } else if (reading_elem_init_expr_) {
+ reading_elem_init_expr_ = false;
+ InitExprToConstOffset(current_init_expr_, &elem_offset_);
+ } else if (reading_global_init_expr_) {
+ reading_global_init_expr_ = false;
+ PrintInitExpr(current_init_expr_);
+ } else {
+ WABT_UNREACHABLE;
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnI32ConstExpr(uint32_t value) {
+ if (ReadingInitExpr()) {
+ current_init_expr_.type = InitExprType::I32;
+ current_init_expr_.insts.back().imm.i32 = value;
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnI64ConstExpr(uint64_t value) {
+ if (ReadingInitExpr()) {
+ current_init_expr_.type = InitExprType::I64;
+ current_init_expr_.insts.back().imm.i64 = value;
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnF32ConstExpr(uint32_t value) {
+ if (ReadingInitExpr()) {
+ current_init_expr_.type = InitExprType::F32;
+ current_init_expr_.insts.back().imm.f32 = value;
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnF64ConstExpr(uint64_t value) {
+ if (ReadingInitExpr()) {
+ current_init_expr_.type = InitExprType::F64;
+ current_init_expr_.insts.back().imm.f64 = value;
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnOpcode(Opcode opcode) {
+ BinaryReaderObjdumpBase::OnOpcode(opcode);
+ if (ReadingInitExpr() && opcode != Opcode::End) {
+ InitInst i;
+ i.opcode = current_opcode;
+ current_init_expr_.insts.push_back(i);
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnGlobalGetExpr(Index global_index) {
+ if (ReadingInitExpr()) {
+ current_init_expr_.type = InitExprType::Global;
+ current_init_expr_.insts.back().imm.index = global_index;
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnModuleName(std::string_view name) {
+ PrintDetails(" - module <" PRIstringview ">\n",
+ WABT_PRINTF_STRING_VIEW_ARG(name));
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnFunctionName(Index index, std::string_view name) {
+ PrintDetails(" - func[%" PRIindex "] <" PRIstringview ">\n", index,
+ WABT_PRINTF_STRING_VIEW_ARG(name));
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnNameEntry(NameSectionSubsection type,
+ Index index,
+ std::string_view name) {
+ PrintDetails(" - %s[%" PRIindex "] <" PRIstringview ">\n",
+ GetNameSectionSubsectionName(type), index,
+ WABT_PRINTF_STRING_VIEW_ARG(name));
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnLocalName(Index func_index,
+ Index local_index,
+ std::string_view name) {
+ if (!name.empty()) {
+ PrintDetails(" - func[%" PRIindex "] local[%" PRIindex "] <" PRIstringview
+ ">\n",
+ func_index, local_index, WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnDataSegmentCount(Index count) {
+ return OnCount(count);
+}
+
+Result BinaryReaderObjdump::BeginDataSegment(Index index,
+ Index memory_index,
+ uint8_t flags) {
+ data_mem_index_ = memory_index;
+ data_flags_ = flags;
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnDataSegmentData(Index index,
+ const void* src_data,
+ Address size) {
+ if (!ShouldPrintDetails()) {
+ return Result::Ok;
+ }
+
+ PrintDetails(" - segment[%" PRIindex "]", index);
+ auto name = GetSegmentName(index);
+ if (!name.empty()) {
+ PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ if (data_flags_ & SegPassive) {
+ PrintDetails(" passive");
+ } else {
+ PrintDetails(" memory=%" PRIindex, data_mem_index_);
+ }
+ PrintDetails(" size=%" PRIaddress, size);
+ if (data_flags_ & SegPassive) {
+ PrintDetails("\n");
+ } else {
+ PrintInitExpr(current_init_expr_, /*as_unsigned=*/true);
+ }
+
+ out_stream_->WriteMemoryDump(src_data, size, data_offset_, PrintChars::Yes,
+ " - ");
+
+ // Print relocations from this segment.
+ if (!options_->relocs) {
+ return Result::Ok;
+ }
+
+ Offset data_start = GetSectionStart(BinarySection::Data);
+ Offset segment_start = state->offset - size;
+ Offset segment_offset = segment_start - data_start;
+ while (next_data_reloc_ < objdump_state_->data_relocations.size()) {
+ const Reloc& reloc = objdump_state_->data_relocations[next_data_reloc_];
+ Offset abs_offset = data_start + reloc.offset;
+ if (abs_offset > state->offset) {
+ break;
+ }
+ PrintRelocation(reloc, reloc.offset - segment_offset + data_offset_);
+ next_data_reloc_++;
+ }
+
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnDylinkInfo(uint32_t mem_size,
+ uint32_t mem_align_log2,
+ uint32_t table_size,
+ uint32_t table_align_log2) {
+ PrintDetails(" - mem_size : %u\n", mem_size);
+ PrintDetails(" - mem_p2align : %u\n", mem_align_log2);
+ PrintDetails(" - table_size : %u\n", table_size);
+ PrintDetails(" - table_p2align: %u\n", table_align_log2);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnDylinkNeededCount(Index count) {
+ if (count) {
+ PrintDetails(" - needed_dynlibs[%u]:\n", count);
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnDylinkImportCount(Index count) {
+ PrintDetails(" - imports[%u]:\n", count);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnDylinkExportCount(Index count) {
+ PrintDetails(" - exports[%u]:\n", count);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnDylinkExport(std::string_view name,
+ uint32_t flags) {
+ PrintDetails(" - " PRIstringview, WABT_PRINTF_STRING_VIEW_ARG(name));
+ return PrintSymbolFlags(flags);
+}
+
+Result BinaryReaderObjdump::OnDylinkImport(std::string_view module,
+ std::string_view name,
+ uint32_t flags) {
+ PrintDetails(" - " PRIstringview "." PRIstringview,
+ WABT_PRINTF_STRING_VIEW_ARG(module),
+ WABT_PRINTF_STRING_VIEW_ARG(name));
+ return PrintSymbolFlags(flags);
+}
+
+Result BinaryReaderObjdump::OnDylinkNeeded(std::string_view so_name) {
+ PrintDetails(" - " PRIstringview "\n", WABT_PRINTF_STRING_VIEW_ARG(so_name));
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnRelocCount(Index count, Index section_index) {
+ BinaryReaderObjdumpBase::OnRelocCount(count, section_index);
+ PrintDetails(" - relocations for section: %d (" PRIstringview ") [%d]\n",
+ section_index,
+ WABT_PRINTF_STRING_VIEW_ARG(GetSectionName(section_index)),
+ count);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnReloc(RelocType type,
+ Offset offset,
+ Index index,
+ uint32_t addend) {
+ Offset total_offset = GetSectionStart(reloc_section_) + offset;
+ PrintDetails(" - %-18s offset=%#08" PRIoffset "(file=%#08" PRIoffset ") ",
+ GetRelocTypeName(type), offset, total_offset);
+ if (type == RelocType::TypeIndexLEB) {
+ PrintDetails("type=%" PRIindex, index);
+ } else {
+ PrintDetails("symbol=%" PRIindex " <" PRIstringview ">", index,
+ WABT_PRINTF_STRING_VIEW_ARG(GetSymbolName(index)));
+ }
+
+ if (addend) {
+ int32_t signed_addend = static_cast<int32_t>(addend);
+ if (signed_addend < 0) {
+ PrintDetails("-");
+ signed_addend = -signed_addend;
+ } else {
+ PrintDetails("+");
+ }
+ PrintDetails("%#x", signed_addend);
+ }
+ PrintDetails("\n");
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnFeature(uint8_t prefix, std::string_view name) {
+ PrintDetails(" - [%c] " PRIstringview "\n", prefix,
+ WABT_PRINTF_STRING_VIEW_ARG(name));
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnSymbolCount(Index count) {
+ PrintDetails(" - symbol table [count=%d]\n", count);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::PrintSymbolFlags(uint32_t flags) {
+ if (flags > WABT_SYMBOL_FLAG_MAX) {
+ err_stream_->Writef("Unknown symbols flags: %x\n", flags);
+ return Result::Error;
+ }
+
+ const char* binding_name = nullptr;
+ SymbolBinding binding =
+ static_cast<SymbolBinding>(flags & WABT_SYMBOL_MASK_BINDING);
+ switch (binding) {
+ case SymbolBinding::Global:
+ binding_name = "global";
+ break;
+ case SymbolBinding::Local:
+ binding_name = "local";
+ break;
+ case SymbolBinding::Weak:
+ binding_name = "weak";
+ break;
+ }
+ flags &= ~WABT_SYMBOL_MASK_BINDING;
+
+ const char* vis_name = nullptr;
+ SymbolVisibility vis =
+ static_cast<SymbolVisibility>(flags & WABT_SYMBOL_MASK_VISIBILITY);
+ switch (vis) {
+ case SymbolVisibility::Hidden:
+ vis_name = "hidden";
+ break;
+ case SymbolVisibility::Default:
+ vis_name = "default";
+ break;
+ }
+ flags &= ~WABT_SYMBOL_MASK_VISIBILITY;
+
+ PrintDetails(" [");
+ if (flags & WABT_SYMBOL_FLAG_UNDEFINED) {
+ PrintDetails(" undefined");
+ flags &= ~WABT_SYMBOL_FLAG_UNDEFINED;
+ }
+ if (flags & WABT_SYMBOL_FLAG_EXPORTED) {
+ PrintDetails(" exported");
+ flags &= ~WABT_SYMBOL_FLAG_EXPORTED;
+ }
+ if (flags & WABT_SYMBOL_FLAG_EXPLICIT_NAME) {
+ PrintDetails(" explicit_name");
+ flags &= ~WABT_SYMBOL_FLAG_EXPLICIT_NAME;
+ }
+ if (flags & WABT_SYMBOL_FLAG_NO_STRIP) {
+ PrintDetails(" no_strip");
+ flags &= ~WABT_SYMBOL_FLAG_NO_STRIP;
+ }
+ if (flags & WABT_SYMBOL_FLAG_TLS) {
+ PrintDetails(" tls");
+ flags &= ~WABT_SYMBOL_FLAG_TLS;
+ }
+ if (flags != 0) {
+ PrintDetails(" unknown_flags=%#x", flags);
+ }
+ PrintDetails(" binding=%s vis=%s ]\n", binding_name, vis_name);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::PrintSegmentFlags(uint32_t flags) {
+ if (flags > WABT_SYMBOL_FLAG_MAX) {
+ err_stream_->Writef("Unknown symbols flags: %x\n", flags);
+ return Result::Error;
+ }
+ PrintDetails(" [");
+ if (flags & WABT_SEGMENT_FLAG_STRINGS) {
+ PrintDetails(" STRINGS");
+ flags &= ~WABT_SEGMENT_FLAG_STRINGS;
+ }
+ if (flags & WABT_SEGMENT_FLAG_TLS) {
+ PrintDetails(" TLS");
+ flags &= ~WABT_SEGMENT_FLAG_TLS;
+ }
+ if (flags != 0) {
+ PrintDetails(" unknown_flags=%#x", flags);
+ }
+ PrintDetails(" ]\n");
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnDataSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index segment,
+ uint32_t offset,
+ uint32_t size) {
+ PrintDetails(" - %d: D <" PRIstringview ">", index,
+ WABT_PRINTF_STRING_VIEW_ARG(name));
+ if (!(flags & WABT_SYMBOL_FLAG_UNDEFINED))
+ PrintDetails(" segment=%" PRIindex " offset=%d size=%d", segment, offset,
+ size);
+ return PrintSymbolFlags(flags);
+}
+
+Result BinaryReaderObjdump::OnFunctionSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index func_index) {
+ if (name.empty()) {
+ name = GetFunctionName(func_index);
+ }
+ PrintDetails(" - %d: F <" PRIstringview "> func=%" PRIindex, index,
+ WABT_PRINTF_STRING_VIEW_ARG(name), func_index);
+ return PrintSymbolFlags(flags);
+}
+
+Result BinaryReaderObjdump::OnGlobalSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index global_index) {
+ if (name.empty()) {
+ name = GetGlobalName(global_index);
+ }
+ PrintDetails(" - %d: G <" PRIstringview "> global=%" PRIindex, index,
+ WABT_PRINTF_STRING_VIEW_ARG(name), global_index);
+ return PrintSymbolFlags(flags);
+}
+
+Result BinaryReaderObjdump::OnSectionSymbol(Index index,
+ uint32_t flags,
+ Index section_index) {
+ auto sym_name = GetSectionName(section_index);
+ assert(!sym_name.empty());
+ PrintDetails(" - %d: S <" PRIstringview "> section=%" PRIindex, index,
+ WABT_PRINTF_STRING_VIEW_ARG(sym_name), section_index);
+ return PrintSymbolFlags(flags);
+}
+
+Result BinaryReaderObjdump::OnTagSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index tag_index) {
+ if (name.empty()) {
+ name = GetTagName(tag_index);
+ }
+ PrintDetails(" - %d: E <" PRIstringview "> tag=%" PRIindex, index,
+ WABT_PRINTF_STRING_VIEW_ARG(name), tag_index);
+ return PrintSymbolFlags(flags);
+}
+
+Result BinaryReaderObjdump::OnTableSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index table_index) {
+ if (name.empty()) {
+ name = GetTableName(table_index);
+ }
+ PrintDetails(" - %d: T <" PRIstringview "> table=%" PRIindex, index,
+ WABT_PRINTF_STRING_VIEW_ARG(name), table_index);
+ return PrintSymbolFlags(flags);
+}
+
+Result BinaryReaderObjdump::OnSegmentInfoCount(Index count) {
+ PrintDetails(" - segment info [count=%d]\n", count);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnSegmentInfo(Index index,
+ std::string_view name,
+ Address alignment_log2,
+ uint32_t flags) {
+ PrintDetails(" - %d: " PRIstringview " p2align=%" PRIaddress, index,
+ WABT_PRINTF_STRING_VIEW_ARG(name), alignment_log2);
+ return PrintSegmentFlags(flags);
+}
+
+Result BinaryReaderObjdump::OnInitFunctionCount(Index count) {
+ PrintDetails(" - init functions [count=%d]\n", count);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnInitFunction(uint32_t priority,
+ Index symbol_index) {
+ PrintDetails(" - %d: priority=%d", symbol_index, priority);
+ auto name = GetSymbolName(symbol_index);
+ if (!name.empty()) {
+ PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ PrintDetails("\n");
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnComdatCount(Index count) {
+ PrintDetails(" - comdat groups [count=%d]\n", count);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnComdatBegin(std::string_view name,
+ uint32_t flags,
+ Index count) {
+ PrintDetails(" - " PRIstringview ": [count=%d]\n",
+ WABT_PRINTF_STRING_VIEW_ARG(name), count);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnComdatEntry(ComdatType kind, Index index) {
+ switch (kind) {
+ case ComdatType::Data: {
+ PrintDetails(" - segment[%" PRIindex "]", index);
+ auto name = GetSegmentName(index);
+ if (!name.empty()) {
+ PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ break;
+ }
+ case ComdatType::Function: {
+ PrintDetails(" - func[%" PRIindex "]", index);
+ auto name = GetFunctionName(index);
+ if (!name.empty()) {
+ PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ break;
+ }
+ }
+ PrintDetails("\n");
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnTagCount(Index count) {
+ return OnCount(count);
+}
+
+Result BinaryReaderObjdump::OnTagType(Index index, Index sig_index) {
+ if (!ShouldPrintDetails()) {
+ return Result::Ok;
+ }
+ printf(" - tag[%" PRIindex "] sig=%" PRIindex "\n", index, sig_index);
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdump::OnCodeMetadataCount(Index function_index,
+ Index count) {
+ if (!ShouldPrintDetails()) {
+ return Result::Ok;
+ }
+ printf(" - func[%" PRIindex "]", function_index);
+ auto name = GetFunctionName(function_index);
+ if (!name.empty()) {
+ printf(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
+ }
+ printf(":\n");
+ return Result::Ok;
+}
+Result BinaryReaderObjdump::OnCodeMetadata(Offset code_offset,
+ const void* data,
+ Address size) {
+ if (!ShouldPrintDetails()) {
+ return Result::Ok;
+ }
+ printf(" - meta[%" PRIzx "]:\n", code_offset);
+
+ out_stream_->WriteMemoryDump(data, size, 0, PrintChars::Yes, " - ");
+ return Result::Ok;
+}
+
+} // end anonymous namespace
+
+std::string_view ObjdumpNames::Get(Index index) const {
+ auto iter = names.find(index);
+ if (iter == names.end())
+ return std::string_view();
+ return iter->second;
+}
+
+void ObjdumpNames::Set(Index index, std::string_view name) {
+ names[index] = std::string(name);
+}
+
+std::string_view ObjdumpLocalNames::Get(Index function_index,
+ Index local_index) const {
+ auto iter = names.find(std::pair<Index, Index>(function_index, local_index));
+ if (iter == names.end())
+ return std::string_view();
+ return iter->second;
+}
+
+void ObjdumpLocalNames::Set(Index function_index,
+ Index local_index,
+ std::string_view name) {
+ names[std::pair<Index, Index>(function_index, local_index)] =
+ std::string(name);
+}
+
+Result ReadBinaryObjdump(const uint8_t* data,
+ size_t size,
+ ObjdumpOptions* options,
+ ObjdumpState* state) {
+ Features features;
+ features.EnableAll();
+ const bool kReadDebugNames = true;
+ const bool kStopOnFirstError = false;
+ const bool kFailOnCustomSectionError = false;
+ ReadBinaryOptions read_options(features, options->log_stream, kReadDebugNames,
+ kStopOnFirstError, kFailOnCustomSectionError);
+
+ switch (options->mode) {
+ case ObjdumpMode::Prepass: {
+ read_options.skip_function_bodies = true;
+ BinaryReaderObjdumpPrepass reader(data, size, options, state);
+ return ReadBinary(data, size, &reader, read_options);
+ }
+ case ObjdumpMode::Disassemble: {
+ BinaryReaderObjdumpDisassemble reader(data, size, options, state);
+ return ReadBinary(data, size, &reader, read_options);
+ }
+ default: {
+ read_options.skip_function_bodies = true;
+ BinaryReaderObjdump reader(data, size, options, state);
+ return ReadBinary(data, size, &reader, read_options);
+ }
+ }
+}
+
+} // namespace wabt