/***************************************************************/ /* mgdb: midipix-specific bits for gdb */ /* Copyright (C) 2019 Z. Gilboa */ /* Released under GPLv2 and GPLv3; see COPYING.MGDB. */ /***************************************************************/ #include "defs.h" #include "osabi.h" #include "config.h" #include "target.h" #include "utils.h" #include "inferior.h" #include "inf-child.h" #include "x86-nat.h" #include #include #include #include #include #include #define winnt_error(msg) \ error("%s(): %s.",__FUNCTION__,msg) #define winnt_perror(msg,pid) \ error("%s(): %s (pid %d).",__FUNCTION__,msg,pid) struct winnt_process { int pfd; pid_t pid; }; static size_t pcnt; static winnt_process * plist; static winnt_process * winnt_plist_expand (void) { struct winnt_process * pnew; struct winnt_process * pold; size_t idx; if (!(pnew = (struct winnt_process *)calloc(pcnt+32, sizeof(*pnew)))) return 0; memcpy( pnew,plist, pcnt*sizeof(*plist)); pold = plist; plist = pnew; pcnt += 32; free(pold); return pnew; } static int winnt_plist_add (pid_t pid, int pfd) { struct winnt_process * pdbg; struct winnt_process * pcap; for (pdbg=plist, pcap=&plist[pcnt]; pdbgpid) { pdbg->pid = pid; pdbg->pfd = pfd; return 0; } } return winnt_plist_expand() ? winnt_plist_add(pid,pfd) : -1; } static void winnt_plist_remove (pid_t pid) { struct winnt_process * pdbg; struct winnt_process * pcap; for (pdbg=plist, pcap=&plist[pcnt]; pdbgpid == pid) { pdbg->pid = 0; return; } } } static int winnt_pfd_from_pid (pid_t pid) { winnt_process * pdbg; winnt_process * pcap; for (pdbg=plist, pcap=&plist[pcnt]; pdbgpid == pid) return pdbg->pfd; return -1; } static nfds_t winnt_poll_one_init (struct pollfd * pfds, pid_t pid) { winnt_process * pdbg; winnt_process * pcap; for (pdbg=plist, pcap=&plist[pcnt]; pdbgpid == pid) { pfds->fd = pdbg->pfd; pfds->events = POLLIN; return 1; } } return 0; } static nfds_t winnt_poll_init (struct pollfd * pfds) { winnt_process * pdbg; winnt_process * pcap; struct pollfd * pfd; for (pfd=pfds, pdbg=plist, pcap=&plist[pcnt]; pdbgpid) { pfd->fd = pdbg->pfd; pfd->events = POLLIN; pfd++; } } return pfd - pfds; } static void winnt_close (struct target_ops * t) { } static void winnt_xclose (struct target_ops * t) { } static void winnt_attach (struct target_ops * t, const char * args, int from_tty) { pid_t pid; int pfd; if ((pid = parse_pid_to_attach(args)) < 0) { winnt_error ("cannot parse pid to attach"); } if ((pfd = __dbg_attach(pid)) < 0) { winnt_perror ("cannot attach to process",pid); } if (__dbg_rbreak(pfd) < 0) { __dbg_detach(pfd); close(pfd); winnt_perror ("could not issue a breakpoint in process",pid); } if (winnt_plist_add(pid,pfd) < 0) { __dbg_detach(pfd); close(pfd); winnt_error ("could not expand debuggee list"); } } static void winnt_detach (struct target_ops * t, const char * args, int from_tty) { pid_t pid; int pfd; if ((pid = ptid_get_pid(inferior_ptid)) < 0) winnt_error ("cannot parse pid to detach"); if ((pfd = winnt_pfd_from_pid(pid)) < 0) winnt_perror ("debuggee record does not exist",pid); if (__dbg_detach(pfd) < 0) winnt_perror ("could not attach from process",pid); if (close(pfd) < 0) winnt_perror ("failed to close process file descriptor",pid); winnt_plist_remove(pid); x86_cleanup_dregs(); } static ptid_t winnt_wait( struct target_ops * t, ptid_t ptid, struct target_waitstatus * waitstatus, int target_options) { struct __dbg_event dbgevent; struct pollfd pollfdbuf[512]; struct pollfd * pfds; struct pollfd * pfd; nfds_t nfds,i; if (pcnt*sizeof(*pfds) < sizeof(pollfdbuf)) pfds = pollfdbuf; else if (!(pfds = (struct pollfd *)calloc(pcnt,sizeof(*pfds)))) return null_ptid; nfds = (ptid.pid > 0) ? winnt_poll_one_init(pfds,ptid.pid) : winnt_poll_init(pfds); if (poll(pfds,nfds,-1) < 0) return null_ptid; for (i=0, pfd=0; ifd,&dbgevent) < 0) return null_ptid; return ptid_build( dbgevent.cpid ? dbgevent.cpid : dbgevent.syspid, 0, dbgevent.ctid ? dbgevent.ctid : dbgevent.systid); } static void winnt_resume ( struct target_ops * t, ptid_t ptid, int step, enum gdb_signal sig) { } static void winnt_kill (struct target_ops * t) { /* current_inferior() */ } static void winnt_mourn_inferior (struct target_ops * t) { /* update plist, etc. */ } static void winnt_create_inferior( struct target_ops * ops, char * exec_file, char * allargs, char ** in_env, int from_tty) { winnt_error("Not implemented"); } static target_ops * winnt_target_alloc (void) { target_ops * t = inf_child_target(); t->to_attach_no_wait = 1; t->to_has_thread_control = 1; t->to_close = winnt_close; t->to_xclose = winnt_xclose; t->to_attach = winnt_attach; t->to_detach = winnt_detach; t->to_wait = winnt_wait; t->to_resume = winnt_resume; t->to_kill = winnt_kill; t->to_mourn_inferior = winnt_mourn_inferior; t->to_create_inferior = winnt_create_inferior; x86_use_watchpoints(t); return t; } extern initialize_file_ftype _initialize_winnt_nat; void _initialize_winnt_nat(void) { add_target(winnt_target_alloc()); }