diff --git a/common/cli.d b/common/cli.d index badc371..a88a6a0 100644 --- a/common/cli.d +++ b/common/cli.d @@ -19,7 +19,7 @@ enum COPYRIGHT = "Copyright (c) 2019-2024 dd86k "; /// License string -immutable(char) *page_license = +immutable char *page_license = COPYRIGHT~` All rights reserved. @@ -117,6 +117,40 @@ /// Default option for --license enum option_license = option_t(0, "license", "Show the license page and exit", &cli_license); +private +immutable(option_t)* getoptlong(const(char)* arg, immutable(option_t)[] options) { + foreach (ref opt; options) { + if (strncmp(arg, opt.longname.ptr, opt.longname.length)) + continue; + return &opt; + } + return null; +} +private +immutable(option_t)* getoptshort(char arg, immutable(option_t)[] options) { + foreach (ref opt; options) { + if (arg != opt.shortname) + continue; + return &opt; + } + return null; +} +private +int getoptexec(immutable(option_t)* option, int argc, const(char) **argv, int index) { + final switch (option.argtype) { + case ARG_NONE: + if (option.f()) return -1; + return 0; + case ARG_STRING: // with argument + if (++index >= argc) + return getoptEmissingLong(option.longname.ptr); + const(char) *val = argv[index]; + if (option.fa(val)) + return getoptEinvValLong(option.longname.ptr, val); + return 1; + } +} + //TODO: Return error // <0 -> error // 0 -> no args left @@ -125,109 +159,106 @@ /// Interpret options int getopt(int argc, const(char) **argv, immutable(option_t)[] options) { // On re-entry, clear extras and error buffers - if (getoptextras) { - free(getoptextras); - getoptextras = null; - } - if (getopterrbuf) { - free(getopterrbuf); - getopterrbuf = null; - } + getoptreset(); - const(char) *arg = void; - const(char) *val = void; - CLI: for (int argi = 1; argi < argc; ++argi) { - arg = argv[argi]; + int i = 1; + for (; i < argc; ++i) { + const(char) *arg = argv[i]; // Current argument - if (arg[1] == '-') { // Long options + immutable(option_t) *option = void; + if (arg[1] == '-') { // Long option const(char) *argLong = arg + 2; // test for "--" (extra args) - /*if (argLong[0] == 0) { - if (cli_args_stop(++argi, argc, argv)) - return -1; - break CLI; - }*/ + if (argLong[0] == 0) + goto Lskip; - // Check options - L_LONG: foreach (ref opt; options) { - //TODO: test for '=' - // --example=value - - if (strncmp(argLong, opt.longname.ptr, opt.longname.length)) - continue L_LONG; - - // no argument expected - if (opt.argtype == ARG_NONE) { - if (opt.f()) - return -1; - continue CLI; - } - - // with argument - if (++argi >= argc) { - getoptEmissingLong(opt.longname.ptr); - return -1; - } - val = argv[argi]; - if (opt.fa(val)) { - getoptEinvValLong(opt.longname.ptr, val); - return -1; - } - continue CLI; - } - - getoptEunknown(arg); - return -1; - } else if (arg[0] == '-') { // Short options - // test for "-" (stdin) + option = getoptlong(argLong, options); + } else if (arg[0] == '-') { // Short option char argShort = arg[1]; - if (argShort == 0) { // "-" - getopterrbuf = cast(char*)"main: standard input not supported"; - return -1; + + // Test for null (often for "-") + if (argShort == 0) { + getoptaddextra(argc, arg); + continue; } - L_SHORT: foreach (ref opt; options) { - if (argShort != opt.shortname) - continue L_SHORT; - - // no argument - if (opt.argtype == ARG_NONE) { - if (opt.f()) - return -1; - continue CLI; - } - - // with argument - if (++argi >= argc) { - getoptEmissingShort(argShort); - return -1; - } - val = argv[argi]; - if (opt.fa(val)) { - getoptEinvValShort(opt.shortname, val); - return -1; - } - continue CLI; - } - - getoptEunknown(arg); - return -1; - } else { + option = getoptshort(argShort, options); + } else { // Not a switch getoptaddextra(argc, arg); - continue CLI; + continue; } + + // Option was not found + if (option == null) + return getoptEunknown(arg); + + // Execute option callback + int e = getoptexec(option, argc, argv, i); + if (e < 0) return e; + i += e; } - return 0; + return getoptleftcount(); + +Lskip: // When '--' is given + for (++i; i < argc; ++i) { + const(char) *arg = argv[i]; // Current argument + getoptaddextra(argc, arg); + } + return getoptleftcount(); } unittest { + __gshared int hit; + static int opttest() { + ++hit; + return 0; + } + static immutable(option_t)[] options = [ + option_t('t', "test", "testing switch", &opttest), + ]; + static const(char) **argv = [ + "program", "argument", "--test", "--", "--test" + ]; + static int argc = 5; + + int e = getopt(argc, argv, options); + assert(e == 2); // Two leftover argument + assert(hit == 1); // --test switch hit once + + const(char) **leftovers = getoptleftovers(); + assert(leftovers); + assert(strcmp(*leftovers, "argument") == 0); + assert(strcmp(*(leftovers + 1), "--test") == 0); +} +unittest { + __gshared int hit; + static int opttest() { + ++hit; + return 0; + } + static immutable(option_t)[] options = [ + option_t('t', "test", "testing switch", &opttest), + ]; + static const(char) **argv = [ + "alicedbg", "--", "alicedbg.exe", "--version" + ]; + static int argc = 4; + + int e = getopt(argc, argv, options); + assert(e == 2); // Two leftover argument + assert(hit == 0); // --test switch never hit + + const(char) **leftovers = getoptleftovers(); + assert(leftovers); + assert(strcmp(*leftovers, "alicedbg.exe") == 0); + assert(strcmp(*(leftovers + 1), "--version") == 0); } /// Print options -void getoptprinter(immutable(option_t)[] options, int skip = 0) { +void getoptprinter(immutable(option_t)[] options) { static immutable int padding = -17; - foreach (ref option; options[skip..$]) { with (option) + foreach (ref option; options) { with (option) if (shortname) printf(" -%c, --%*s %s\n", shortname, padding, longname.ptr, description.ptr); else @@ -235,10 +266,24 @@ } } +// Reset getopt internals +private void getoptreset() { + if (getoptextras) { + free(getoptextras); + getoptextras = null; + } + getoptextrascnt = 0; + if (getopterrbuf) { + free(getopterrbuf); + getopterrbuf = null; + } +} + // CLI "extra" argument handling private __gshared const(char)** getoptextras; private __gshared int getoptextrascnt; +//TODO: This should error out private void getoptaddextra(int argc, const(char)* extra) { if (getoptextrascnt >= argc) return; @@ -248,13 +293,14 @@ return; } getoptextras[getoptextrascnt++] = extra; + getoptextras[getoptextrascnt] = null; } /// Get remaining arguments -const(char)** getoptrem() { +const(char)** getoptleftovers() { return getoptextras; } /// Get remaining argument count -int getoptremcnt() { +int getoptleftcount() { return getoptextrascnt; } @@ -264,7 +310,7 @@ private __gshared char* getopterrbuf; /// Get getopt error message -const(char)* getopterrstring() { +const(char)* getopterror() { return getopterrbuf ? getopterrbuf : "No errors occured"; } @@ -278,30 +324,35 @@ } return 0; } -private void getoptEunknown(const(char)* opt) { - if (getopt_prepbuf()) return; +private int getoptEunknown(const(char)* opt) { + if (getopt_prepbuf()) return -100; snprintf(getopterrbuf, GETOPTBFSZ, "main: unknown option '%s'\n", opt); + return -1; } -private void getoptEinvValLong(const(char)* opt, const(char)* val) { - if (getopt_prepbuf()) return; +private int getoptEinvValLong(const(char)* opt, const(char)* val) { + if (getopt_prepbuf()) return -100; snprintf(getopterrbuf, GETOPTBFSZ, "main: '%s' is an invalid value for --%s\n", val, opt); + return -1; } -private void getoptEinvValShort(char opt, const(char)* val) { - if (getopt_prepbuf()) return; +private int getoptEinvValShort(char opt, const(char)* val) { + if (getopt_prepbuf()) return -100; snprintf(getopterrbuf, GETOPTBFSZ, "main: '%s' is an invalid value for -%c\n", val, opt); + return -1; } -private void getoptEmissingLong(const(char)* opt) { - if (getopt_prepbuf()) return; +private int getoptEmissingLong(const(char)* opt) { + if (getopt_prepbuf()) return -100; snprintf(getopterrbuf, GETOPTBFSZ, "main: missing argument for --%s\n", opt); + return -1; } -private void getoptEmissingShort(char opt) { - if (getopt_prepbuf()) return; +private int getoptEmissingShort(char opt) { + if (getopt_prepbuf()) return -100; snprintf(getopterrbuf, GETOPTBFSZ, "main: missing argument for -%c\n", opt); + return -1; } /// Is user asking for help with this option? diff --git a/common/error.d b/common/error.d index 8f81be6..b36ffc3 100644 --- a/common/error.d +++ b/common/error.d @@ -5,16 +5,25 @@ /// License: BSD-3-Clause-Clear module common.error; -import core.stdc.stdlib : exit; -import core.stdc.string : strerror; -import core.stdc.errno : errno; + +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; import adbg.error; import adbg.disassembler; import adbg.debugger.exception; -import adbg.machines : AdbgMachine; +import core.stdc.string : strerror; +import core.stdc.errno : errno; import core.stdc.stdio; import core.stdc.stdlib : malloc; +extern (C): + void print_adbg_error( const(char)* mod = cast(char*)__MODULE__, int line = __LINE__) { @@ -34,11 +43,53 @@ const(char)* mod = cast(char*)__MODULE__, int line = __LINE__) { printf("%s@%u: %s\n", mod, line, message); - exit(0); + exit(code); } -void panic_crt() { - panic(errno, strerror(errno)); +void panic_crt() { panic(errno, strerror(errno)); } +void panic_adbg() { panic(adbg_errno(), adbg_error_msg()); } + +void oopsie(adbg_process_t *proc, adbg_exception_t *ex) { + puts( +` + _ _ _ _ _ _ _ _ _ _ _ _ _ _ + _|_|_|_| |_|_|_|_ _|_|_|_ _|_|_|_| |_| |_| |_| +|_| |_|_ _|_| |_|_ _|_| |_|_ _ |_|_ _|_| |_| +|_| |_|_|_|_ |_|_|_|_| |_|_|_ |_|_|_|_| |_| +|_|_ _ _ |_| |_| |_| |_| _ _ _|_| |_| |_| _ + |_|_|_| |_| |_| |_| |_| |_|_|_| |_| |_| |_| +` + ); + + printf( + "Exception : %s\n"~ + "PID : %d\n", + adbg_exception_name(ex), adbg_process_get_pid(proc)); // casting is temp + + //TODO: Get thread context + + // Fault address & disasm if available + if (ex.faultz) { + printf("Address : %#zx\n", ex.faultz); + + adbg_opcode_t op = void; + adbg_disassembler_t *dis = adbg_dis_open(adbg_machine_default()); + printf("Instruction:"); + if (dis && adbg_dis_process_once(dis, &op, proc, ex.fault_address) == 0) { + // Print address + // Print machine bytes + for (size_t bi; bi < op.size; ++bi) + printf(" %02x", op.machine[bi]); + // + printf(" (%s", op.mnemonic); + if (op.operands) + printf(" %s", op.operands); + // + puts(")"); + } else { + printf(" Disassembly unavailable (%s)\n", adbg_error_msg()); + } + } + + //TODO: Option to attach debugger to this process + exit(ex.oscode); } -void panic_adbg() { - panic(adbg_errno(), adbg_error_msg()); -} \ No newline at end of file diff --git a/debugger/main.d b/debugger/main.d index 46cde2b..e07f90b 100644 --- a/debugger/main.d +++ b/debugger/main.d @@ -16,6 +16,7 @@ import core.stdc.stdlib : strtol, EXIT_SUCCESS, EXIT_FAILURE; import core.stdc.stdio; import debugger, shell; +import common.error; import common.cli; import common.utils : unformat64; @@ -23,12 +24,11 @@ immutable option_t[] options = [ // secrets - option_t(0, "meow", "Meow and exit", &cli_meow), + option_t(0, "meow", null, &cli_meow), // common options option_arch, option_syntax, // debugger options - option_t(0, "args", "Debugger: Supply arguments to executable", &cli_args), // option_t('E', "env", "Debugger: Supply environment variables to executable", &cli_env), option_t('p', "attach", "Debugger: Attach to Process ID", &cli_pid), // pages @@ -41,44 +41,6 @@ enum NUMBER_OF_SECRETS = 1; // -// ANCHOR --args/-- -// - -int cli_args_stop(int argi, int argc, const(char) **argv) { // -- - import adbg.utils.strings : adbg_util_move; - - //TODO: Allocate pointer buffer instead using calloc - - enum MAX = 16; - __gshared const(char) *[MAX] args; - - opt_file_argv = cast(const(char)**)args; - - int left = argc - argi; /// to move - void **s = cast(void**)(argv+argi); - - int m = adbg_util_move( - cast(void**)&opt_file_argv, MAX, - cast(void**)&s, left); - - debug assert(m == left, "cli_argsdd: 'adbg_util_move' Failed due to small buffer"); - - return EXIT_SUCCESS; -} -int cli_args(const(char) *val) { // --args - import adbg.utils.strings : adbg_util_expand; - - int argc = void; - char **argv = adbg_util_expand(val, &argc); - - if (argc == 0) - return EXIT_FAILURE; - - opt_file_argv = cast(const(char)**)argv; - return EXIT_SUCCESS; -} - -// // ANCHOR -E, --env // @@ -122,7 +84,7 @@ "\n"~ "OPTIONS" ); - getoptprinter(options, NUMBER_OF_SECRETS); + getoptprinter(options[NUMBER_OF_SECRETS..$]); puts("\nFor a list of values, for example a list of platforms, type '-a help'"); exit(0); return 0; @@ -147,68 +109,16 @@ } extern (C) -void crash_handler(adbg_exception_t *ex) { - scope(exit) exit(ex.oscode); - - adbg_process_t *self = adbg_self_process(); - - puts( -r" - _ _ _ _ _ _ _ _ _ _ _ _ _ _ - _|_|_|_| |_|_|_|_ _|_|_|_ _|_|_|_| |_| |_| |_| -|_| |_|_ _|_| |_|_ _|_| |_|_ _ |_|_ _|_| |_| -|_| |_|_|_|_ |_|_|_|_| |_|_|_ |_|_|_|_| |_| -|_|_ _ _ |_| |_| |_| |_| _ _ _|_| |_| |_| _ - |_|_|_| |_| |_| |_| |_| |_|_|_| |_| |_| |_| -" - ); - - printf( - "Exception : %s\n"~ - "PID : %d\n", - adbg_exception_name(ex), cast(int)self.pid); // casting is temp - - // Fault address & disasm if available - if (ex.faultz) { - printf("Address : %#zx\n", ex.faultz); - - adbg_opcode_t op = void; - adbg_disassembler_t *dis = adbg_dis_open(adbg_machine_default()); - printf("Instruction:"); - if (dis && adbg_dis_process_once(dis, &op, self, ex.fault_address) == 0) { - // Print address - // Print machine bytes - for (size_t bi; bi < op.size; ++bi) - printf(" %02x", op.machine[bi]); - // - printf(" (%s", op.mnemonic); - if (op.operands) - printf(" %s", op.operands); - // - puts(")"); - } else { - printf(" Disassembly unavailable (%s)\n", adbg_error_msg()); - } - } -} - -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(&crash_handler); + adbg_self_set_crashhandler(&oopsie); - if (getopt(argc, argv, options) < 0) { - puts(getopterrstring()); + int cnt = getopt(argc, argv, options); + if (cnt < 0) { + puts(getopterror()); return EXIT_FAILURE; } - if (getoptremcnt() < 1) { - puts("error: No file specified"); - return EXIT_FAILURE; - } - - const(char)** args = getoptrem(); - - return shell_loop(*args); + return shellinit(cnt, getoptleftovers()); } diff --git a/debugger/shell.d b/debugger/shell.d index 033e4e2..b859c02 100644 --- a/debugger/shell.d +++ b/debugger/shell.d @@ -31,9 +31,10 @@ pauseRequired = -5, alreadyLoaded = -6, missingOption = -7, - unformat = -8, - invalidCount = -9, - unattached = -10, + missingArgument = -8, + unformat = -9, + invalidCount = -10, + unattached = -11, scanMissingType = -20, scanMissingValue = -21, @@ -63,6 +64,8 @@ return "File already loaded."; case missingOption: return "Missing option for command."; + case missingArgument: + return "Missing argument."; case unformat: return "Input is not a number."; case invalidCount: @@ -88,27 +91,23 @@ } } -/*void registerError(void function(ref command2_help_t help)) { - -} -void registerHelp(void function(ref command2_help_t help)) { - -}*/ - -int shell_loop(const(char)* entry) { +//TODO: Turn into character array (like gdb --args) +int shellinit(int argc, const(char)** argv) { int ecode = void; if (loginit(null)) return 1337; - // Load or attach process if CLI specified it - if (entry) { - ecode = shell_proc_spawn(entry, opt_file_argv); + // Start process if specified + if (argc > 0 && argv) { + ecode = argc > 1 ? + shell_proc_spawn(*argv, argc - 1, argv + 1) : + shell_proc_spawn(*argv, 0, null); if (ecode) { printf("Error: %s\n", adbg_error_msg()); return ecode; } - } else if (opt_pid) { + } else if (opt_pid) { // Or attach to process if specified ecode = shell_proc_attach(opt_pid); if (ecode) { printf("Error: %s\n", adbg_error_msg()); @@ -118,7 +117,7 @@ coninit(); -LINPUT: +Lcommand: printf("(adbg) "); // .ptr is temporary because a slice with a length of 0 @@ -132,7 +131,7 @@ ecode = shell_exec(line); if (ecode) logerror(shell_error_string(ecode)); - goto LINPUT; + goto Lcommand; } int shell_exec(const(char) *command) { @@ -158,11 +157,14 @@ private: __gshared: -const(char)* last_file; adbg_process_t *process; adbg_disassembler_t *dis; adbg_registers_t *registers; +const(char)* last_spawn_exec; +int last_spawn_argc; +const(char)** last_spawn_argv; + // NOTE: BetterC stderr bindings on Windows are broken // And don't allow re-opening the streams, so screw it @@ -533,26 +535,31 @@ return null; } -int shell_proc_spawn(const(char) *exec, const(char) **argv) { +int shell_proc_spawn(const(char) *exec, int argc, const(char) **argv) { // Save for restart - last_file = exec; - opt_file_argv = argv; + last_spawn_exec = exec; + last_spawn_argc = argc; + last_spawn_argv = argv; // Spawn process process = adbg_debugger_spawn(exec, - AdbgSpawnOpt.argv, argv, + AdbgSpawnOpt.argv, argc, argv, 0); - if (process == null) { + if (process == null) return ShellError.alicedbg; - } - puts("Process created."); + printf("Process '%s' created", exec); + if (argc && argv) { + printf(" with %d arguments:", argc); + for (int i; i < argc; ++i) + printf(" '%s'", argv[i]); + } + putchar('\n'); // Open disassembler for process machine type dis = adbg_dis_open(adbg_process_get_machine(process)); - if (dis == null) { - logwarn("Disassembler not available (%s).", adbg_error_msg()); - } + if (dis == null) + logwarn("Disassembler not available (%s)", adbg_error_msg()); return 0; } @@ -769,17 +776,18 @@ } int command_spawn(int argc, const(char) **argv) { - if (argc < 2) { - return ShellError.invalidParameter; - } + if (argc < 2) + return ShellError.missingArgument; - return shell_proc_spawn(argv[1], argc > 2 ? argv + 2: null); + if (argc < 3) + return shell_proc_spawn(argv[1], 0, null); + + return shell_proc_spawn(argv[1], argc - 2, argv + 2); } int command_attach(int argc, const(char) **argv) { - if (argc < 2) { + if (argc < 2) return ShellError.invalidParameter; - } return shell_proc_attach(atoi(argv[1])); } @@ -803,7 +811,7 @@ adbg_debugger_terminate(process); // Spawn, shell still messages status - e = shell_proc_spawn(last_file, opt_file_argv); + e = shell_proc_spawn(last_spawn_exec, last_spawn_argc, last_spawn_argv); break; case attached: // Detach first, ignore on error (e.g., already detached) diff --git a/dumper/dumper.d b/dumper/dumper.d index 260ded6..7d589f7 100644 --- a/dumper/dumper.d +++ b/dumper/dumper.d @@ -128,8 +128,8 @@ if (setting_extract_any() == 0) { print_string("filename", path); print_u64("filesize", o.file_size); - print_string("format", adbg_object_name(o)); - print_string("short_name", adbg_object_short_name(o)); + print_string("format", adbg_object_format_name(o)); + print_string("short_name", adbg_object_format_shortname(o)); } final switch (o.format) with (AdbgObject) { case mz: return dump_mz(o); @@ -150,7 +150,8 @@ } // Otherwise, make a basic summary - printf("%s: %s\n", path, adbg_object_name(o)); + printf("%s: %s (%s)\n", path, + adbg_object_format_name(o), adbg_object_format_shortname(o)); return 0; } diff --git a/dumper/main.d b/dumper/main.d index 1f1e674..e057cd0 100644 --- a/dumper/main.d +++ b/dumper/main.d @@ -16,6 +16,7 @@ import core.stdc.stdlib : EXIT_FAILURE; import core.stdc.stdio; import dumper; +import common.error; import common.cli; import common.utils : unformat64; @@ -29,6 +30,8 @@ //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, @@ -53,12 +56,13 @@ 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", &cli_help), + 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 @@ -145,7 +149,7 @@ // ANCHOR --help // -int cli_help() { +int cliopt_help() { puts( "alicedump: Binary object dumper.\n"~ "\n"~ @@ -159,72 +163,43 @@ "\n"~ "OPTIONS" ); - getoptprinter(options); + getoptprinter(options[NUMBER_OF_SECRETS..$]); exit(0); return 0; } -extern (C) -void crash_handler(adbg_exception_t *ex) { - adbg_process_t *self = adbg_self_process(); - +int cliopt_woof() { puts( r" - _ _ _ _ _ _ _ _ _ _ _ _ _ _ - _|_|_|_| |_|_|_|_ _|_|_|_ _|_|_|_| |_| |_| |_| -|_| |_|_ _|_| |_|_ _|_| |_|_ _ |_|_ _|_| |_| -|_| |_|_|_|_ |_|_|_|_| |_|_|_ |_|_|_|_| |_| -|_|_ _ _ |_| |_| |_| |_| _ _ _|_| |_| |_| _ - |_|_|_| |_| |_| |_| |_| |_|_|_| |_| |_| |_| ++---------------------+ , +| Are you SystemReady | .__,-/| +| compliant yet? Woof | \_ ` \ ++---------------------+ `==== + { \ + \ / \ + /// `\ / + //_\ /` " ); - - printf( - "Exception : %s\n"~ - "PID : %d\n", - adbg_exception_name(ex), cast(int)self.pid); // casting is temp - - // Fault address & disasm if available - if (ex.faultz) { - printf("Address : %#zx\n", ex.faultz); - - adbg_opcode_t op = void; - adbg_disassembler_t *dis = adbg_dis_open(adbg_machine_default()); - if (dis && adbg_dis_process_once(dis, &op, self, ex.fault_address) == 0) { - // Print address - printf("Instruction:"); - // Print machine bytes - for (size_t bi; bi < op.size; ++bi) - printf(" %02x", op.machine[bi]); - // - printf(" (%s", op.mnemonic); - if (op.operands) - printf(" %s", op.operands); - // - puts(")"); - } else { - printf(" Unavailable (%s)\n", adbg_error_msg()); - } - } - - exit(ex.oscode); + 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(&crash_handler); + adbg_self_set_crashhandler(&oopsie); - if (getopt(argc, argv, options) < 0) { - puts(getopterrstring()); + int e = getopt(argc, argv, options); + if (e < 0) { + puts(getopterror()); return EXIT_FAILURE; } - - if (getoptremcnt() < 1) { + if (e == 0) { puts("error: No file specified"); return EXIT_FAILURE; } - return dump(*getoptrem()); // First argument as file + return dump(*getoptleftovers()); // First argument as file } diff --git a/src/adbg/self.d b/src/adbg/self.d index 1bbf6dd..a2c7625 100644 --- a/src/adbg/self.d +++ b/src/adbg/self.d @@ -132,7 +132,7 @@ /// Note: Not respected by some exceptions, like buffer overruns. /// Params: func = User handler function. /// Returns: Zero on success; Non-zero on error. -int adbg_self_set_crashhandler(void function(adbg_exception_t*) func) { +int adbg_self_set_crashhandler(void function(adbg_process_t*, adbg_exception_t*) func) { if (func == null) return adbg_oops(AdbgError.invalidArgument); @@ -161,7 +161,7 @@ private: -__gshared void function(adbg_exception_t*) __ufunction; +__gshared void function(adbg_process_t*, adbg_exception_t*) __ufunction; version (Windows) extern (Windows) @@ -182,7 +182,7 @@ } // Call user function - __ufunction(&ex); + __ufunction(adbg_self_process(), &ex); return EXCEPTION_EXECUTE_HANDLER; } @@ -210,7 +210,7 @@ //adbg_registers_t regs = void; //adbg_registers_config(®s, adbg_machine_default()); - __ufunction(&ex); + __ufunction(adbg_self_process(), &ex); /+adbg_ctx_init(&mexception.registers); version (X86) {