Newer
Older
alicedbg / dumper / main.d
/// Command line interface.
///
/// Authors: dd86k <dd@dax.moe>
/// Copyright: © dd86k <dd@dax.moe>
/// License: BSD-3-Clause-Clear
module main;

import adbg.platform;
import adbg.include.c.stdlib : exit;
import adbg.debugger.exception : adbg_exception_t, adbg_exception_name;
import adbg.self;
import adbg.machines : adbg_machine_default;
import adbg.disassembler;
import adbg.error;
import adbg.debugger.process : adbg_process_t;
import core.stdc.stdlib : EXIT_FAILURE;
import core.stdc.stdio;
import dumper;
import common.error;
import common.cli;
import common.utils : unformat64;

private:

//TODO: --dump-blob-offset/--dump-blob-seek/--dump-blob-start: Starting offset for raw blob
//TODO: --dump-length/--dump-end: Length or end
//TODO: --dump-imports-all: Dependency walker
//TODO: --dump-stats: File statistics?
//                    pdb: stream count, positions, etc.
//TODO: --type-only: Returns short-name only for identification purposes
//TODO: --name: Extract by section, import, export name (will replace --section?)
immutable option_t[] options = [
	// secrets
	option_t(0,   "woof", null, &cliopt_woof),
	// common options
	option_arch,
	option_syntax,
	// selections
	option_t('H', "headers",      "Dump object's headers", &cliopt_headers),
	option_t('S', "sections",     "Dump object's sections", &cliopt_sections),
	option_t(0,   "section",      "Dump object's section by name", &cliopt_section),
	option_t('I', "imports",      "Dump object's import information", &cliopt_imports),
	option_t('E', "exports",      "Dump object's export information", &cliopt_exports),
//	option_t(0,   "loadcfg",      "Dump object's load configuration", &cliopt_loadcfg),
//	option_t(0,   "source",       "Dump object's source with disassembly", &cliopt_source),
	option_t(0,   "relocs",       "Dump object's relocations", &cliopt_relocs),
	option_t(0,   "debug",        "Dump object's debug information", &cliopt_debug),
	option_t(0,   "everything",   "Dump everything except disassembly", &cliopt_everything),
	// settings
	option_t(0,   "as-blob",           "Setting: Input is headless binary blob", &cliopt_as_blob),
	option_t(0,   "disassemble",       "Setting: Disassemble executable sections", &cliopt_disasm),
	option_t(0,   "disassemble-all",   "Setting: Disassemble all sections", &cliopt_disasm_all),
	option_t(0,   "disassemble-stats", "Setting: Provide disassembly statistics", &cliopt_disasm_stats),
	option_t(0,   "origin",            "Setting: Mark base address for disassembly", &cliopt_origin),
	option_t(0,   "extract",           "Setting: Output selected portion to stdout", &cliopt_extract),
	option_t(0,   "extract-to",        "Setting: Output selected portion to file", &cliopt_extract_to),
	option_t(0,   "hexdump",           "Setting: Output selected portion to stdout as hexdump", &cliopt_hexdump),
	// pages
	option_t('h', "help", "Show this help screen and exit", &cliopt_help),
	option_version,
	option_build_info,
	option_ver,
	option_license,
];
enum NUMBER_OF_SECRETS = 1;

//
// Selections
//

int cliopt_headers() {
	opt_selected |= Select.headers;
	return 0;
}
int cliopt_section(const(char) *val) {
	opt_selected |= Select.sections;
	opt_section_name = val;
	return 0;
}
int cliopt_sections() {
	opt_selected |= Select.sections;
	return 0;
}
int cliopt_imports() {
	opt_selected |= Select.imports;
	return 0;
}
int cliopt_exports() {
	opt_selected |= Select.exports;
	return 0;
}
int cliopt_loadcfg() {
	opt_selected |= Select.loadcfg;
	return 0;
}
int cliopt_relocs() {
	opt_selected |= Select.relocs;
	return 0;
}
int cliopt_debug() {
	opt_selected |= Select.debug_;
	return 0;
}

int cliopt_everything() {
	opt_selected |= Select.all;
	return 0;
}

//
// Settings
//

int cliopt_as_blob() {
	opt_settings |= Setting.blob;
	return 0;
}
int cliopt_disasm() {
	opt_settings |= Setting.disasm;
	return 0;
}
int cliopt_disasm_all() {
	opt_settings |= Setting.disasmAll;
	return 0;
}
int cliopt_disasm_stats() {
	opt_settings |= Setting.disasmStats;
	return 0;
}
int cliopt_origin(const(char) *val) {
	return unformat64(&opt_baseaddress, val);
}

int cliopt_extract() {
	opt_settings |= Setting.extract;
	return 0;
}
int cliopt_extract_to(const(char)* fname) {
	opt_settings |= Setting.extract;
	opt_extractfile = fname;
	return 0;
}
int cliopt_hexdump() {
	opt_settings |= Setting.hexdump;
	return 0;
}

//
// ANCHOR --help
//

int cliopt_help() {
	puts(
	"alicedump: Binary object dumper.\n"~
	"\n"~
	"USAGE\n"~
	"  Summarize object file:\n"~
	"    alicedbg [OPTIONS...] FILE\n"~
	"  Dump headers:\n"~
	"    alicedbg {-H|--headers} [OPTIONS...] FILE\n"~
	"  Show information page and exit:\n"~
	"    alicedbg {-h|--help|--version|--ver|--license}\n"~
	"\n"~
	"OPTIONS"
	);
	getoptprinter(options[NUMBER_OF_SECRETS..$]);
	exit(0);
	return 0;
}

int cliopt_woof() {
	puts(
r"
+---------------------+         ,
| Are you SystemReady |   .__,-/|
| compliant yet? Woof |    \_ ` \
+---------------------+      `====
                              {   \
                               \ / \
                               ///  `\ /
                              //_\   /`
"
	);
	exit(0);
	return 0;
}

extern (C)
int main(int argc, const(char)** argv) {
	// Set crash handle, and ignore on error
	// Could do a warning, but it might be a little confusing
	adbg_self_set_crashhandler(&oopsie);
	
	int e = getopt(argc, argv, options);
	if (e < 0) {
		puts(getopterror());
		return EXIT_FAILURE;
	}
	if (e == 0) {
		puts("error: No file specified");
		return EXIT_FAILURE;
	}
	
	return dump(*getoptleftovers()); // First argument as file
}