diff --git a/common/cli.d b/common/cli.d index 59dcd90..13955c3 100644 --- a/common/cli.d +++ b/common/cli.d @@ -17,8 +17,10 @@ import core.stdc.string; import core.stdc.errno; +/// Copyright string enum COPYRIGHT = "Copyright (c) 2019-2024 dd86k "; +/// License string immutable(char) *page_license = COPYRIGHT~` All rights reserved. @@ -48,8 +50,8 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.`; -debug enum FULL_VERSION = ADBG_VERSION~"+"~__BUILDTYPE__; -else enum FULL_VERSION = ADBG_VERSION; +debug enum FULL_VERSION = ADBG_VERSION~"+"~__BUILDTYPE__; /// Full version string +else enum FULL_VERSION = ADBG_VERSION; /// Ditto /// Turns a __VERSION__ number into a string constant template DSTRVER(uint ver) { @@ -76,7 +78,9 @@ //ARG_LARGENUMBER, // %lli } +/// Represents one command-line option switch struct option_t { align(1): + /// Make an option without arguments this (char oshort, string olong, string desc, int function() ufunc) { shortname = oshort; longname = olong; @@ -84,6 +88,7 @@ argtype = ARG_NONE; f = ufunc; } + /// Make an option with string argument this (char oshort, string olong, string desc, int function(const(char)*) ufunc) { shortname = oshort; longname = olong; @@ -96,18 +101,22 @@ char shortname; /// Short switch name ubyte argtype; /// Argument type union { - int function() f; - int function(const(char)*) fa; + int function() f; /// User callback + int function(const(char)*) fa; /// Ditto } } -//NOTE: Can't make a template and pass a function pointer - +/// Default option for --machine enum option_arch = option_t('m', "machine", "Select machine for disassembler (default=platform)", &cli_march); +/// Default option for --syntax enum option_syntax = option_t('s', "syntax", "Select syntax for disassembler (default=platform)", &cli_syntax); +/// Default option for --version enum option_version = option_t(0, "version", "Show the version screen and exit", &cli_version); +/// Default option for --build-info enum option_build_info = option_t(0, "build-info", "Show the build and debug information and exit", &cli_build_info); +/// Default option for --ver enum option_ver = option_t(0, "ver", "Show only the version string and exit", &cli_ver); +/// Default option for --license enum option_license = option_t(0, "license", "Show the license page and exit", &cli_license); //TODO: Return error @@ -115,6 +124,7 @@ // 0 -> no args left // >0 -> args left //TODO: Make option functions return <0=error >0=ok, consumed arg(s) +/// Interpret options int getopt(int argc, const(char) **argv, immutable(option_t)[] options) { const(char) *arg = void; const(char) *val = void; @@ -208,6 +218,7 @@ unittest { } +/// Print options void getoptprinter(immutable(option_t)[] options, int skip = 0) { static immutable int padding = -17; foreach (ref option; options[skip..$]) { with (option) @@ -232,9 +243,11 @@ } getoptextras[getoptextrascnt++] = extra; } +/// Get remaining arguments const(char)** getoptrem() { return getoptextras; } +/// Get remaining argument count int getoptremcnt() { return getoptextrascnt; } @@ -244,6 +257,7 @@ private enum GETOPTBFSZ = 2048; private __gshared char* getopterrbuf; +/// Get getopt error message const(char)* getopterrstring() { return getopterrbuf ? getopterrbuf : "No errors occured"; } @@ -284,12 +298,13 @@ "main: missing argument for -%c\n", opt); } - +/// Is user asking for help with this option? bool wantsHelp(const(char) *query) { - return (query[0] == 'h' && query[1] == 0) || - strcmp(query, "help") == 0; + return strcmp(query, "help") == 0; } +private: + // // --march // diff --git a/debugger/shell.d b/debugger/shell.d index 3a11393..033e4e2 100644 --- a/debugger/shell.d +++ b/debugger/shell.d @@ -624,7 +624,12 @@ } } -void shell_event_exception(adbg_exception_t *ex) { +void shell_event_exception(adbg_process_t *proc, int event, void* evdata) { + if (event != AdbgEvent.exception) + return; + + adbg_exception_t *ex = cast(adbg_exception_t*)evdata; + printf("* Process %d (thread %d) stopped\n"~ " Reason : %s ("~ADBG_OS_ERROR_FORMAT~")\n", ex.pid, ex.tid, diff --git a/dumper/format/elf.d b/dumper/format/elf.d index 11ef97d..ad6d776 100644 --- a/dumper/format/elf.d +++ b/dumper/format/elf.d @@ -5,7 +5,7 @@ /// License: BSD-3-Clause-Clear module format.elf; -import adbg.utils.bit : adbg_align4up; +import adbg.utils.bit : adbg_alignup; import adbg.disassembler; import adbg.object.server; import adbg.machines; @@ -241,7 +241,7 @@ print_u32("n_descsz", nhdr.n_descsz); print_u32("n_type", nhdr.n_type, adbg_object_elf_nt_type_string(nhdr.n_type)); - size_t nnamesz = adbg_align4up(nhdr.n_namesz); + size_t nnamesz = adbg_alignup(nhdr.n_namesz, ulong.sizeof); void *data = note + Elf64_Nhdr.sizeof + nnamesz; // NOTE: Only for x86-64, for now @@ -388,7 +388,7 @@ ulong nsize = Elf64_Nhdr.sizeof + nnamesz + - adbg_align4up(nhdr.n_descsz); + adbg_alignup(nhdr.n_descsz, uint.sizeof); noffset += nsize; nleft -= nsize; diff --git a/examples/simple.d b/examples/simple.d index 0f997ca..1c2d53e 100644 --- a/examples/simple.d +++ b/examples/simple.d @@ -11,12 +11,58 @@ import adbg; extern (C): +__gshared: +private: // Shuts up dscanner + +adbg_disassembler_t *dis; + +void die(int code = 0, const(char) *reason = null) { + printf("error: %s\n", reason ? reason : adbg_error_msg); + if (code == 0) code = adbg_errno; + exit(code); +} + +int choice(const(char) *msg) { + printf("\n%s: ", msg); +LINPUT: int c = getchar; + if (isprint(c)) return c; + goto LINPUT; +} + +void loop_handler(adbg_process_t *proc, int event, void *evdata) { + if (event != AdbgEvent.exception) + return; + + adbg_exception_t *ex = cast(adbg_exception_t*)evdata; + printf( + "\n----------------------------------------\n"~ + "* EXCEPTION ("~ADBG_OS_ERROR_FORMAT~"): %s\n"~ + "* PID=%u TID=%u\n"~ + "* FAULT=%8llx", + ex.oscode, adbg_exception_name(ex), + ex.pid, ex.tid, + ex.fault_address + ); + + // Print disassembly if available + if (dis && ex.faultz) { + adbg_opcode_t op = void; + if (adbg_dis_process_once(dis, &op, proc, ex.fault_address)) { + printf(" (error:%s)\n", adbg_error_msg); + return; + } + if (op.operands) + printf(" (%s %s)\n", op.mnemonic, op.operands); + else + printf(" (%s)\n", op.mnemonic); + } +} int main(int argc, const(char) **argv) { if (argc < 2) die(1, "Missing path to executable"); - process = adbg_debugger_spawn(argv[1], 0); + adbg_process_t *process = adbg_debugger_spawn(argv[1], 0); if (process == null) die; @@ -50,47 +96,4 @@ adbg_debugger_wait(process, &loop_handler); goto LOOP; -} - -private: // Shuts up dscanner - -void die(int code = 0, const(char) *reason = null) { - printf("error: %s\n", reason ? reason : adbg_error_msg); - if (code == 0) code = adbg_errno; - exit(code); -} - -int choice(const(char) *msg) { - printf("\n%s: ", msg); -LINPUT: int c = getchar; - if (isprint(c)) return c; - goto LINPUT; -} - -__gshared adbg_process_t *process; -__gshared adbg_disassembler_t *dis; - -void loop_handler(adbg_exception_t *ex) { - printf( - "\n----------------------------------------\n"~ - "* EXCEPTION ("~ADBG_OS_ERROR_FORMAT~"): %s\n"~ - "* PID=%u TID=%u\n"~ - "* FAULT=%8llx", - ex.oscode, adbg_exception_name(ex), - ex.pid, ex.tid, - ex.fault_address - ); - - // Print disassembly if available - if (dis && ex.faultz) { - adbg_opcode_t op = void; - if (adbg_dis_process_once(dis, &op, process, ex.fault_address)) { - printf(" (error:%s)\n", adbg_error_msg); - return; - } - if (op.operands) - printf(" (%s %s)\n", op.mnemonic, op.operands); - else - printf(" (%s)\n", op.mnemonic); - } } \ No newline at end of file diff --git a/src/adbg/debugger/process.d b/src/adbg/debugger/process.d index e20982c..bcb08ec 100644 --- a/src/adbg/debugger/process.d +++ b/src/adbg/debugger/process.d @@ -51,6 +51,11 @@ extern (C): +/// Debugging events +enum AdbgEvent { + exception, +} + /// Process status enum AdbgProcStatus : ubyte { unknown, /// Process status is not known. @@ -58,29 +63,8 @@ standby, /// Process is loaded and waiting to run. running, /// Process is running. paused, /// Process is paused due to an exception or by the debugger. - idle = unloaded, /// Old v1 alias for unloaded. - ready = standby, /// Old v1 alias for standby. } -/// Debugger event -/+public -enum AdbgEvent { - exception, - processCreated, - processExit, - threadCreated, - threadExit, -} - -/// Debugger event structure -public -struct adbg_debugger_event_t { - AdbgEvent event; - public union { - exception_t exception; - } -}+/ - //TODO: Rename to AdbgDebuggerRelation /// Process creation source. enum AdbgCreation : ubyte { @@ -603,7 +587,8 @@ /// tracee = Tracee instance. /// userfunc = User function callback. /// Returns: Error code. -int adbg_debugger_wait(adbg_process_t *tracee, void function(adbg_exception_t*) userfunc) { +int adbg_debugger_wait(adbg_process_t *tracee, + void function(adbg_process_t*, int, void*) userfunc) { if (tracee == null || userfunc == null) return adbg_oops(AdbgError.invalidArgument); if (tracee.creation == AdbgCreation.unloaded) @@ -730,7 +715,7 @@ adbg_exception_translate(&exception, &tracee.pid, &stopsig); } - userfunc(&exception); + userfunc(tracee, AdbgEvent.exception, &exception); return 0; L_UNLOADED: @@ -785,12 +770,12 @@ version (Windows) { if (ContinueDebugEvent(tracee.pid, tracee.tid, DBG_CONTINUE) == FALSE) { - tracee.status = AdbgProcStatus.idle; + tracee.status = AdbgProcStatus.unknown; return adbg_oops(AdbgError.os); } } else { if (ptrace(PT_CONT, tracee.pid, null, null) < 0) { - tracee.status = AdbgProcStatus.idle; + tracee.status = AdbgProcStatus.unknown; return adbg_oops(AdbgError.os); } }