blob: b11ad42e57e3b7d5c3579c73eb880a204ac7e919 [file] [log] [blame]
/*
* 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 "binary-reader-objdump.h"
#include <assert.h>
#include <inttypes.h>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include "binary-reader-nop.h"
#include "literal.h"
namespace wabt {
namespace {
typedef std::vector<uint32_t> Uint32Vector;
class BinaryReaderObjdumpBase : public BinaryReaderNop {
public:
BinaryReaderObjdumpBase(const uint8_t* data,
size_t size,
ObjdumpOptions* options);
virtual Result BeginModule(uint32_t version);
virtual Result BeginSection(BinarySection section_type, uint32_t size);
virtual Result OnRelocCount(uint32_t count,
BinarySection section_code,
StringSlice section_name);
protected:
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];
bool section_found = false;
};
BinaryReaderObjdumpBase::BinaryReaderObjdumpBase(const uint8_t* data,
size_t size,
ObjdumpOptions* options)
: options(options),
data(data),
size(size) {
WABT_ZERO_MEMORY(section_starts);
}
Result BinaryReaderObjdumpBase::BeginSection(BinarySection section_code,
uint32_t size) {
section_starts[static_cast<size_t>(section_code)] = state->offset;
return Result::Ok;
}
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: {
const char* last_slash = strrchr(options->infile, '/');
const char* last_backslash = strrchr(options->infile, '\\');
const char* basename;
if (last_slash && last_backslash) {
basename = std::max(last_slash, last_backslash) + 1;
} else if (last_slash) {
basename = last_slash + 1;
} else if (last_backslash) {
basename = last_backslash + 1;
} else {
basename = options->infile;
}
printf("%s:\tfile format wasm %#x\n", basename, version);
break;
}
case ObjdumpMode::RawData:
break;
}
return Result::Ok;
}
Result BinaryReaderObjdumpBase::OnRelocCount(uint32_t count,
BinarySection section_code,
StringSlice section_name) {
reloc_section = section_code;
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,
uint32_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) {
options->function_names.resize(index + 1);
options->function_names[index] = string_slice_to_string(name);
return Result::Ok;
}
Result BinaryReaderObjdumpPrepass::OnReloc(RelocType type,
uint32_t offset,
uint32_t index,
uint32_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 BinaryReaderObjdumpDisassemble : public BinaryReaderObjdumpBase {
public:
BinaryReaderObjdumpDisassemble(const uint8_t* data,
size_t size,
ObjdumpOptions* options);
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();
private:
void LogOpcode(const uint8_t* data, size_t data_size, const char* fmt, ...);
Opcode current_opcode = Opcode::Unreachable;
size_t current_opcode_offset = 0;
size_t last_opcode_end = 0;
int indent_level = 0;
uint32_t next_reloc = 0;
};
BinaryReaderObjdumpDisassemble::BinaryReaderObjdumpDisassemble(
const uint8_t* data,
size_t size,
ObjdumpOptions* options)
: BinaryReaderObjdumpBase(data, size, options) {}
Result BinaryReaderObjdumpDisassemble::OnOpcode(Opcode opcode) {
if (options->debug) {
const char* opcode_name = get_opcode_name(opcode);
printf("on_opcode: %#" PRIzx ": %s\n", state->offset, opcode_name);
}
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",
state->offset, last_opcode_end + 1, data[last_opcode_end],
opcode_name);
return Result::Error;
}
}
current_opcode_offset = state->offset;
current_opcode = opcode;
return Result::Ok;
}
#define IMMEDIATE_OCTET_COUNT 9
void BinaryReaderObjdumpDisassemble::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>(current_opcode));
for (size_t i = 0; i < data_size && i < IMMEDIATE_OCTET_COUNT;
i++, offset++) {
printf(" %02x", data[offset]);
}
for (size_t i = data_size + 1; i < IMMEDIATE_OCTET_COUNT; i++) {
printf(" ");
}
printf(" | ");
// Print disassemble
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(current_opcode);
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 = current_opcode_offset + data_size;
if (options->relocs) {
if (next_reloc < options->code_relocations.size()) {
Reloc* reloc = &options->code_relocations[next_reloc];
size_t code_start =
section_starts[static_cast<size_t>(BinarySection::Code)];
size_t abs_offset = code_start + reloc->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) {
case RelocType::MemoryAddressLEB:
case RelocType::MemoryAddressSLEB:
case RelocType::MemoryAddressI32:
printf(" + %d", reloc->addend);
break;
default:
break;
}
printf("\n");
next_reloc++;
}
}
}
}
Result BinaryReaderObjdumpDisassemble::OnOpcodeBare() {
LogOpcode(data, 0, nullptr);
return Result::Ok;
}
Result BinaryReaderObjdumpDisassemble::OnOpcodeUint32(uint32_t value) {
size_t immediate_len = state->offset - current_opcode_offset;
LogOpcode(data, immediate_len, "%#x", value);
return Result::Ok;
}
Result BinaryReaderObjdumpDisassemble::OnOpcodeUint32Uint32(uint32_t value,
uint32_t value2) {
size_t immediate_len = state->offset - current_opcode_offset;
LogOpcode(data, immediate_len, "%lu %lu", value, value2);
return Result::Ok;
}
Result BinaryReaderObjdumpDisassemble::OnOpcodeUint64(uint64_t value) {
size_t immediate_len = state->offset - current_opcode_offset;
LogOpcode(data, immediate_len, "%d", value);
return Result::Ok;
}
Result BinaryReaderObjdumpDisassemble::OnOpcodeF32(uint32_t value) {
size_t immediate_len = state->offset - current_opcode_offset;
char buffer[WABT_MAX_FLOAT_HEX];
write_float_hex(buffer, sizeof(buffer), value);
LogOpcode(data, immediate_len, buffer);
return Result::Ok;
}
Result BinaryReaderObjdumpDisassemble::OnOpcodeF64(uint64_t value) {
size_t immediate_len = state->offset - current_opcode_offset;
char buffer[WABT_MAX_DOUBLE_HEX];
write_double_hex(buffer, sizeof(buffer), value);
LogOpcode(data, immediate_len, buffer);
return Result::Ok;
}
Result BinaryReaderObjdumpDisassemble::OnBrTableExpr(
uint32_t num_targets,
uint32_t* target_depths,
uint32_t default_target_depth) {
size_t immediate_len = state->offset - current_opcode_offset;
/* TODO(sbc): Print targets */
LogOpcode(data, immediate_len, nullptr);
return Result::Ok;
}
Result BinaryReaderObjdumpDisassemble::OnEndFunc() {
LogOpcode(nullptr, 0, nullptr);
return Result::Ok;
}
Result BinaryReaderObjdumpDisassemble::OnEndExpr() {
indent_level--;
assert(indent_level >= 0);
LogOpcode(nullptr, 0, nullptr);
return Result::Ok;
}
Result BinaryReaderObjdumpDisassemble::BeginFunctionBody(uint32_t index) {
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", state->offset, index);
last_opcode_end = 0;
return Result::Ok;
}
const char* type_name(Type type) {
switch (type) {
case Type::I32:
return "i32";
case Type::I64:
return "i64";
case Type::F32:
return "f32";
case Type::F64:
return "f64";
default:
assert(0);
return "INVALID TYPE";
}
}
Result BinaryReaderObjdumpDisassemble::OnOpcodeBlockSig(uint32_t num_types,
Type* sig_types) {
if (num_types)
LogOpcode(data, 1, "%s", type_name(*sig_types));
else
LogOpcode(data, 1, nullptr);
indent_level++;
return Result::Ok;
}
class BinaryReaderObjdump : public BinaryReaderObjdumpBase {
public:
BinaryReaderObjdump(const uint8_t* data,
size_t size,
ObjdumpOptions* options);
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 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);
virtual Result OnRelocCount(uint32_t count,
BinarySection section_code,
StringSlice section_name);
virtual Result OnReloc(RelocType type,
uint32_t offset,
uint32_t index,
uint32_t addend);
private:
bool ShouldPrintDetails();
void PrintDetails(const char* fmt, ...);
Result OnCount(uint32_t count);
std::unique_ptr<FileStream> out_stream;
};
BinaryReaderObjdump::BinaryReaderObjdump(const uint8_t* data,
size_t size,
ObjdumpOptions* options)
: BinaryReaderObjdumpBase(data, size, options),
out_stream(FileStream::CreateStdout()) {}
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;
}
Result BinaryReaderObjdump::BeginSection(BinarySection section_code,
uint32_t size) {
BinaryReaderObjdumpBase::BeginSection(section_code, size);
const char* name = get_section_name(section_code);
bool section_match =
!options->section_name || !strcasecmp(options->section_name, name);
if (section_match)
section_found = true;
switch (options->mode) {
case ObjdumpMode::Headers:
printf("%9s start=%#010" PRIzx " end=%#010" PRIzx " (size=%#010x) ", name,
state->offset, state->offset + size, size);
break;
case ObjdumpMode::Details:
if (section_match) {
if (section_code != BinarySection::Code)
printf("%s:\n", name);
print_details = true;
} else {
print_details = false;
}
break;
case ObjdumpMode::RawData:
if (section_match) {
printf("\nContents of section %s:\n", name);
out_stream->WriteMemoryDump(data + state->offset, size, state->offset,
nullptr, nullptr, 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(uint32_t count) {
if (options->mode == ObjdumpMode::Headers) {
printf("count: %d\n", count);
}
return Result::Ok;
}
Result BinaryReaderObjdump::EndModule() {
if (options->section_name && !section_found) {
printf("Section not found: %s\n", options->section_name);
return Result::Error;
}
return Result::Ok;
}
Result BinaryReaderObjdump::OnTypeCount(uint32_t count) {
return OnCount(count);
}
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++) {
if (i != 0) {
printf(", ");
}
printf("%s", type_name(param_types[i]));
}
printf(") -> ");
if (result_count)
printf("%s", type_name(result_types[0]));
else
printf("nil");
printf("\n");
return Result::Ok;
}
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;
}
Result BinaryReaderObjdump::OnFunctionBodyCount(uint32_t count) {
return OnCount(count);
}
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;
}
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;
}
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;
}
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)
PrintDetails(" max=%" PRId64, page_limits->max);
PrintDetails("\n");
return Result::Ok;
}
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)
PrintDetails(" max=%" PRId64, elem_limits->max);
PrintDetails("\n");
return Result::Ok;
}
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;
}
Result BinaryReaderObjdump::OnElemSegmentFunctionIndex(uint32_t index,
uint32_t func_index) {
PrintDetails(" - func[%d]\n", func_index);
return Result::Ok;
}
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;
}
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;
}
Result BinaryReaderObjdump::OnInitExprF32ConstExpr(uint32_t index,
uint32_t value) {
char buffer[WABT_MAX_FLOAT_HEX];
write_float_hex(buffer, sizeof(buffer), value);
PrintDetails(" - init f32=%s\n", buffer);
return Result::Ok;
}
Result BinaryReaderObjdump::OnInitExprF64ConstExpr(uint32_t index,
uint64_t value) {
char buffer[WABT_MAX_DOUBLE_HEX];
write_float_hex(buffer, sizeof(buffer), value);
PrintDetails(" - init f64=%s\n", buffer);
return Result::Ok;
}
Result BinaryReaderObjdump::OnInitExprGetGlobalExpr(uint32_t index,
uint32_t global_index) {
PrintDetails(" - init global=%d\n", global_index);
return Result::Ok;
}
Result BinaryReaderObjdump::OnInitExprI32ConstExpr(uint32_t index,
uint32_t value) {
PrintDetails(" - init i32=%d\n", value);
return Result::Ok;
}
Result BinaryReaderObjdump::OnInitExprI64ConstExpr(uint32_t index,
uint64_t value) {
PrintDetails(" - init i64=%" PRId64 "\n", value);
return Result::Ok;
}
Result BinaryReaderObjdump::OnFunctionName(uint32_t index, StringSlice name) {
PrintDetails(" - func[%d] " PRIstringslice "\n", index,
WABT_PRINTF_STRING_SLICE_ARG(name));
return Result::Ok;
}
Result BinaryReaderObjdump::OnLocalName(uint32_t func_index,
uint32_t local_index,
StringSlice name) {
if (name.length) {
PrintDetails(" - func[%d] local[%d] " PRIstringslice "\n", func_index,
local_index, WABT_PRINTF_STRING_SLICE_ARG(name));
}
return Result::Ok;
}
Result BinaryReaderObjdump::OnDataSegmentCount(uint32_t count) {
return OnCount(count);
}
Result BinaryReaderObjdump::BeginDataSegment(uint32_t index,
uint32_t memory_index) {
PrintDetails(" - memory[%d]", memory_index);
return Result::Ok;
}
Result BinaryReaderObjdump::OnDataSegmentData(uint32_t index,
const void* src_data,
uint32_t size) {
if (ShouldPrintDetails()) {
out_stream->WriteMemoryDump(src_data, size, state->offset - size, " - ", nullptr,
PrintChars::Yes);
}
return Result::Ok;
}
Result BinaryReaderObjdump::OnRelocCount(uint32_t count,
BinarySection section_code,
StringSlice section_name) {
BinaryReaderObjdumpBase::OnRelocCount(count, section_code, section_name);
PrintDetails(" - section: %s\n", get_section_name(section_code));
return Result::Ok;
}
Result BinaryReaderObjdump::OnReloc(RelocType type,
uint32_t offset,
uint32_t index,
uint32_t addend) {
uint32_t total_offset =
section_starts[static_cast<size_t>(reloc_section)] + offset;
PrintDetails(" - %-18s offset=%#08x(file=%#08x) index=%#08x",
get_reloc_type_name(type), offset, total_offset, 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;
}
} // namespace
Result read_binary_objdump(const uint8_t* data,
size_t size,
ObjdumpOptions* options) {
ReadBinaryOptions read_options = WABT_READ_BINARY_OPTIONS_DEFAULT;
read_options.read_debug_names = true;
read_options.log_stream = options->log_stream;
switch (options->mode) {
case ObjdumpMode::Prepass: {
BinaryReaderObjdumpPrepass reader(data, size, options);
return read_binary(data, size, &reader, &read_options);
}
case ObjdumpMode::Disassemble: {
BinaryReaderObjdumpDisassemble reader(data, size, options);
return read_binary(data, size, &reader, &read_options);
}
default: {
BinaryReaderObjdump reader(data, size, options);
return read_binary(data, size, &reader, &read_options);
}
}
}
} // namespace wabt