diff options
Diffstat (limited to 'src/tools/wasm-objdump.cc')
-rw-r--r-- | src/tools/wasm-objdump.cc | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/src/tools/wasm-objdump.cc b/src/tools/wasm-objdump.cc new file mode 100644 index 00000000..49134fc2 --- /dev/null +++ b/src/tools/wasm-objdump.cc @@ -0,0 +1,224 @@ +/* + * 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 "common.h" +#include "option-parser.h" +#include "stream.h" +#include "writer.h" +#include "binary-reader.h" +#include "binary-reader-objdump.h" + +#define PROGRAM_NAME "wasm-objdump" + +#define NOPE HasArgument::No +#define YEP HasArgument::Yes + +using namespace wabt; + +enum { + FLAG_HEADERS, + FLAG_SECTION, + FLAG_RAW, + FLAG_DISASSEMBLE, + FLAG_DEBUG, + FLAG_DETAILS, + FLAG_RELOCS, + FLAG_HELP, + NUM_FLAGS +}; + +static const char s_description[] = + " Print information about the contents of wasm binaries.\n" + "\n" + "examples:\n" + " $ wasm-objdump test.wasm\n"; + +static Option s_options[] = { + {FLAG_HEADERS, 'h', "headers", nullptr, NOPE, "print headers"}, + {FLAG_SECTION, 'j', "section", nullptr, YEP, "select just one section"}, + {FLAG_RAW, 's', "full-contents", nullptr, NOPE, + "print raw section contents"}, + {FLAG_DISASSEMBLE, 'd', "disassemble", nullptr, NOPE, + "disassemble function bodies"}, + {FLAG_DEBUG, '\0', "debug", nullptr, NOPE, "print extra debug information"}, + {FLAG_DETAILS, 'x', "details", nullptr, NOPE, "Show section details"}, + {FLAG_RELOCS, 'r', "reloc", nullptr, NOPE, + "show relocations inline with disassembly"}, + {FLAG_HELP, 'h', "help", nullptr, NOPE, "print this help message"}, +}; + +WABT_STATIC_ASSERT(NUM_FLAGS == WABT_ARRAY_SIZE(s_options)); + +static ObjdumpOptions s_objdump_options; + +static std::vector<const char*> s_infiles; + +static std::unique_ptr<FileStream> s_log_stream; + +static void on_argument(struct OptionParser* parser, const char* argument) { + s_infiles.push_back(argument); +} + +static void on_option(struct OptionParser* parser, + struct Option* option, + const char* argument) { + switch (option->id) { + case FLAG_HEADERS: + s_objdump_options.headers = true; + break; + + case FLAG_RAW: + s_objdump_options.raw = true; + break; + + case FLAG_DEBUG: + s_objdump_options.debug = true; + s_log_stream = FileStream::CreateStdout(); + s_objdump_options.log_stream = s_log_stream.get(); + break; + + case FLAG_DISASSEMBLE: + s_objdump_options.disassemble = true; + break; + + case FLAG_DETAILS: + s_objdump_options.details = true; + break; + + case FLAG_RELOCS: + s_objdump_options.relocs = true; + break; + + case FLAG_SECTION: + s_objdump_options.section_name = argument; + break; + + case FLAG_HELP: + print_help(parser, PROGRAM_NAME); + exit(0); + break; + } +} + +static void on_option_error(struct OptionParser* parser, const char* message) { + WABT_FATAL("%s\n", message); +} + +static void parse_options(int argc, char** argv) { + OptionParser parser; + WABT_ZERO_MEMORY(parser); + parser.description = s_description; + parser.options = s_options; + parser.num_options = WABT_ARRAY_SIZE(s_options); + parser.on_option = on_option; + parser.on_argument = on_argument; + parser.on_error = on_option_error; + parse_options(&parser, argc, argv); + + if (s_infiles.size() == 0) { + print_help(&parser, PROGRAM_NAME); + WABT_FATAL("No filename given.\n"); + } +} + +Result dump_file(const char* filename) { + char* char_data; + size_t size; + Result result = read_file(filename, &char_data, &size); + if (WABT_FAILED(result)) + return result; + + uint8_t* data = reinterpret_cast<uint8_t*>(char_data); + + // Perform serveral passed over the binary in order to print out different + // types of information. + s_objdump_options.filename = filename; + printf("\n"); + + // Pass 0: Prepass + s_objdump_options.mode = ObjdumpMode::Prepass; + result = read_binary_objdump(data, size, &s_objdump_options); + if (WABT_FAILED(result)) + goto done; + s_objdump_options.log_stream = nullptr; + + // Pass 1: Print the section headers + if (s_objdump_options.headers) { + s_objdump_options.mode = ObjdumpMode::Headers; + result = read_binary_objdump(data, size, &s_objdump_options); + if (WABT_FAILED(result)) + goto done; + } + + // Pass 2: Print extra information based on section type + if (s_objdump_options.details) { + s_objdump_options.mode = ObjdumpMode::Details; + result = read_binary_objdump(data, size, &s_objdump_options); + if (WABT_FAILED(result)) + goto done; + } + + // Pass 3: Disassemble code section + if (s_objdump_options.disassemble) { + s_objdump_options.mode = ObjdumpMode::Disassemble; + result = read_binary_objdump(data, size, &s_objdump_options); + if (WABT_FAILED(result)) + goto done; + } + + // Pass 4: Dump to raw contents of the sections + if (s_objdump_options.raw) { + s_objdump_options.mode = ObjdumpMode::RawData; + result = read_binary_objdump(data, size, &s_objdump_options); + } + +done: + delete[] data; + return result; +} + +int ProgramMain(int argc, char** argv) { + init_stdio(); + + parse_options(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 (WABT_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 +} |