Hi, On Sat, Sep 7, 2013 at 2:53 AM, Pedro Alves <pal...@redhat.com> wrote: > This is what I meant: > https://sourceware.org/ml/gdb-patches/2013-09/msg00253.html > > I was thinking you'd wrap gnu_xfer_memory. >
I have study your patch, but I found there is no to_xfer_partial field or something similar in gdbserver's structure target_obj, how can I do? Please give me more hints, thanks. > But I have to say I don't really understand the real need for > all those: > > task_t task = (gnu_current_inf > ? (gnu_current_inf->task > ? gnu_current_inf->task->port : 0) > : 0); > int res; > > if (task == MACH_PORT_NULL) > return 0; > > checks in the existing code. I mean, why would we reach here with > an invalid inferior/task/port selected? > It just reads as workaround for some bug to me. Honestly to say, I have copied them from function gnu_xfer_memory. But I think, before reference a pointer, check whether it was a NULL seems not a bad way :-). And this is my update patch which is base on the current upstream master branch. ====================================================================== gdbserver * configure.ac (host_makefile_frag): New rule for GNU/Hurd to load i386gnu.mh. * configure.srv (srv_tgtobj): Add gnu-nat.o i386gnu-nat.o. for GNU/Hurd. (srv_regobj): Add $(srv_i386_regobj) for GNU/Hurd. (srv_xmlfiles): Add $(srv_i386_xmlfiles) for GNU/Hurd. * configure: Regenerate. * Makefile.in (OBS): Add $(NATDEPFILES). (generated_files): Add $(NAT_GENERATED_FILES). (@host_makefile_frag@): New rule, add i386gnu.mh. (MIG): New tools. (AWK): New tools. * utils.c (host_address_to_string): New functions, copy from [gdb]/gdb/utils.c. diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index 1805e5a..6da44d1 100644 --- a/gdb/gdbserver/Makefile.in +++ b/gdb/gdbserver/Makefile.in @@ -50,6 +50,8 @@ INSTALL_DATA = @INSTALL_DATA@ RANLIB = @RANLIB@ CC = @CC@ +MIG = @MIG@ +AWK = @AWK@ # Dependency tracking information. DEPMODE = @CCDEPMODE@ @@ -176,7 +178,7 @@ OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o \ target.o waitstatus.o utils.o version.o vec.o gdb_vecs.o \ mem-break.o hostio.o event-loop.o tracepoint.o xml-utils.o \ common-utils.o ptid.o buffer.o format.o filestuff.o dll.o notif.o \ - tdesc.o $(XML_BUILTIN) $(DEPFILES) $(LIBOBJS) + tdesc.o $(XML_BUILTIN) $(DEPFILES) $(LIBOBJS) $(NATDEPFILES) GDBREPLAY_OBS = gdbreplay.o version.o GDBSERVER_LIBS = @GDBSERVER_LIBS@ XM_CLIBS = @LIBS@ @@ -199,6 +201,11 @@ CLEANDIRS = $(SUBDIRS) # The format here is for the `case' shell command. REQUIRED_SUBDIRS = $(GNULIB_BUILDDIR) +# Host-dependent makefile fragment comes in here. +GDBSERVER_HURD=@GDBSERVER_HURD@ +@host_makefile_frag@ +# End of host-dependent makefile fragment + FLAGS_TO_PASS = \ "prefix=$(prefix)" \ "exec_prefix=$(exec_prefix)" \ @@ -232,7 +239,7 @@ FLAGS_TO_PASS = \ "RUNTESTFLAGS=$(RUNTESTFLAGS)" # All generated files which can be included by another file. -generated_files = config.h $(GNULIB_H) +generated_files = config.h $(GNULIB_H) $(NAT_GENERATED_FILES) .c.o: $(COMPILE) $< @@ -522,6 +529,16 @@ mips-linux-watch.o: ../common/mips-linux-watch.c $(COMPILE) $< $(POSTCOMPILE) +ifdef GDBSERVER_HURD +#fixme, if use i386gnu-nat.o here will complain that can't find rule for target i386gnu-gnu.c +i386gnu-nat_foo.o: $(srcdir)/../i386gnu-nat.c + $(COMPILE) $< + $(POSTCOMPILE) +gnu-nat.o: $(srcdir)/../gnu-nat.c + $(COMPILE) $< + $(POSTCOMPILE) +endif + # Native object files rules from ../nat linux-waitpid.o: ../nat/linux-waitpid.c @@ -535,6 +552,9 @@ linux-waitpid.o: ../nat/linux-waitpid.c vasprintf.o: $(srcdir)/../../libiberty/vasprintf.c $(COMPILE) $< -DHAVE_CONFIG_H $(POSTCOMPILE) +obstack.o: $(srcdir)/../../libiberty/obstack.c + $(COMPILE) $< -DHAVE_CONFIG_H + $(POSTCOMPILE) vsnprintf.o: $(srcdir)/../../libiberty/vsnprintf.c $(COMPILE) $< $(POSTCOMPILE) diff --git a/gdb/gdbserver/configure.ac b/gdb/gdbserver/configure.ac index 456a1f7..7d4eb75 100644 --- a/gdb/gdbserver/configure.ac +++ b/gdb/gdbserver/configure.ac @@ -471,6 +471,31 @@ if $want_ipa ; then fi fi +frags= +GDBSERVER_HURD=1 +case $host_os in + gnu*) + #Needed for GNU Hurd hosts. + AC_PROG_AWK + AC_CHECK_TOOL(MIG, mig) + if test x"$MIG" = x; then + AC_MSG_ERROR([MIG not found but required for $host hosts]) + fi + host_makefile_frag=${srcdir}/../config/i386/i386gnu.mh + if test ! -f ${host_makefile_frag}; then + AC_MSG_ERROR("*** Gdb does not support native target ${host}") + fi + frags="$frags $host_makefile_frag" + ;; + *) + host_makefile_frag=/dev/null + ;; +esac + +AC_SUBST_FILE(host_makefile_frag) +AC_SUBST(frags) +AC_SUBST(GDBSERVER_HURD) + AC_SUBST(GDBSERVER_DEPFILES) AC_SUBST(GDBSERVER_LIBS) AC_SUBST(srv_xmlbuiltin) diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv index b3c0421..d370e4a 100644 --- a/gdb/gdbserver/configure.srv +++ b/gdb/gdbserver/configure.srv @@ -116,6 +116,10 @@ case "${target}" in srv_linux_btrace=yes ipa_obj="${ipa_i386_linux_regobj} linux-i386-ipa.o" ;; + i[34567]86-*-gnu*) srv_regobj="$srv_i386_regobj" + srv_tgtobj="" + srv_xmlfiles="$srv_i386_xmlfiles" + ;; i[34567]86-*-lynxos*) srv_regobj="i386.o" srv_tgtobj="lynx-low.o lynx-i386-low.o" srv_xmlfiles="i386/i386.xml" diff --git a/gdb/gdbserver/utils.c b/gdb/gdbserver/utils.c index 9706d74..a181d06 100644 --- a/gdb/gdbserver/utils.c +++ b/gdb/gdbserver/utils.c @@ -181,6 +181,15 @@ get_cell (void) return buf[cell]; } +const char * +host_address_to_string (const void *addr) +{ + char *str = get_cell (); + + xsnprintf (str, CELLSIZE, "0x%s", phex_nz ((unsigned long long) addr, sizeof (addr))); + return str; +} + static char * decimal2str (char *sign, ULONGEST addr) { ====================================================================== gdb * configure.tgt: Set build_gdbserver=yes for GNU/Hurd hosts. * configure: Regenerate. * config/i386/i386gnu.mh: Add #ifdef to determine which rule to use in gdbserver. * i386gnu-nat.c: Add macor GDBSERVER to support build gdbserver. * gnu-nat.h: Add macor GDBSERVER to support build gdbserver. * gnu-nat.c: Add macor GDBSERVER to support build gdbserver. (gnu_kill): New function, used in gdbserver. (gnu_mourn): New function, clean up after inferior dies, used in gdbserver. (gnu_create_inferior): New function, use for create inferior in gdbserver. (gnu_attach): New function, a placeholder. (gnu_detach): New function, used in gdbserver detach from inferior. (gnu_thread_alive): New function, call find_thread_ptid(). (gnu_ptid_build): New function, build structure ptid_t from pid, and tid when has GDBSERVER defined. (gnu_get_tid): New function, return lwp from structure ptid_t,when has GDBSERVER defined. (gnu_add_process): New function, add a new process to process list. (gnu_join): New function, a placeholder. (gnu_resume_wrap): New function, a wrap function, just call gnu_resume(). (gnu_wait_wrap): New function, a wrap function, just call gnu_wait(). (gnu_fetch_registers_wrap): New function, a wrap function, just call gnu_fetch_registers(). (gnu_store_registers_wrap): New function, a wrap function, just call gnu_store_registers(). (gnu_read_memory): New function, a wrap function, just call gnu_read_inferior(). (gnu_write_memory): New function, a wrap function, just call gnu_write_inferior(). (gnu_request_interrupt): New function, used in gdbserver. (store_waitstatus): New function, helper function, copy from [gdb]/gdb/inf-child.c. (initialize_low): New function, use for initialize gdbserver's target_ops. (initialize_low_arch): New function, used by initialize_low(). (_initialize_gnu_nat): New function, used by initialize_low(). diff --git a/gdb/config/i386/i386gnu.mh b/gdb/config/i386/i386gnu.mh index a3ea122..4b9d64d 100644 --- a/gdb/config/i386/i386gnu.mh +++ b/gdb/config/i386/i386gnu.mh @@ -1,5 +1,6 @@ # Host: Intel 386 running the GNU Hurd -NATDEPFILES= i386gnu-nat.o gnu-nat.o core-regset.o fork-child.o \ +ifndef GDBSERVER_HURD +NATDEPFILES= gnu-nat.o i386gnu-nat.o core-regset.o fork-child.o \ notify_S.o process_reply_S.o msg_reply_S.o \ msg_U.o exc_request_U.o exc_request_S.o HAVE_NATIVE_GCORE_HOST = 1 @@ -12,22 +13,41 @@ XM_CLIBS = -lshouldbeinlibc # Use our own user stubs for the msg rpcs, so we can make them time out, in # case the program is fucked, or we guess the wrong signal thread. msg-MIGUFLAGS = -D'MSG_IMPORTS=waittime 1000;' +else +NATDEPFILES= gnu-nat.o i386gnu-nat_foo.o obstack.o notify_S.o process_reply_S.o msg_reply_S.o \ + exc_request_U.o exc_request_S.o +endif # ick MIGCOM = $(MIG) -cc cat - /dev/null # Reply servers need special massaging of the code mig generates, to make # them work correctly for error returns in some cases. +ifndef GDBSERVER_HURD %_reply_S.h %_reply_S.c: %_reply.defs $(CPP) $(CPPFLAGS) -DSERVERPREFIX=S_ -x c $< \ | $(MIGCOM) -sheader $*_reply_S.h -server $*_reply_S.raw -user /dev/null -header /dev/null \ && $(AWK) -f $(srcdir)/reply_mig_hack.awk < $*_reply_S.raw > $*_reply_S.c +else +%_reply_S.h %_reply_S.c: %_reply.defs + $(CPP) $(CPPFLAGS) -DSERVERPREFIX=S_ -x c $< \ + | $(MIGCOM) -sheader $*_reply_S.h -server $*_reply_S.raw -user /dev/null -header /dev/null \ + && $(AWK) -f $(srcdir)/../reply_mig_hack.awk < $*_reply_S.raw > $*_reply_S.c +endif # Normal servers +ifndef GDBSERVER_HURD %_S.h %_S.c: %.defs +else +%_S.h %_S.c: $(srcdir)/../%.defs +endif $(CPP) $(CPPFLAGS) -DSERVERPREFIX=S_ -x c $< \ | $(MIGCOM) -sheader $*_S.h -server $*_S.c -user /dev/null -header /dev/null # User rpc stubs +ifndef GDBSERVER_HURD %_U.h %_U.c: %.defs +else +%_U.h %_U.c: $(srcdir)/../%.defs +endif $(CPP) $(CPPFLAGS) $($*-MIGUFLAGS) -x c $< \ | $(MIGCOM) -sheader /dev/null -server /dev/null -user $*_U.c -header $*_U.h diff --git a/gdb/configure.tgt b/gdb/configure.tgt index 95c7217..e841a9a 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -231,6 +231,7 @@ i[34567]86-*-linux*) i[34567]86-*-gnu*) # Target: Intel 386 running the GNU Hurd gdb_target_obs="i386-tdep.o i387-tdep.o i386gnu-tdep.o solib-svr4.o" + build_gdbserver=yes ;; i[34567]86-*-cygwin*) # Target: Intel 386 running win32 diff --git a/gdb/gnu-nat.c b/gdb/gnu-nat.c index 59d2f23..9e37e2b 100644 --- a/gdb/gnu-nat.c +++ b/gdb/gnu-nat.c @@ -20,29 +20,16 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#ifndef GDBSERVER #include "defs.h" #include <ctype.h> #include <errno.h> -#include <limits.h> #include <setjmp.h> #include <signal.h> #include <stdio.h> #include "gdb_string.h" -#include <sys/ptrace.h> - -#include <mach.h> -#include <mach_error.h> -#include <mach/exception.h> -#include <mach/message.h> -#include <mach/notify.h> -#include <mach/vm_attributes.h> -#include <hurd.h> -#include <hurd/interrupt.h> -#include <hurd/msg.h> -#include <hurd/msg_request.h> -#include <hurd/process.h> /* Defined in <hurd/process.h>, but we need forward declarations from <hurd/process_request.h> as well. */ #undef _process_user_ @@ -56,25 +43,63 @@ #include "symtab.h" #include "value.h" #include "language.h" -#include "target.h" -#include "gdb_wait.h" #include "gdbcmd.h" #include "gdbcore.h" #include "gdbthread.h" #include "gdb_assert.h" -#include "gdb_obstack.h" -#include "gnu-nat.h" #include "inf-child.h" +#include "exc_request_U.h" +#include "msg_U.h" + +#else /* GDBSERVER */ +#include "server.h" + +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <signal.h> +#endif /* GDBSERVER */ + +#include "target.h" + +#include <limits.h> +#include <sys/ptrace.h> +#include "gdb_obstack.h" +#include "gdb_wait.h" + +#include <mach.h> +#include <mach_error.h> +#include <mach/exception.h> +#include <mach/message.h> + +#include <mach/notify.h> +#include <mach/vm_attributes.h> + +#include <hurd.h> +#include <hurd/interrupt.h> +#include <hurd/msg.h> +#include <hurd/msg_request.h> +#include <hurd/process.h> + +#include "gnu-nat.h" #include "exc_request_S.h" #include "notify_S.h" #include "process_reply_S.h" #include "msg_reply_S.h" -#include "exc_request_U.h" -#include "msg_U.h" static process_t proc_server = MACH_PORT_NULL; +#ifdef GDBSERVER +/* this should move into i386gnu-nat.c ?*/ +/* Defined in auto-generated file i386.c. */ +extern void init_registers_i386 (void); +extern const struct target_desc *tdesc_i386; +const struct target_desc *gnu_tdesc; +int using_threads = 1; +ptid_t inferior_ptid; +static struct target_ops gnu_target_ops; +#endif /* If we've sent a proc_wait_request to the proc server, the pid of the process we asked about. We can only ever have one outstanding. */ @@ -114,6 +139,9 @@ void inf_continue (struct inf *inf); debug ("{inf %d %s}: " msg, __inf->pid, \ host_address_to_string (__inf) , ##args); } while (0) +#ifdef GDBSERVER +static struct process_info * gnu_add_process (int pid, int attached); +#endif void proc_abort (struct proc *proc, int force); struct proc *make_proc (struct inf *inf, mach_port_t port, int tid); struct proc *_proc_free (struct proc *proc); @@ -145,6 +173,13 @@ int proc_trace (struct proc *proc, int set); __e; }) \ : EIEIO) +#ifdef GDBSERVER +struct process_info_private +{ + struct inf *inf; +}; +#endif + /* The state passed by an exception message. */ struct exc_state @@ -242,6 +277,25 @@ struct inf int want_exceptions; }; +static ptid_t +gnu_ptid_build (int pid, long lwp, long tid) +{ +#ifndef GDBSERVER + return ptid_build (pid, lwp, tid); +#else + return ptid_build (pid, tid, lwp); +#endif +} + +long +gnu_get_tid (ptid_t ptid) +{ +#ifndef GDBSERVER + return ptid_get_tid(ptid); +#else + return ptid_get_lwp (ptid); +#endif +} int __proc_pid (struct proc *proc) @@ -855,6 +909,7 @@ inf_validate_task_sc (struct inf *inf) if (inf->task->cur_sc < suspend_count) { +#ifndef GDBSERVER //need fix, I am not sure whether gdbserver need this or not? int abort; target_terminal_ours (); /* Allow I/O. */ @@ -865,7 +920,7 @@ inf_validate_task_sc (struct inf *inf) if (abort) error (_("Additional task suspend count left untouched.")); - +#endif inf->task->cur_sc = suspend_count; } } @@ -1056,6 +1111,12 @@ inf_validate_procs (struct inf *inf) if (!left) { proc_debug (thread, "died!"); +#ifdef GDBSERVER + ptid_t ptid; + ptid = gnu_ptid_build (inf->pid, 0, thread->tid); + if (find_thread_ptid (ptid)) + remove_thread (find_thread_ptid (ptid)); +#endif thread->port = MACH_PORT_NULL; thread = _proc_free (thread); /* THREAD is dead. */ if (last) @@ -1083,10 +1144,11 @@ inf_validate_procs (struct inf *inf) last = thread; proc_debug (thread, "new thread: %d", threads[i]); - ptid = ptid_build (inf->pid, 0, thread->tid); + ptid = gnu_ptid_build (inf->pid, 0, thread->tid); /* Tell GDB's generic thread code. */ +#ifndef GDBSERVER if (ptid_equal (inferior_ptid, pid_to_ptid (inf->pid))) /* This is the first time we're hearing about thread ids, after a fork-child. */ @@ -1096,6 +1158,15 @@ inf_validate_procs (struct inf *inf) add_thread_silent (ptid); else add_thread (ptid); +#else + if (!find_thread_ptid (ptid)) + { + debug ("New thread, pid=%d, tid=%d\n", inf->pid, + thread->tid); + add_thread (ptid, thread); + //inferior_ptid = ptid; /* need fix; seems this line not need, but I can't explain why*/ + } +#endif } } @@ -1221,6 +1292,7 @@ inf_set_threads_resume_sc_for_signal_thread (struct inf *inf) return 0; } +#ifndef GDBSERVER static void inf_update_signal_thread (struct inf *inf) { @@ -1229,6 +1301,7 @@ inf_update_signal_thread (struct inf *inf) inf->signal_thread = inf->threads ? inf->threads->next : 0; } +#endif /* Detachs from INF's inferior task, letting it run once again... */ void @@ -1284,6 +1357,7 @@ inf_attach (struct inf *inf, int pid) inf_startup (inf, pid); } +#ifndef GDBSERVER /* Makes sure that we've got our exception ports entrenched in the process. */ void @@ -1314,6 +1388,7 @@ inf_restore_exc_ports (struct inf *inf) for (thread = inf->threads; thread; thread = thread->next) proc_restore_exc_port (thread); } +#endif /* Deliver signal SIG to INF. If INF is stopped, delivering a signal, even @@ -1613,19 +1688,17 @@ rewait: thread = inf->wait.thread; if (thread) - ptid = ptid_build (inf->pid, 0, thread->tid); + ptid = gnu_ptid_build (inf->pid, 0, thread->tid); else if (ptid_equal (ptid, minus_one_ptid)) thread = inf_tid_to_thread (inf, -1); else - thread = inf_tid_to_thread (inf, ptid_get_tid (ptid)); + thread = inf_tid_to_thread (inf, gnu_get_tid (ptid)); if (!thread || thread->port == MACH_PORT_NULL) { /* TID is dead; try and find a new thread. */ if (inf_update_procs (inf) && inf->threads) - ptid = ptid_build (inf->pid, 0, inf->threads->tid); /* The first - available - thread. */ + ptid = gnu_ptid_build (inf->pid, 0, inf->threads->tid);/* The first available thread*/ else ptid = inferior_ptid; /* let wait_for_inferior handle exit case */ } @@ -1651,6 +1724,12 @@ rewait: : "?", status->value.integer); +#ifdef GDBSERVER + inferior_ptid = ptid; +/* why this? because in gdb, the inferior_ptid is used in all over world, + if gdbserver use another one to do the same thing, we will need a lot of +#ifdef GDBSERVER in this file, so we re-used this in gdbserver */ +#endif return ptid; } @@ -2022,7 +2101,7 @@ gnu_resume (struct target_ops *ops, else /* Just allow a single thread to run. */ { - struct proc *thread = inf_tid_to_thread (inf, ptid_get_tid (ptid)); + struct proc *thread = inf_tid_to_thread (inf, gnu_get_tid (ptid)); if (!thread) error (_("Can't run single thread id %s: no such thread!"), @@ -2033,7 +2112,7 @@ gnu_resume (struct target_ops *ops, if (step) { - step_thread = inf_tid_to_thread (inf, ptid_get_tid (ptid)); + step_thread = inf_tid_to_thread (inf, gnu_get_tid (ptid)); if (!step_thread) warning (_("Can't step thread id %s: no such thread."), target_pid_to_str (ptid)); @@ -2047,6 +2126,7 @@ gnu_resume (struct target_ops *ops, inf_resume (inf); } +#ifndef GDBSERVER static void gnu_kill_inferior (struct target_ops *ops) @@ -2061,8 +2141,29 @@ gnu_kill_inferior (struct target_ops *ops) } target_mourn_inferior (); } +#else +static int +gnu_kill (int pid) +{ + struct proc *task = gnu_current_inf->task; + struct process_info *process; + + process = find_process_pid (pid); + + if (task) + { + proc_debug (task, "terminating..."); + task_terminate (task->port); + inf_set_pid (gnu_current_inf, -1); + } + the_target->mourn (process); + return 0; +} +#endif + /* Clean up after the inferior dies. */ +#ifndef GDBSERVER static void gnu_mourn_inferior (struct target_ops *ops) { @@ -2071,6 +2172,17 @@ gnu_mourn_inferior (struct target_ops *ops) unpush_target (ops); generic_mourn_inferior (); } +#else +static void +gnu_mourn (struct process_info *process) +{ + /* Free our private data. */ + free (process->private); + process->private = NULL; + + clear_inferiors (); +} +#endif /* Fork an inferior process, and start debugging it. */ @@ -2095,6 +2207,7 @@ cur_inf (void) return gnu_current_inf; } +#ifndef GDBSERVER static void gnu_create_inferior (struct target_ops *ops, char *exec_file, char *allargs, char **env, @@ -2148,10 +2261,35 @@ gnu_create_inferior (struct target_ops *ops, else inf_restore_exc_ports (inf); } +#else +static int +gnu_create_inferior (char *program, char **allargs) +{ + int pid; + pid = fork (); + if (pid < 0) + perror_with_name ("fork"); + + if (pid == 0) + { + ptrace (PTRACE_TRACEME); + setpgid (0, 0); + execv (program, allargs); + + fprintf (stderr, "Cannot exec %s: %s.\n", program, strerror (errno)); + fflush (stderr); + _exit (0177); + } + + gnu_add_process (pid, 0); + return pid; +} +#endif /* Attach to process PID, then initialize for debugging it and wait for the trace-trap that results from attaching. */ +#ifndef GDBSERVER static void gnu_attach (struct target_ops *ops, char *args, int from_tty) { @@ -2207,6 +2345,13 @@ gnu_attach (struct target_ops *ops, char *args, int from_tty) renumber_threads (0); /* Give our threads reasonable names. */ #endif } +#else +static int +gnu_attach (unsigned long pid) +{ + return -1; //not support now +} +#endif /* Take a program previously attached to and detaches it. @@ -2216,6 +2361,7 @@ gnu_attach (struct target_ops *ops, char *args, int from_tty) to work, it may be necessary for the process to have been previously attached. It *might* work if the program was started via fork. */ +#ifndef GDBSERVER static void gnu_detach (struct target_ops *ops, char *args, int from_tty) { @@ -2255,6 +2401,23 @@ gnu_stop (ptid_t ptid) { error (_("to_stop target function not implemented")); } +#else +static int +gnu_detach (int pid) +{ + struct process_info *process; + + process = find_process_pid (pid); + if (process == NULL) + return -1; + + inf_detach (gnu_current_inf); + + inferior_ptid = null_ptid; + the_target->mourn (process); + return 0; +} +#endif static int gnu_thread_alive (struct target_ops *ops, ptid_t ptid) @@ -2454,7 +2617,9 @@ gnu_write_inferior (task_t task, CORE_ADDR addr, char *myaddr, int length) out: if (deallocate) { +#ifdef GDBSERVER obstack_free (®ion_obstack, 0); +#endif (void) vm_deallocate (mach_task_self (), copied, @@ -2470,6 +2635,7 @@ out: return length; } +#ifndef GDBSERVER /* Return 0 on failure, number of bytes handled otherwise. TARGET is ignored. */ @@ -2576,6 +2742,7 @@ gnu_find_memory_regions (find_memory_region_ftype func, void *data) return 0; } +#endif /* Return printable description of proc. */ @@ -2592,6 +2759,7 @@ proc_string (struct proc *proc) return tid_str; } +#ifndef GDBSERVER static char * gnu_pid_to_str (struct target_ops *ops, ptid_t ptid) { @@ -3452,3 +3620,203 @@ flush_inferior_icache (CORE_ADDR pc, int amount) warning (_("Error flushing inferior's cache : %s"), safe_strerror (ret)); } #endif /* FLUSH_INFERIOR_CACHE */ + +#else +static struct process_info * +gnu_add_process (int pid, int attached) +{ + struct process_info *proc; + + proc = add_process (pid, attached); + proc->tdesc = gnu_tdesc; + proc->private = xcalloc (1, sizeof (*proc->private)); + proc->private->inf = cur_inf (); + struct inf *inf = gnu_current_inf; + + inf_attach (inf, pid); + inf->pending_execs = 2; + inf->nomsg = 1; + inf->traced = 1; + + inf_resume (inf); + + return proc; +} + +static void +gnu_join (int pid) +{ + /* doesn't need */ +} + +static void +gnu_resume_wrap (struct thread_resume *resume_info, size_t n) +{ + /* FIXME: Assume for now that n == 1. */ + ptid_t ptid = resume_info[0].thread; + const int step = (resume_info[0].kind == resume_step ? 1 : 0); //1 means step, 0 means contiune + const int signal = resume_info[0].sig; + if (ptid_equal (ptid, minus_one_ptid)) + ptid = thread_to_gdb_id (current_inferior); + + regcache_invalidate (); + + debug ("in gnu_resume: ptid=%d, step=%d, signal=%d\n", ptid, step, + signal); + gnu_resume (NULL, ptid, step, signal); +} + +static ptid_t +gnu_wait_wrap (ptid_t ptid, struct target_waitstatus *status, int target_options) +{ + ptid_t event_ptid; + debug ("gnu_wait: [%s]", target_pid_to_str (ptid)); + event_ptid = gnu_wait (NULL, ptid, status, target_options); + debug (" -> (status->kind = %d)\n", status->kind); + return event_ptid; +} + +void +gnu_fetch_registers_wrap (struct regcache *regcache, int regno) +{ + debug ("gnu_fetch_registers() regno=%d\n", regno); + return gnu_fetch_registers (NULL, regcache, regno); +} + +void +gnu_store_registers_wrap (struct regcache *regcache, int regno) +{ + debug ("gnu_store_registers() regno=%d\n", regno); + return gnu_store_registers (NULL, regcache, regno); +} + +static int +gnu_thread_alive_wrap (ptid_t ptid) +{ + return gnu_thread_alive(NULL, ptid); +} + +static int +gnu_read_memory (CORE_ADDR addr, unsigned char *myaddr, int length) +{ + int ret = 0; + task_t task = (gnu_current_inf + ? (gnu_current_inf->task + ? gnu_current_inf->task->port : 0) : 0); + if (task == MACH_PORT_NULL) + return 0; + ret = gnu_read_inferior (task, addr, myaddr, length); + if (length != ret) + { + debug ("gnu_read_inferior,length=%d, but return %d\n", length, ret); + return -1; + } + return 0; +} + +static int +gnu_write_memory (CORE_ADDR addr, const unsigned char *myaddr, int length) +{ + int ret = 0; + task_t task = (gnu_current_inf + ? (gnu_current_inf->task + ? gnu_current_inf->task->port : 0) : 0); + if (task == MACH_PORT_NULL) + return 0; + ret = gnu_write_inferior (task, addr, myaddr, length); + if (length != ret) + { + debug ("gnu_write_inferior,length=%d, but return %d\n", length, + ret); + return -1; + } + return 0; +} + +static void +gnu_request_interrupt (void) +{ + ptid_t inferior_ptid = thread_to_gdb_id (current_inferior); + kill (ptid_get_pid (inferior_ptid), SIGINT); +} + +/* Helper function for child_wait and the derivatives of child_wait. + HOSTSTATUS is the waitstatus from wait() or the equivalent; store our + translation of that in OURSTATUS. */ +void +store_waitstatus (struct target_waitstatus *ourstatus, int hoststatus) +{ + if (WIFEXITED (hoststatus)) + { + ourstatus->kind = TARGET_WAITKIND_EXITED; + ourstatus->value.integer = WEXITSTATUS (hoststatus); + } + else if (!WIFSTOPPED (hoststatus)) + { + ourstatus->kind = TARGET_WAITKIND_SIGNALLED; + ourstatus->value.sig = gdb_signal_from_host (WTERMSIG (hoststatus)); + } + else + { + ourstatus->kind = TARGET_WAITKIND_STOPPED; + ourstatus->value.sig = gdb_signal_from_host (WSTOPSIG (hoststatus)); + } +} + +static struct target_ops gnu_target_ops = { + gnu_create_inferior, + gnu_attach, + gnu_kill, + gnu_detach, + gnu_mourn, + gnu_join, + gnu_thread_alive_wrap, + gnu_resume_wrap, + gnu_wait_wrap, + gnu_fetch_registers_wrap, + gnu_store_registers_wrap, + NULL, /* prepare_to_access_memory */ + NULL, /* done_accessing_memory */ + gnu_read_memory, + gnu_write_memory, + NULL, /* look_up_symbols */ + gnu_request_interrupt, + NULL, /* read_auxv */ + NULL, /* insert_point */ + NULL, /* remove_point */ + NULL, /* stopped_by_watchpoint */ + NULL, /* stopped_data_address */ + NULL, /* read_offsets */ + NULL, /* get_tls_address */ + NULL, /* qxfer_spu */ + NULL, /* hostio_last_error */ + NULL, /* qxfer_osdata */ + NULL, /* qxfer_siginfo */ + NULL, /* supports_non_stop */ + NULL, /* async */ + NULL, /* start_non_stop */ + NULL, /* supports_multi_process */ + NULL, /* handle_monitor_command */ +}; + +void +_initialize_gnu_nat (void) +{ + proc_server = getproc (); +} + +static void +initialize_low_arch () +{ + init_registers_i386 (); + gnu_tdesc = tdesc_i386; +} + +void +initialize_low (void) +{ + set_target_ops (&gnu_target_ops); + initialize_low_arch (); + _initialize_gnu_nat (); +} +#endif diff --git a/gdb/gnu-nat.h b/gdb/gnu-nat.h index f896bd2..45f2d6b 100644 --- a/gdb/gnu-nat.h +++ b/gdb/gnu-nat.h @@ -93,13 +93,44 @@ extern char *proc_string (struct proc *proc); extern int gnu_debug_flag; +#ifndef GDBSERVER #define debug(msg, args...) \ do { if (gnu_debug_flag) \ fprintf_unfiltered (gdb_stdlog, "%s:%d: " msg "\r\n", \ __FILE__ , __LINE__ , ##args); } while (0) +#else +#define debug(msg, args...) \ + do { if (gnu_debug_flag) \ + printf ("%s:%d: " msg "\r\n", \ + __FILE__ , __LINE__ , ##args); } while (0) +#endif /* Create a prototype generic GNU/Hurd target. The client can override it with local methods. */ struct target_ops *gnu_target (void); +#ifdef GDBSERVER +#define THREAD_STATE_FLAVOR i386_REGS_SEGS_STATE +#define THREAD_STATE_SIZE i386_THREAD_STATE_COUNT +#define THREAD_STATE_SET_TRACED(state) \ + ((struct i386_thread_state *) (state))->efl |= 0x100 +#define THREAD_STATE_CLEAR_TRACED(state) \ + ((((struct i386_thread_state *) (state))->efl &= ~0x100), 1) + +#ifndef PIDGET +#define PIDGET(PTID) (ptid_get_pid (PTID)) +#endif + +static ptid_t gnu_ptid_build(int pid,long lwp,long tid); +long gnu_get_tid (ptid_t ptid); + +/* Return printable description of proc. */ +extern char *proc_string (struct proc *proc); + +#ifndef safe_strerror +#define safe_strerror(err) \ + "" +#endif +#endif + #endif /* __GNU_NAT_H__ */ diff --git a/gdb/i386gnu-nat.c b/gdb/i386gnu-nat.c index 0fd8d91..5d46255 100644 --- a/gdb/i386gnu-nat.c +++ b/gdb/i386gnu-nat.c @@ -17,24 +17,17 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#ifndef GDBSERVER #include "defs.h" #include "inferior.h" #include "floatformat.h" #include "regcache.h" #include "gdb_assert.h" -#include <errno.h> -#include <stdio.h> #include "gdb_string.h" -#include <mach.h> -#include <mach_error.h> -#include <mach/message.h> -#include <mach/exception.h> - #include "i386-tdep.h" -#include "gnu-nat.h" #include "i387-tdep.h" #ifdef HAVE_SYS_PROCFS_H @@ -42,6 +35,23 @@ # include "gregset.h" #endif +#else /* GDBSERVER */ +#include "server.h" +#include "target.h" +#include "gdb_wait.h" + +#define I386_NUM_GREGS 16 +#endif /* GDBSERVER */ + +#include <errno.h> +#include <stdio.h> + +#include <mach.h> +#include <mach_error.h> +#include <mach/message.h> +#include <mach/exception.h> +#include "gnu-nat.h" + /* Offset to the thread_state_t location where REG is stored. */ #define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg) @@ -78,6 +88,7 @@ static int creg_offset[] = static void fetch_fpregs (struct regcache *regcache, struct proc *thread) { +#ifndef GDBSERVER mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT; struct i386_float_state state; error_t err; @@ -101,8 +112,12 @@ fetch_fpregs (struct regcache *regcache, struct proc *thread) /* Supply the floating-point registers. */ i387_supply_fsave (regcache, -1, state.hw_state); } +#else + debug ("fetch_fpregs() not support now\n"); +#endif } +#ifndef GDBSERVER #ifdef HAVE_SYS_PROCFS_H /* These two calls are used by the core-regset.c code for reading ELF core files. */ @@ -120,9 +135,16 @@ supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregs) i387_supply_fsave (regcache, -1, fpregs); } #endif +#endif +extern struct inf *gnu_current_inf; +extern ptid_t inferior_ptid; /* Fetch register REGNO, or all regs if REGNO is -1. */ +#ifndef GDBSERVER static void +#else +void +#endif gnu_fetch_registers (struct target_ops *ops, struct regcache *regcache, int regno) { @@ -132,7 +154,7 @@ gnu_fetch_registers (struct target_ops *ops, inf_update_procs (gnu_current_inf); thread = inf_tid_to_thread (gnu_current_inf, - ptid_get_tid (inferior_ptid)); + gnu_get_tid (inferior_ptid)); if (!thread) error (_("Can't fetch registers from thread %s: No such thread"), target_pid_to_str (inferior_ptid)); @@ -157,17 +179,25 @@ gnu_fetch_registers (struct target_ops *ops, proc_debug (thread, "fetching all register"); for (i = 0; i < I386_NUM_GREGS; i++) +#ifndef GDBSERVER regcache_raw_supply (regcache, i, REG_ADDR (state, i)); +#else + supply_register (regcache, i, REG_ADDR (state, i)); +#endif thread->fetched_regs = ~0; } else { +#ifndef GDBSERVER proc_debug (thread, "fetching register %s", gdbarch_register_name (get_regcache_arch (regcache), regno)); regcache_raw_supply (regcache, regno, REG_ADDR (state, regno)); +#else + supply_register (regcache, regno, REG_ADDR (state, regno)); +#endif thread->fetched_regs |= (1 << regno); } } @@ -183,9 +213,14 @@ gnu_fetch_registers (struct target_ops *ops, /* Store the whole floating-point state into THREAD using information from the corresponding (pseudo) registers. */ +#ifndef GDBSERVER static void +#else +void +#endif store_fpregs (const struct regcache *regcache, struct proc *thread, int regno) { +#ifndef GDBSERVER mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT; struct i386_float_state state; error_t err; @@ -211,21 +246,32 @@ store_fpregs (const struct regcache *regcache, struct proc *thread, int regno) proc_string (thread)); return; } +#else + debug ("store_fpregs() not support now\n"); +#endif } /* Store at least register REGNO, or all regs if REGNO == -1. */ +#ifndef GDBSERVER static void +#else +void +#endif gnu_store_registers (struct target_ops *ops, struct regcache *regcache, int regno) { struct proc *thread; +#ifndef GDBSERVER struct gdbarch *gdbarch = get_regcache_arch (regcache); +#else + const struct target_desc *gdbarch = regcache->tdesc; +#endif /* Make sure we know about new threads. */ inf_update_procs (gnu_current_inf); thread = inf_tid_to_thread (gnu_current_inf, - ptid_get_tid (inferior_ptid)); + gnu_get_tid (inferior_ptid)); if (!thread) error (_("Couldn't store registers into thread %s: No such thread"), target_pid_to_str (inferior_ptid)); @@ -265,12 +311,19 @@ gnu_store_registers (struct target_ops *ops, register_size (gdbarch, check_regno))) /* Register CHECK_REGNO has changed! Ack! */ { +#ifndef GDBSERVER warning (_("Register %s changed after the thread was aborted"), gdbarch_register_name (gdbarch, check_regno)); +#endif if (regno >= 0 && regno != check_regno) /* Update GDB's copy of the register. */ +#ifndef GDBSERVER regcache_raw_supply (regcache, check_regno, REG_ADDR (state, check_regno)); +#else + supply_register (regcache, check_regno, + REG_ADDR (state, check_regno)); +#endif else warning (_("... also writing this register! " "Suspicious...")); @@ -284,16 +337,24 @@ gnu_store_registers (struct target_ops *ops, proc_debug (thread, "storing all registers"); for (i = 0; i < I386_NUM_GREGS; i++) +#ifndef GDBSERVER if (REG_VALID == regcache_register_status (regcache, i)) regcache_raw_collect (regcache, i, REG_ADDR (state, i)); +#else + collect_register (regcache, i, REG_ADDR (state, i)); +#endif } else { +#ifndef GDBSERVER proc_debug (thread, "storing register %s", gdbarch_register_name (gdbarch, regno)); gdb_assert (REG_VALID == regcache_register_status (regcache, regno)); regcache_raw_collect (regcache, regno, REG_ADDR (state, regno)); +#else + collect_register (regcache, regno, REG_ADDR (state, regno)); +#endif } /* Restore the T bit. */ @@ -309,6 +370,7 @@ gnu_store_registers (struct target_ops *ops, } } +#ifndef GDBSERVER /* Provide a prototype to silence -Wmissing-prototypes. */ extern initialize_file_ftype _initialize_i386gnu_nat; @@ -326,3 +388,4 @@ _initialize_i386gnu_nat (void) /* Register the target. */ add_target (t); } +#endif thanks. -- Yue Lu (陆岳)