From 0354669846be9be0d0353a6aa83297a1021c910d Mon Sep 17 00:00:00 2001 From: midipix Date: Sun, 15 Sep 2019 19:12:33 +0000 Subject: mgdb: struct winnt_thread and friends: initial implementation and integration. --- overlay/mgdb/gdb/amd64-winnt-regcache.c | 27 +++-- overlay/mgdb/gdb/i386-winnt-regcache.c | 8 +- overlay/mgdb/gdb/winnt-nat.c | 182 ++++++++++++++++++++------------ overlay/mgdb/gdb/winnt-nat.h | 57 ++++++++++ 4 files changed, 195 insertions(+), 79 deletions(-) create mode 100644 overlay/mgdb/gdb/winnt-nat.h diff --git a/overlay/mgdb/gdb/amd64-winnt-regcache.c b/overlay/mgdb/gdb/amd64-winnt-regcache.c index 83a836c..7a1dab6 100644 --- a/overlay/mgdb/gdb/amd64-winnt-regcache.c +++ b/overlay/mgdb/gdb/amd64-winnt-regcache.c @@ -8,6 +8,7 @@ #include "osabi.h" #include "regcache.h" #include "amd64-tdep.h" +#include "winnt-nat.h" #include #include @@ -61,23 +62,29 @@ static void amd64_winnt_supply_core_regs( amd64_winnt_supply_reg(rcache,AMD64_EFLAGS_REGNUM,regctx->uc_eflags); } -int amd64_winnt_fetch_registers( - int pfd, struct regcache * rcache, - int regnum, pid_t tid) +void amd64_winnt_fetch_registers( + struct regcache * rcache, int regnum, + struct winnt_thread * thread) { - int ret; - mcontext_t regctx; + int pfd; + pid_t tid; + mcontext_t * regctx; - if ((ret = __dbg_regs_fetch(pfd,tid,®ctx)) < 0) - return ret; + pfd = thread->process->pfd; + tid = thread->tid; + regctx = &thread->regctx; + + if (thread->regctx.uc_context_flags) + if (__dbg_regs_fetch(pfd,tid,regctx) < 0) + return; if (regnum == AMD64_RIP_REGNUM) { - amd64_winnt_supply_pc_regs(rcache,®ctx); + amd64_winnt_supply_pc_regs(rcache,regctx); } else { - amd64_winnt_supply_core_regs(rcache,®ctx); + amd64_winnt_supply_core_regs(rcache,regctx); } - return 0; + regctx->uc_context_flags = WINNT_THREAD_CONTEXT_READY; } #define AMD64_WINNT_INIT_REG_OFFSET(regnum,regmem) \ diff --git a/overlay/mgdb/gdb/i386-winnt-regcache.c b/overlay/mgdb/gdb/i386-winnt-regcache.c index 1c2fb3e..7941fd3 100644 --- a/overlay/mgdb/gdb/i386-winnt-regcache.c +++ b/overlay/mgdb/gdb/i386-winnt-regcache.c @@ -8,15 +8,15 @@ #include "osabi.h" #include "frame-unwind.h" #include "i386-tdep.h" +#include "winnt-nat.h" struct regcache; void i386_winnt_fetch_registers( - int pfd, struct regcache * rcache, - int regnum, pid_t tid) + struct regcache * rcache, int regnum, + struct winnt_thread * thread) { - (void)pfd; (void)rcache; (void)regnum; - (void)tid; + (void)thread; } diff --git a/overlay/mgdb/gdb/winnt-nat.c b/overlay/mgdb/gdb/winnt-nat.c index ed3fa53..a253426 100644 --- a/overlay/mgdb/gdb/winnt-nat.c +++ b/overlay/mgdb/gdb/winnt-nat.c @@ -15,6 +15,7 @@ #include "gdbthread.h" #include "inf-child.h" #include "xml-support.h" +#include "winnt-nat.h" #include "x86-nat.h" #include @@ -35,37 +36,11 @@ #define winnt_perror(msg,pid) \ error("%s(): %s (pid %d).",__FUNCTION__,msg,pid) -#define WINNT_DR_STATE_DIRTY (0x1) - -struct regcache; - -struct winnt_process { - int pfd; - pid_t pid; - pid_t syspid; - pid_t systid; - pid_t flags; - int nmodules; - struct __dbg_module_info * modules; - struct __dbg_event event; - char * solibs; - uintptr_t dr_cache[8]; - uint32_t dr_state; -}; - static size_t pcnt; static winnt_process * plist; static char * outbuf; static struct pe_driver_ctx * pe_dctx; -extern void amd64_winnt_fetch_registers( - int pfd, struct regcache * rcache, - int regnum, pid_t tid); - -extern void i386_winnt_fetch_registers( - int pfd, struct regcache * rcache, - int regnum, pid_t tid); - static winnt_process * winnt_plist_expand (void) { struct winnt_process * pnew; @@ -136,6 +111,19 @@ static void winnt_free_modules(struct winnt_process * pidinfo) pidinfo->solibs = 0; } +static void winnt_free_threads(struct winnt_process * pidinfo) +{ + struct winnt_thread * thread; + struct winnt_thread * next; + + next = pidinfo->threads; + + for (thread=next; thread; thread=next) { + next = thread->next; + free(thread); + } +} + static void winnt_plist_remove (pid_t pid) { struct winnt_process * pdbg; @@ -144,6 +132,7 @@ static void winnt_plist_remove (pid_t pid) for (pdbg=plist, pcap=&plist[pcnt]; pdbgpid == pid) { winnt_free_modules(pdbg); + winnt_free_threads(pdbg); pdbg->pid = 0; pdbg->pfd = 0; return; @@ -315,43 +304,6 @@ static void winnt_get_modules(struct winnt_process * pidinfo) mark += sprintf(mark,"\n"); } -static void winnt_fetch_registers ( - struct target_ops * t, - struct regcache * rcache, - int regnum) -{ - pid_t pid; - pid_t tid; - struct winnt_process * pidinfo; - - pid = inferior_ptid.pid; - tid = inferior_ptid.tid; - - if (!(pidinfo = winnt_process_record(pid))) - winnt_perror("internal error: record not found",pid); - - if (sizeof(uintptr_t) == 8) - amd64_winnt_fetch_registers( - pidinfo->pfd, - rcache,regnum, - tid); - else - i386_winnt_fetch_registers( - pidinfo->pfd, - rcache,regnum, - tid); -} - -static void winnt_store_registers ( - struct target_ops * t, - struct regcache * rcache, - int regnum) -{ - (void)t; - (void)rcache; - (void)regnum; -} - ssize_t winnt_xfer_solibs( struct winnt_process * pidinfo, gdb_byte * readbuf, @@ -495,6 +447,73 @@ static void winnt_xclose (struct target_ops * t) { } +static void winnt_set_thread_context_state(struct winnt_thread * thread, int state) +{ + thread->regctx.uc_context_flags = state; +} + +static void winnt_add_thread(int pfd, ptid_t ptid) +{ + pid_t pid; + struct winnt_process * pidinfo; + struct winnt_thread * thread; + mcontext_t * tctx; + uint32_t dr_rtm_mask = (1 << 16); + + pid = ptid_get_pid(inferior_ptid); + pidinfo = winnt_process_record(pid); + + if (!(thread = (struct winnt_thread *)calloc(1,sizeof(*thread)))) + winnt_perror("could not allocate thread record.",pid); + + if (__dbg_regs_fetch(pfd,ptid.tid,&thread->regctx) < 0) + winnt_perror("could not fetch registers for thread.",pid); + + tctx = &thread->regctx; + tctx->uc_dr0 = pidinfo->dr_cache[0]; + tctx->uc_dr1 = pidinfo->dr_cache[1]; + tctx->uc_dr2 = pidinfo->dr_cache[2]; + tctx->uc_dr3 = pidinfo->dr_cache[3]; + tctx->uc_dr6 = dr_rtm_mask; + tctx->uc_dr7 = pidinfo->dr_cache[7]; + + winnt_set_thread_context_state( + thread, + WINNT_THREAD_CONTEXT_READY); + + if (__dbg_regs_store(pfd,ptid.tid,tctx) < 0) + winnt_perror("could not store registers for thread.",pid); + + thread->next = pidinfo->threads; + pidinfo->threads = thread; + + thread->process = pidinfo; + thread->tid = ptid.tid; + + add_thread(ptid); +} + +static struct winnt_thread * winnt_get_thread(struct winnt_process * pidinfo, pid_t tid) +{ + struct winnt_thread * thread; + + for (thread=pidinfo->threads; thread; thread=thread->next) + if (thread->tid == tid) + return thread; + + return 0; +} + +static struct winnt_thread * winnt_get_thread_from_ptid(ptid_t ptid) +{ + struct winnt_process * pidinfo; + + if ((pidinfo = winnt_process_record(ptid.pid))) + return winnt_get_thread(pidinfo,ptid.tid); + + return 0; +} + static void winnt_respond (int pfd, struct __dbg_event * event, int response) { ptid_t ptid; @@ -504,12 +523,12 @@ static void winnt_respond (int pfd, struct __dbg_event * event, int response) switch (event->evttype) { case __DBG_STATE_CREATE_PROCESS: ptid = ptid_build(event->syspid,0,event->systid); - add_thread(ptid); + winnt_add_thread(pfd,ptid); break; case __DBG_STATE_CREATE_THREAD: ptid = ptid_build(event->syspid,0,event->systid); - add_thread(ptid); + winnt_add_thread(pfd,ptid); break; default: @@ -589,6 +608,39 @@ static void winnt_prepare (struct target_ops * t, pid_t pid, int pfd, int attach } } +static void winnt_fetch_registers ( + struct target_ops * t, + struct regcache * rcache, + int regnum) +{ + pid_t tid; + struct winnt_thread * thread; + + tid = inferior_ptid.tid; + + if (!(thread = winnt_get_thread_from_ptid(inferior_ptid))) + winnt_perror("internal error: thread record not found",tid); + + if (sizeof(uintptr_t) == 8) + amd64_winnt_fetch_registers( + rcache,regnum, + thread); + else + i386_winnt_fetch_registers( + rcache,regnum, + thread); +} + +static void winnt_store_registers ( + struct target_ops * t, + struct regcache * rcache, + int regnum) +{ + (void)t; + (void)rcache; + (void)regnum; +} + static void winnt_attach (struct target_ops * t, const char * args, int from_tty) { pid_t pid; diff --git a/overlay/mgdb/gdb/winnt-nat.h b/overlay/mgdb/gdb/winnt-nat.h new file mode 100644 index 0000000..c99d3f4 --- /dev/null +++ b/overlay/mgdb/gdb/winnt-nat.h @@ -0,0 +1,57 @@ +/***************************************************************/ +/* mgdb: midipix-specific bits for gdb */ +/* Copyright (C) 2019 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.MGDB. */ +/***************************************************************/ + +#ifndef WINNT_NAT_H +#define WINNT_NAT_H + +#include +#include +#include +#include +#include + +#define WINNT_DR_STATE_DIRTY (0x1) + +#define WINNT_THREAD_CONTEXT_READY (0X0) +#define WINNT_THREAD_CONTEXT_DIRTY (0Xffffffff) + +struct regcache; + +struct winnt_process; +struct winnt_thread; + +struct winnt_process { + int pfd; + pid_t pid; + pid_t syspid; + pid_t systid; + pid_t flags; + int nmodules; + struct __dbg_module_info * modules; + struct __dbg_event event; + char * solibs; + uintptr_t dr_cache[8]; + uint32_t dr_state; + struct winnt_thread * threads; +}; + +struct winnt_thread { + struct winnt_thread * next; + struct winnt_process * process; + pid_t tid; + uint32_t state; + mcontext_t regctx; +}; + +void amd64_winnt_fetch_registers( + struct regcache *, int regnum, + struct winnt_thread *); + +void i386_winnt_fetch_registers( + struct regcache *, int regnum, + struct winnt_thread *); + +#endif -- cgit v1.2.3