blob: fbfed12cf1d3dbd123dc7985ae1e7c9e629c54cc [file] [log] [blame] [edit]
/*
* 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 <cstdio>
#include <cstdlib>
#include <cstring>
#include "src/common.h"
#include "src/option-parser.h"
#include "src/stream.h"
#include "src/binary-reader.h"
#include "src/binary-reader-objdump.h"
using namespace wabt;
static const char s_description[] =
R"( Print information about the contents of wasm binaries.
examples:
$ wasm-objdump test.wasm
)";
static ObjdumpOptions s_objdump_options;
static std::vector<const char*> s_infiles;
static std::unique_ptr<FileStream> s_log_stream;
static void ParseOptions(int argc, char** argv) {
OptionParser parser("wasm-objdump", s_description);
parser.AddOption('h', "headers", "Print headers",
[]() { s_objdump_options.headers = true; });
parser.AddOption(
'j', "section", "SECTION", "Select just one section",
[](const char* argument) { s_objdump_options.section_name = argument; });
parser.AddOption('s', "full-contents", "Print raw section contents",
[]() { s_objdump_options.raw = true; });
parser.AddOption('d', "disassemble", "Disassemble function bodies",
[]() { s_objdump_options.disassemble = true; });
parser.AddOption("debug", "Print extra debug information", []() {
s_objdump_options.debug = true;
s_log_stream = FileStream::CreateStderr();
s_objdump_options.log_stream = s_log_stream.get();
});
parser.AddOption('x', "details", "Show section details",
[]() { s_objdump_options.details = true; });
parser.AddOption('r', "reloc", "Show relocations inline with disassembly",
[]() { s_objdump_options.relocs = true; });
parser.AddOption(0, "section-offsets",
"Print section offsets instead of file offsets "
"in code disassembly",
[]() { s_objdump_options.section_offsets = true; });
parser.AddArgument(
"filename", OptionParser::ArgumentCount::OneOrMore,
[](const char* argument) { s_infiles.push_back(argument); });
parser.Parse(argc, argv);
}
Result dump_file(const char* filename) {
std::vector<uint8_t> file_data;
CHECK_RESULT(ReadFile(filename, &file_data));
uint8_t* data = file_data.data();
size_t size = file_data.size();
// Perform serveral passed over the binary in order to print out different
// types of information.
s_objdump_options.filename = filename;
printf("\n");
ObjdumpState state;
Result result = Result::Ok;
// Pass 0: Prepass
s_objdump_options.mode = ObjdumpMode::Prepass;
result |= ReadBinaryObjdump(data, size, &s_objdump_options, &state);
s_objdump_options.log_stream = nullptr;
// Pass 1: Print the section headers
if (s_objdump_options.headers) {
s_objdump_options.mode = ObjdumpMode::Headers;
result |= ReadBinaryObjdump(data, size, &s_objdump_options, &state);
}
// Pass 2: Print extra information based on section type
if (s_objdump_options.details) {
s_objdump_options.mode = ObjdumpMode::Details;
result |= ReadBinaryObjdump(data, size, &s_objdump_options, &state);
}
// Pass 3: Disassemble code section
if (s_objdump_options.disassemble) {
s_objdump_options.mode = ObjdumpMode::Disassemble;
result |= ReadBinaryObjdump(data, size, &s_objdump_options, &state);
}
// Pass 4: Dump to raw contents of the sections
if (s_objdump_options.raw) {
s_objdump_options.mode = ObjdumpMode::RawData;
result |= ReadBinaryObjdump(data, size, &s_objdump_options, &state);
}
return result;
}
int ProgramMain(int argc, char** argv) {
InitStdio();
ParseOptions(argc, argv);
if (!s_objdump_options.headers && !s_objdump_options.details &&
!s_objdump_options.disassemble && !s_objdump_options.raw) {
fprintf(stderr, "At least one of the following switches must be given:\n");
fprintf(stderr, " -d/--disassemble\n");
fprintf(stderr, " -h/--headers\n");
fprintf(stderr, " -x/--details\n");
fprintf(stderr, " -s/--full-contents\n");
return 1;
}
for (const char* filename: s_infiles) {
if (Failed(dump_file(filename))) {
return 1;
}
}
return 0;
}
int main(int argc, char** argv) {
WABT_TRY
return ProgramMain(argc, argv);
WABT_CATCH_BAD_ALLOC_AND_EXIT
}