diff --git a/debugger/shell.d b/debugger/shell.d index 7523780c..e4bd8fcf 100644 --- a/debugger/shell.d +++ b/debugger/shell.d @@ -603,11 +603,12 @@ void shell_event_disassemble(size_t address, int count = 1, bool showAddress = t void shell_event_exception(adbg_process_t *proc, int event, void *edata, void *udata) { switch (event) with (AdbgEvent) { case exception: - adbg_exception_t *ex = cast(adbg_exception_t*)edata; + adbg_exception_t *ex = adbg_debugger_event_exception(edata); + assert(ex); printf("* Process %d (thread %d) stopped\n"~ " Reason : %s ("~ADBG_OS_ERROR_FORMAT~")\n", - ex.pid, ex.tid, + proc.pid, proc.tid, adbg_exception_name(ex), ex.oscode); // No fault address available @@ -647,13 +648,18 @@ void shell_event_exception(adbg_process_t *proc, int event, void *edata, void *u printf(" %s", op.operands); putchar('\n'); return; + case processExit: + int *exitcode = adbg_debugger_event_process_exitcode(edata); + assert(exitcode); + printf("* Process exited with code %d\n", *exitcode); + return; default: } } void shell_event_help(immutable(command2_t) *command) { // Print header - int p = 34; + int p = 34; // horizontal alignment padding for (size_t i; i < command.names.length; ++i) { if (i) { printf(", "); diff --git a/examples/simple.d b/examples/simple.d index 6c6b1e9a..969ea05f 100644 --- a/examples/simple.d +++ b/examples/simple.d @@ -40,7 +40,7 @@ void loop_handler(adbg_process_t *proc, int event, void *edata, void *udata) { "* PID=%u TID=%u\n"~ "* FAULT=%8llx", ex.oscode, adbg_exception_name(ex), - ex.pid, ex.tid, + proc.pid, proc.tid, ex.fault_address ); @@ -96,6 +96,6 @@ LOOP: // Process input goto LOOP; } - adbg_debugger_wait(process, &loop_handler); + adbg_debugger_wait(process, &loop_handler, null); goto LOOP; } \ No newline at end of file diff --git a/src/adbg/debugger.d b/src/adbg/debugger.d index 6ae3d0a6..62b716b5 100644 --- a/src/adbg/debugger.d +++ b/src/adbg/debugger.d @@ -5,7 +5,8 @@ /// License: BSD-3-Clause-Clear module adbg.debugger; -// TODO: adbg_debugger_spawn: Get default child stack size +// TODO: adbg_debugger_spawn: Get/set default child stack size +// TODO: High-level disassembly functions (e.g., from exception, etc.) public import adbg.process.base; import adbg.process.exception; @@ -45,6 +46,7 @@ extern (C): /// Debugging events enum AdbgEvent { exception, + processExit, } version (Posix) @@ -524,34 +526,69 @@ version (Windows) { return 0; } +private struct adbg_debugger_event_t { + AdbgEvent type; + union { + adbg_exception_t exception; + int exitcode; + } +} + +adbg_exception_t* adbg_debugger_event_exception(void *edata) { + if (edata == null) { + adbg_oops(AdbgError.invalidArgument); + return null; + } + adbg_debugger_event_t *event = cast(adbg_debugger_event_t*)edata; + if (event.type != AdbgEvent.exception) { + adbg_oops(AdbgError.invalidValue); + return null; + } + + return &event.exception; +} + +int* adbg_debugger_event_process_exitcode(void *edata) { + if (edata == null) { + adbg_oops(AdbgError.invalidArgument); + return null; + } + adbg_debugger_event_t *event = cast(adbg_debugger_event_t*)edata; + if (event.type != AdbgEvent.exception) { + adbg_oops(AdbgError.invalidValue); + return null; + } + + return &event.exitcode; +} + /// Continue execution of the process until a new debug event occurs. /// /// This call is blocking. /// -/// Windows: Uses WaitForDebugEvent. -/// Posix: Uses ptrace(2) and waitpid(2), filters SIGCONT out. +/// It is highly recommended to use the callback's process instance for +/// debugging services, and to not call this function within the callback. +/// +/// After the callback, this function returns. /// +/// Windows: Uses WaitForDebugEvent. +/// Posix: Uses waitpid(2) and ptrace(2), filters SIGCONT out. /// Params: -/// tracee = Tracee instance. -/// userfunc = User function callback on event. +/// proc = Tracee instance. +/// ufunc = User function callback on event. /// udata = User data passed to callback. Can be used to identify requests, for example. /// Returns: Error code. -int adbg_debugger_wait(adbg_process_t *tracee, - void function(adbg_process_t *proc, int type, void *data, void *user) userfunc, - void *udata) { - if (tracee == null || userfunc == null) +int adbg_debugger_wait(adbg_process_t *proc, + void function(adbg_process_t*, int, void*, void*) ufunc, void *udata) { + if (proc == null || ufunc == null) return adbg_oops(AdbgError.invalidArgument); - if (tracee.creation == AdbgCreation.unloaded) + if (proc.creation == AdbgCreation.unloaded) return adbg_oops(AdbgError.debuggerUnattached); - //TODO: Urgent: The process instance should ideally not be modified - // Changing process information (e.g., PID) can in turn - // be bad news for other API functions (e.g., breakpoints). - // - // Children processes should be allocated and attached to exception - // (via adbg_exception_get_process?). + adbg_process_t tracee = void; + adbg_debugger_event_t event = void; - adbg_exception_t exception = void; + memset(&tracee, 0, adbg_process_t.sizeof); version (Windows) { DEBUG_EVENT de = void; @@ -559,13 +596,23 @@ Lwait: // Something bad happened if (WaitForDebugEvent(&de, INFINITE) == FALSE) { tracee.status = AdbgProcStatus.unloaded; - tracee.creation = AdbgCreation.unloaded; return adbg_oops(AdbgError.os); } + version(Trace) trace("EventCode=%#x", de.dwDebugEventCode); + // Filter events switch (de.dwDebugEventCode) { - case EXCEPTION_DEBUG_EVENT: break; + case EXCEPTION_DEBUG_EVENT: + event.type = AdbgEvent.exception; + tracee.status = AdbgProcStatus.paused; + adbg_exception_translate(&event.exception, &de, null); + break; + case EXIT_PROCESS_DEBUG_EVENT: + event.type = AdbgEvent.processExit; + tracee.status = AdbgProcStatus.unknown; + event.exitcode = de.ExitProcess.dwExitCode; + break; /*case CREATE_THREAD_DEBUG_EVENT: case CREATE_PROCESS_DEBUG_EVENT: case EXIT_THREAD_DEBUG_EVENT: @@ -574,109 +621,63 @@ Lwait: case OUTPUT_DEBUG_STRING_EVENT: case RIP_EVENT: goto default;*/ - case EXIT_PROCESS_DEBUG_EVENT: - goto Lexited; default: ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE); goto Lwait; } + tracee.pid = de.dwProcessId; + tracee.tid = de.dwThreadId; + // Fixes access to debugger, thread context functions. // Especially when attaching, but should be standard with spawned-in processes too. - // TODO: Get rid of hack, replace with refreshing thread list - // or just opening/closing thread handle when needed - tracee.tid = de.dwThreadId; + // TODO: Get rid of hack to help multiprocess support + // By opening/closing process+thread handles per debugger function that need it: + // - Help with leaking handles + // - Permissions, since each OS function need different permissions + tracee.hpid = OpenProcess( + PROCESS_ALL_ACCESS, + FALSE, de.dwProcessId); tracee.htid = OpenThread( THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME, FALSE, de.dwThreadId); - tracee.status = AdbgProcStatus.paused; - adbg_exception_translate(&exception, &de, null); } else version (Posix) { int wstatus = void; - int stopsig = void; Lwait: tracee.pid = waitpid(-1, &wstatus, 0); - version (Trace) trace("wstatus=%#x", wstatus); - - // Something bad happened - if (tracee.pid < 0) { - tracee.status = AdbgProcStatus.unloaded; - tracee.creation = AdbgCreation.unloaded; + // Something terrible happened + if (tracee.pid < 0) return adbg_oops(AdbgError.crt); - } - - // If exited or killed by signal, it's gone. - if (WIFEXITED(wstatus) || WIFSIGNALED(wstatus)) - goto Lexited; - // Skip glibc "continue" signals. - version (CRuntime_Glibc) - if (WIFCONTINUED(wstatus)) + version(Trace) trace("wstatus=%#x", wstatus); + + if (WIFEXITED(wstatus) || WIFSIGNALED(wstatus)) { // Process exited or killed + event.type = AdbgEvent.processExit; + event.exitcode = WTERMSIG(wstatus); + } else if (WIFSTOPPED(wstatus)) { // Process stopped by signal + event.type = AdbgEvent.exception; + tracee.status = AdbgProcStatus.paused; + int sig = WSTOPSIG(wstatus); + adbg_exception_translate(&exception, &tracee.pid, &sig); + /* + } else if (WIFCONTINUED(wstatus)) { // Process continues, ignore these + goto Lwait; + */ + } else { + version (Trace) if (!WIFCONTINUED(wstatus)) trace("Unknown status code"); goto Lwait; - - // Bits Description (Linux) - // 6:0 Signo that caused child to exit - // 0x7f if child stopped/continued - // or zero if child exited without signal - // 7 Core dumped - // 15:8 exit value (or returned main value) - // or signal that cause child to stop/continue - stopsig = WEXITSTATUS(wstatus); - - // Get fault address - version (linux) switch (stopsig) { - case SIGCONT: goto Lwait; - // NOTE: si_addr is NOT populated under ptrace for SIGTRAP - // - linux does not fill si_addr on a SIGTRAP from a ptrace event - // - see sigaction(2) - // - linux *only* fills user_regs_struct for "user area" - // - see arch/x86/include/asm/user_64.h - // - "ptrace does not yet supply these. Someday...." - // - So yeah, debug registers and "fault_address" not filled - // - No access to ucontext_t from ptrace either - // - using EIP/RIP is NOT a good idea - // - IP ALWAYS point to NEXT instruction - // - First SIGTRAP does NOT contain int3 - // - Windows does, though, and points to it - // - gdbserver and lldb never attempt to do such thing anyway - // - RIP-1 (x86) could *maybe* point to int3 or similar. - // - User area might have DR3, it does have "fault_address" - // NOTE: Newer D compilers fixed siginfo_t as a whole - // for version (linux). Noticed on DMD 2.103.1. - // Old glibc: ._sifields._sigfault.si_addr - // Old musl: .__si_fields.__sigfault.si_addr - // New: ._sifields._sigfault.si_addr & .si_addr() - // NOTE: .si_addr() emits linker errors on Musl platforms. - case SIGILL, SIGSEGV, SIGFPE, SIGBUS: - siginfo_t sig = void; - if (ptrace(PT_GETSIGINFO, tracee.pid, null, &sig) < 0) { - exception.fault_address = 0; - break; - } - exception.fault_address = cast(size_t)sig._sifields._sigfault.si_addr; - break; -// case SIGINT, SIGTERM, SIGABRT: //TODO: Killed? - default: - exception.fault_address = 0; } - else exception.fault_address = 0; - - tracee.status = AdbgProcStatus.paused; - adbg_exception_translate(&exception, &tracee.pid, &stopsig); -} - - userfunc(tracee, AdbgEvent.exception, &exception, udata); - return 0; +} else static assert(0, "Implement adbg_debugger_wait"); -Lexited: - tracee.status = AdbgProcStatus.unloaded; - tracee.creation = AdbgCreation.unloaded; + ufunc(&tracee, event.type, &event, udata); return 0; } /// Disconnect and terminate the debuggee process. +/// +/// This function frees the process instance on success. /// Params: tracee = Process. /// Returns: Error code. int adbg_debugger_terminate(adbg_process_t *tracee) { @@ -692,10 +693,11 @@ version (Windows) { // was used instead. I forgot where I saw that example. MSDN does not feature it. if (TerminateProcess(tracee.hpid, DBG_TERMINATE_PROCESS) == FALSE) return adbg_oops(AdbgError.os); -} else { +} else version (Posix) { if (kill(tracee.pid, SIGKILL) < 0) // PT_KILL is deprecated on Linux return adbg_oops(AdbgError.os); -} +} else static assert(0, "Implement adbg_debugger_terminate"); + adbg_process_free(tracee); return 0; } @@ -723,12 +725,12 @@ version (Windows) { tracee.status = AdbgProcStatus.unknown; return adbg_oops(AdbgError.os); } -} else { +} else version (Posix) { if (ptrace(PT_CONTINUE, tracee.pid, null, 0) < 0) { tracee.status = AdbgProcStatus.unknown; return adbg_oops(AdbgError.os); } -} +} else static assert(0, "Implement adbg_debugger_continue"); return 0; } diff --git a/src/adbg/include/posix/sys/wait.d b/src/adbg/include/posix/sys/wait.d index 58e943d9..027e3400 100644 --- a/src/adbg/include/posix/sys/wait.d +++ b/src/adbg/include/posix/sys/wait.d @@ -1,7 +1,14 @@ /// Fixing improper sys/wait.h definitions. /// -/// This is due to extern (D) tricking the compiler the function that is -/// external dispite the defined body. +/// Existing definitions are defined with extern (D), which tricks the +/// compiler to define it as an external function, leading to linking issues. +/// +/// This module defines these macros, as inlined functions: +/// WEXITSTATUS, WTERMSIG, WSTOPSIG, WIFEXITED, WIFSIGNALED, WIFSTOPPED, +/// WIFCONTINUED, and WCOREDUMP. +/// +/// It also defines these values to be used in wait(2) functions: +/// WNOHANG, WUNTRACED, WSTOPPED, WCONTINUED, WNOWAIT, WEXITED, and WTRAPPED /// /// Authors: dd86k /// Copyright: © dd86k @@ -14,47 +21,88 @@ public import core.sys.posix.sys.wait; pragma(inline, true): -// Source: -// gdb/gdbsupport/gdb_wait.h - -bool WIFEXITED(int status) { - version (MinGW) // (((w) & 0xC0000000) == 0) - return (status & 0xC0000000) == 0; - else // (((w)&0377) == 0) - return cast(ubyte)status == 0; -} - -bool WIFSIGNALED(int status) { - version (MinGW) // (((w) & 0xC0000000) == 0xC0000000) - return ((status) & 0xC0000000) == 0xC0000000; - else // (((w)&0377) != 0177 && ((w)&~0377) == 0) - return cast(ubyte)status != 0x7f && cast(ubyte)(status >> 8) == 0; -} - -bool WIFSTOPPED(int status) { - version (RS6000) // ((w)&0x40) - return (status & 0x40) != 0; - else // (((w)&0377) == 0177) - return cast(ubyte)status == 0x7f; -} - -version (CRuntime_Glibc) -bool WIFCONTINUED(int status) { - // ((s) == 0xffff) - return cast(short)status == 0xffff; -} - -int WEXITSTATUS(int status) { - version (MinGW) // ((w) & ~0xC0000000) - return status & ~0xC0000000; - else // (((w) >> 8) & 0377) /* same as WRETCODE */ - return cast(ubyte)(status >> 8); -} - -int WTERMSIG(int status) { - // MinGW: extern int windows_status_to_termsig (unsigned long); - return status & 0x7f; -} - -// #define WSTOPSIG WEXITSTATUS -alias WSTOPSIG = WEXITSTATUS; +version (linux) { + // NOTE: wstatus + // Bits Description (Linux) + // 6:0 Signo that caused child to exit + // 0x7f if child stopped/continued + // or zero if child exited without signal + // 7 Core dumped + // 15:8 exit value (or returned main value) + // or signal that cause child to stop/continue + + // Shared at least across Glibc and Musl + enum WNOHANG = 1; + enum WUNTRACED = 2; + + enum WSTOPPED = 2; + enum WEXITED = 4; + enum WCONTINUED = 8; + enum WNOWAIT = 0x1000000; + + enum __WNOTHREAD = 0x20000000; + enum __WALL = 0x40000000; + enum __WCLONE = 0x80000000; + + int WEXITSTATUS(int s) { return (s & 0xff00) >> 8; } + int WTERMSIG(int s) { return s & 0x7f; } + int WSTOPSIG(int s) { return WEXITSTATUS(s); } + + bool WIFCONTINUED(int s) { return s == 0xffff; } + + int WCOREDUMP(int s) { return s & 0x80; } + + version (CRuntime_Glibc) { + // Source: bits/waitstatus.h + // sysdeps/unix/sysv/linux/bits/waitflags.h + + bool WIFEXITED(int s) { return WTERMSIG(s) == 0; } + bool WIFSIGNALED(int s) { return (cast(byte)((s & 0x7f) + 1) >> 1) > 0; } + bool WIFSTOPPED(int s) { return (s & 0xff) == 0x7f; } + + /* + #define __W_EXITCODE(ret, sig) ((ret) << 8 | (sig)) + #define __W_STOPCODE(sig) ((sig) << 8 | 0x7f) + */ + } else version (CRuntime_Musl) { + // Source: include/sys/wait.h + + bool WIFEXITED(int s) { return !WTERMSIG(s); } + bool WIFSIGNALED(int s) { return (s&0xffff)-1U < 0xffu; } + bool WIFSTOPPED(int s) { return cast(short)(((s&0xffff)*0x10001U)>>8) > 0x7f00; } + } else static assert(0, "Define wait.h macros (Linux)"); +} else version (FreeBSD) { + // Source: sys/sys/wait.h + + enum WNOHANG = 1; + enum WUNTRACED = 2; + enum WSTOPPED = WUNTRACED; + enum WCONTINUED = 4; + enum WNOWAIT = 8; + enum WEXITED = 16; + enum WTRAPPED = 32; + + enum WLINUXCLONE = 0x80000000; // Wait for kthread spawned from linux_clone. + + enum _WSTOPPED = 0x7f; // 0177, _WSTATUS if process is stopped + + int _WSTATUS(int x) { return x & 0x7f; } // 0177 + + int WEXITSTATUS(int x) { return x >> 8; } + int WTERMSIG(int x) { return _WSTATUS(x); } + alias WSTOPSIG = WEXITSTATUS; + + bool WIFSTOPPED(int x) { return _WSTATUS(x) == _WSTOPPED; } + bool WIFSIGNALED(int x) { return _WSTATUS(x) != _WSTOPPED && _WSTATUS(x) != 0 && x != 0x13; } + bool WIFEXITED(int x) { return _WSTATUS(x) == 0; } + + bool WIFCONTINUED(int x) { return x == 0x13; } // 0x13 == SIGCONT + + // #if __BSD_VISIBLE + int WCOREDUMP(int x) { return x & 0x80; } + + /* + #define W_EXITCODE(ret, sig) ((ret) << 8 | (sig)) + #define W_STOPCODE(sig) ((sig) << 8 | _WSTOPPED) + */ +} else static assert(0, "Define wait.h macros"); \ No newline at end of file diff --git a/src/adbg/process/base.d b/src/adbg/process/base.d index 1324c890..54817b40 100644 --- a/src/adbg/process/base.d +++ b/src/adbg/process/base.d @@ -5,7 +5,8 @@ /// License: BSD-3-Clause-Clear module adbg.process.base; -// TODO: Internal process flags (has pid, has thread list, etc.) +// TODO: Internal process flags +// Has memory handle, process-debugger relation, debugger/process options, etc. // TODO: Process Pause/Resume // Windows: NtSuspendProcess/NtResumeProcess or SuspendThread/ResumeThread // Linux: Send SIGSTOP/SIGCONT signals via kill(2) @@ -41,9 +42,6 @@ version (Windows) { import adbg.include.linux.personality; } -//version (CRuntime_Glibc) -// version = USE_CLONE; - extern (C): /// Process status @@ -65,27 +63,29 @@ enum AdbgCreation : ubyte { spawned, } -//TODO: Deprecate and remove static buffer in process struct -enum ADBG_PROCESS_NAME_LENGTH = 256; - /// Represents an instance of a process. struct adbg_process_t { - version (Windows) { // Original identifiers; Otherwise informal - int pid; /// Process identificiation number - HANDLE hpid; /// Process handle - char *args; /// Saved arguments when process was launched - // TODO: Deprecate tid and htid to rely on adbg_thread_t - int tid; /// Thread identification number - HANDLE htid; /// Thread handle - } - version (Posix) { - pid_t pid; /// Process ID - char **argv; /// Saved arguments when process was launched - } - version (linux) { - int mhandle; /// Internal memory file handle to /proc/PID/mem - bool memfailed; /// Set if we fail to open /proc/PID/mem - } +version (Windows) { // Original identifiers; Otherwise informal + // NOTE: PID and TID usage + // The Process and Thread IDs are used to open handles + // This is done on a per-function basis for permissions + // and memory management (opening and closing handles) + // purposes. + int pid; /// Process identificiation number + int tid; /// Thread identification number + char *args; /// Saved arguments when process was launched + // TODO: Deprecate hpid and htid + HANDLE htid; /// Thread handle + HANDLE hpid; /// Process handle +} +version (Posix) { + pid_t pid; /// Process ID + char **argv; /// Saved arguments when process was launched +} +version (linux) { + int mhandle; /// Internal memory file handle to /proc/PID/mem + bool memfailed; /// Set if we fail to open /proc/PID/mem +} /// Last known process status. AdbgProcStatus status; /// Process' creation source. @@ -99,9 +99,12 @@ void adbg_process_free(adbg_process_t *proc) { return; version (Windows) { if (proc.args) free(proc.args); + CloseHandle(proc.hpid); + CloseHandle(proc.htid); } version (Posix) { if (proc.argv) free(proc.argv); + version (linux) if (proc.mhandle) close(proc.mhandle); } adbg_list_free(proc.thread_list); free(proc); diff --git a/src/adbg/process/exception.d b/src/adbg/process/exception.d index 397e8e49..3af270fc 100644 --- a/src/adbg/process/exception.d +++ b/src/adbg/process/exception.d @@ -82,11 +82,6 @@ struct adbg_exception_t { AdbgException type; /// Original OS code (exception or signal value). uint oscode; - //TODO: Attach process instead of dedicated pid/tid. - /// Process ID. - int pid; - /// Thread ID, if available; Otherwise zero. - int tid; union { /// Faulting address, if available; Otherwise zero. ulong fault_address; @@ -240,10 +235,9 @@ const(char) *adbg_exception_name(adbg_exception_t *ex) { // Used internally for debugger void adbg_exception_translate(adbg_exception_t *exception, void *os1, void *os2) { version (Windows) { + assert(os1); DEBUG_EVENT *de = cast(DEBUG_EVENT*)os1; - exception.pid = de.dwProcessId; - exception.tid = de.dwThreadId; exception.faultz = cast(size_t)de.Exception.ExceptionRecord.ExceptionAddress; exception.oscode = de.Exception.ExceptionRecord.ExceptionCode; @@ -257,11 +251,50 @@ version (Windows) { exception.type = adbg_exception_from_os(exception.oscode); } } else { + assert(os1); + assert(os2); int pid = *cast(int*)os1; int signo = *cast(int*)os2; - exception.pid = exception.tid = pid; - exception.tid = 0; + // Get fault address + version (linux) { + switch (signo) { + // NOTE: si_addr is NOT populated under ptrace for SIGTRAP + // - linux does not fill si_addr on a SIGTRAP from a ptrace event + // - see sigaction(2) + // - linux *only* fills user_regs_struct for "user area" + // - see arch/x86/include/asm/user_64.h + // - "ptrace does not yet supply these. Someday...." + // - So yeah, debug registers and "fault_address" not filled + // - No access to ucontext_t from ptrace either + // - using EIP/RIP is NOT a good idea + // - IP ALWAYS point to NEXT instruction + // - First SIGTRAP does NOT contain int3 + // - Windows does, though, and points to it + // - gdbserver and lldb never attempt to do such thing anyway + // - RIP-1 (x86) could *maybe* point to int3 or similar. + // - User area might have DR3, it does have "fault_address" + // NOTE: Newer D compilers fixed siginfo_t as a whole + // for version (linux). Noticed on DMD 2.103.1. + // Old glibc: ._sifields._sigfault.si_addr + // Old musl: .__si_fields.__sigfault.si_addr + // New: ._sifields._sigfault.si_addr & .si_addr() + // NOTE: .si_addr() emits linker errors on Musl platforms. + case SIGILL, SIGSEGV, SIGFPE, SIGBUS: + siginfo_t siginfo = void; + if (ptrace(PT_GETSIGINFO, pid, null, &siginfo) < 0) { + exception.fault_address = 0; + break; + } + event.exception.fault_address = cast(size_t)siginfo._sifields._sigfault.si_addr; + break; + default: + event.exception.fault_address = 0; + } + } else { + event.exception.fault_address = 0; + } + exception.oscode = signo; exception.type = adbg_exception_from_os(signo); } diff --git a/src/adbg/self.d b/src/adbg/self.d index 69811bb4..308599e4 100644 --- a/src/adbg/self.d +++ b/src/adbg/self.d @@ -57,6 +57,7 @@ version (Windows) { proc.tid = GetCurrentThreadId(); } else version (Posix) { proc.pid = getpid(); + // TODO: (Linux) gettid(2) } return &proc; } @@ -169,8 +170,6 @@ uint adbg_internal_handler(EXCEPTION_POINTERS *e) { adbg_exception_t ex = void; ex.oscode = e.ExceptionRecord.ExceptionCode; ex.faultz = cast(size_t)e.ExceptionRecord.ExceptionAddress; - ex.pid = GetCurrentProcessId(); - ex.tid = GetCurrentThreadId(); with (e.ExceptionRecord) switch (ex.oscode) { case EXCEPTION_IN_PAGE_ERROR: case EXCEPTION_ACCESS_VIOLATION: @@ -195,8 +194,6 @@ void adbg_internal_handler(int sig, siginfo_t *si, void *p) { adbg_exception_t ex = void; ex.oscode = sig; ex.type = adbg_exception_from_os(si.si_signo, si.si_code); - ex.pid = getpid(); - ex.tid = 0; // NOTE: gettid(2) is only available on Linux version (linux) { switch (sig) { case SIGILL, SIGSEGV, SIGFPE, SIGBUS: