From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 2988 invoked by alias); 12 Sep 2013 03:05:39 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 2978 invoked by uid 89); 12 Sep 2013 03:05:38 -0000 Received: from mail-lb0-f175.google.com (HELO mail-lb0-f175.google.com) (209.85.217.175) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Thu, 12 Sep 2013 03:05:38 +0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=3.2 required=5.0 tests=AWL,BAYES_50,FREEMAIL_FROM,GARBLED_BODY,KHOP_THREADED,NO_RELAYS autolearn=no version=3.3.2 X-HELO: mail-lb0-f175.google.com Received: by mail-lb0-f175.google.com with SMTP id y6so361322lbh.6 for ; Wed, 11 Sep 2013 20:05:29 -0700 (PDT) X-Received: by 10.112.168.3 with SMTP id zs3mr5491799lbb.2.1378955129514; Wed, 11 Sep 2013 20:05:29 -0700 (PDT) MIME-Version: 1.0 Received: by 10.152.130.194 with HTTP; Wed, 11 Sep 2013 20:05:14 -0700 (PDT) In-Reply-To: <522A2497.7090405@redhat.com> References: <87txi2i6t6.fsf@kepler.schwinge.homeip.net> <5225C3C6.8090101@redhat.com> <5228DBA7.9050408@redhat.com> <522A2497.7090405@redhat.com> From: Yue Lu Date: Thu, 12 Sep 2013 03:05:00 -0000 Message-ID: Subject: Re: [PATCH 1/2] Port gdbserver to GNU/Hurd To: Pedro Alves Cc: gdb-patches , Thomas Schwinge , Luis Machado , bug-hurd@gnu.org Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes X-SW-Source: 2013-09/txt/msg00367.txt.bz2 Hi, On Sat, Sep 7, 2013 at 2:53 AM, Pedro Alves 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 =3D (gnu_current_inf > ? (gnu_current_inf->task > ? gnu_current_inf->task->port : 0) > : 0); > int res; > > if (task =3D=3D 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 br= anch. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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 =3D @INSTALL_DATA@ RANLIB =3D @RANLIB@ CC =3D @CC@ +MIG =3D @MIG@ +AWK =3D @AWK@ # Dependency tracking information. DEPMODE =3D @CCDEPMODE@ @@ -176,7 +178,7 @@ OBS =3D 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 =3D gdbreplay.o version.o GDBSERVER_LIBS =3D @GDBSERVER_LIBS@ XM_CLIBS =3D @LIBS@ @@ -199,6 +201,11 @@ CLEANDIRS =3D $(SUBDIRS) # The format here is for the `case' shell command. REQUIRED_SUBDIRS =3D $(GNULIB_BUILDDIR) +# Host-dependent makefile fragment comes in here. +GDBSERVER_HURD=3D@GDBSERVER_HURD@ +@host_makefile_frag@ +# End of host-dependent makefile fragment + FLAGS_TO_PASS =3D \ "prefix=3D$(prefix)" \ "exec_prefix=3D$(exec_prefix)" \ @@ -232,7 +239,7 @@ FLAGS_TO_PASS =3D \ "RUNTESTFLAGS=3D$(RUNTESTFLAGS)" # All generated files which can be included by another file. -generated_files =3D config.h $(GNULIB_H) +generated_files =3D 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=3D +GDBSERVER_HURD=3D1 +case $host_os in + gnu*) + #Needed for GNU Hurd hosts. + AC_PROG_AWK + AC_CHECK_TOOL(MIG, mig) + if test x"$MIG" =3D x; then + AC_MSG_ERROR([MIG not found but required for $host hosts]) + fi + host_makefile_frag=3D${srcdir}/../config/i386/i386gnu.mh + if test ! -f ${host_makefile_frag}; then + AC_MSG_ERROR("*** Gdb does not support native target ${host}") + fi + frags=3D"$frags $host_makefile_frag" + ;; + *) + host_makefile_frag=3D/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=3Dyes ipa_obj=3D"${ipa_i386_linux_regobj} linux-i386-ipa.o" ;; + i[34567]86-*-gnu*) srv_regobj=3D"$srv_i386_regobj" + srv_tgtobj=3D"" + srv_xmlfiles=3D"$srv_i386_xmlfiles" + ;; i[34567]86-*-lynxos*) srv_regobj=3D"i386.o" srv_tgtobj=3D"lynx-low.o lynx-i386-low.o" srv_xmlfiles=3D"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 =3D get_cell (); + + xsnprintf (str, CELLSIZE, "0x%s", phex_nz ((unsigned long long) addr, sizeof (addr))); + return str; +} + static char * decimal2str (char *sign, ULONGEST addr) { =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D gdb * configure.tgt: Set build_gdbserver=3Dyes 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=3D i386gnu-nat.o gnu-nat.o core-regset.o fork-child.o \ +ifndef GDBSERVER_HURD +NATDEPFILES=3D 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 =3D 1 @@ -12,22 +13,41 @@ XM_CLIBS =3D -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 =3D -D'MSG_IMPORTS=3Dwaittime 1000;' +else +NATDEPFILES=3D 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 =3D $(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=3DS_ -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=3DS_ -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=3DS_ -x c $< \ | $(MIGCOM) -sheader $*_S.h -server $*_S.c -user /dev/null -header /dev/n= ull # 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=3D"i386-tdep.o i387-tdep.o i386gnu-tdep.o solib-svr4.o" + build_gdbserver=3Dyes ;; 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 . = */ +#ifndef GDBSERVER #include "defs.h" #include #include -#include #include #include #include #include "gdb_string.h" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* Defined in , but we need forward declarations from 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 +#include +#include +#include +#endif /* GDBSERVER */ + +#include "target.h" + +#include +#include +#include "gdb_obstack.h" +#include "gdb_wait.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#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 =3D 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 =3D 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 =3D suspend_count; } } @@ -1056,6 +1111,12 @@ inf_validate_procs (struct inf *inf) if (!left) { proc_debug (thread, "died!"); +#ifdef GDBSERVER + ptid_t ptid; + ptid =3D gnu_ptid_build (inf->pid, 0, thread->tid); + if (find_thread_ptid (ptid)) + remove_thread (find_thread_ptid (ptid)); +#endif thread->port =3D MACH_PORT_NULL; thread =3D _proc_free (thread); /* THREAD is dead. */ if (last) @@ -1083,10 +1144,11 @@ inf_validate_procs (struct inf *inf) last =3D thread; proc_debug (thread, "new thread: %d", threads[i]); - ptid =3D ptid_build (inf->pid, 0, thread->tid); + ptid =3D 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=3D%d, tid=3D%d\n", inf->pid, + thread->tid); + add_thread (ptid, thread); + //inferior_ptid =3D 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 =3D 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 =3D inf->threads; thread; thread =3D 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 =3D inf->wait.thread; if (thread) - ptid =3D ptid_build (inf->pid, 0, thread->tid); + ptid =3D gnu_ptid_build (inf->pid, 0, thread->tid); else if (ptid_equal (ptid, minus_one_ptid)) thread =3D inf_tid_to_thread (inf, -1); else - thread =3D inf_tid_to_thread (inf, ptid_get_tid (ptid)); + thread =3D inf_tid_to_thread (inf, gnu_get_tid (ptid)); if (!thread || thread->port =3D=3D MACH_PORT_NULL) { /* TID is dead; try and find a new thread. */ if (inf_update_procs (inf) && inf->threads) - ptid =3D ptid_build (inf->pid, 0, inf->threads->tid); /* The first - available - thread. */ + ptid =3D gnu_ptid_build (inf->pid, 0, inf->threads->tid);/* The first available thread*/ else ptid =3D inferior_ptid; /* let wait_for_inferior handle exit case */ } @@ -1651,6 +1724,12 @@ rewait: : "?", status->value.integer); +#ifdef GDBSERVER + inferior_ptid =3D 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 =3D inf_tid_to_thread (inf, ptid_get_tid (ptid)); + struct proc *thread =3D 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 =3D inf_tid_to_thread (inf, ptid_get_tid (ptid)); + step_thread =3D 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 =3D gnu_current_inf->task; + struct process_info *process; + + process =3D 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 =3D 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 =3D fork (); + if (pid < 0) + perror_with_name ("fork"); + + if (pid =3D=3D 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 =3D find_process_pid (pid); + if (process =3D=3D NULL) + return -1; + + inf_detach (gnu_current_inf); + + inferior_ptid =3D 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 =3D add_process (pid, attached); + proc->tdesc =3D gnu_tdesc; + proc->private =3D xcalloc (1, sizeof (*proc->private)); + proc->private->inf =3D cur_inf (); + struct inf *inf =3D gnu_current_inf; + + inf_attach (inf, pid); + inf->pending_execs =3D 2; + inf->nomsg =3D 1; + inf->traced =3D 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 =3D=3D 1. */ + ptid_t ptid =3D resume_info[0].thread; + const int step =3D (resume_info[0].kind =3D=3D resume_step ? 1 : 0); //1 means step, 0 means contiune + const int signal =3D resume_info[0].sig; + if (ptid_equal (ptid, minus_one_ptid)) + ptid =3D thread_to_gdb_id (current_inferior); + + regcache_invalidate (); + + debug ("in gnu_resume: ptid=3D%d, step=3D%d, signal=3D%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 =3D gnu_wait (NULL, ptid, status, target_options); + debug (" -> (status->kind =3D %d)\n", status->kind); + return event_ptid; +} + +void +gnu_fetch_registers_wrap (struct regcache *regcache, int regno) +{ + debug ("gnu_fetch_registers() regno=3D%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=3D%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 =3D 0; + task_t task =3D (gnu_current_inf + ? (gnu_current_inf->task + ? gnu_current_inf->task->port : 0) : 0); + if (task =3D=3D MACH_PORT_NULL) + return 0; + ret =3D gnu_read_inferior (task, addr, myaddr, length); + if (length !=3D ret) + { + debug ("gnu_read_inferior,length=3D%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 =3D 0; + task_t task =3D (gnu_current_inf + ? (gnu_current_inf->task + ? gnu_current_inf->task->port : 0) : 0); + if (task =3D=3D MACH_PORT_NULL) + return 0; + ret =3D gnu_write_inferior (task, addr, myaddr, length); + if (length !=3D ret) + { + debug ("gnu_write_inferior,length=3D%d, but return %d\n", length, + ret); + return -1; + } + return 0; +} + +static void +gnu_request_interrupt (void) +{ + ptid_t inferior_ptid =3D 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 =3D TARGET_WAITKIND_EXITED; + ourstatus->value.integer =3D WEXITSTATUS (hoststatus); + } + else if (!WIFSTOPPED (hoststatus)) + { + ourstatus->kind =3D TARGET_WAITKIND_SIGNALLED; + ourstatus->value.sig =3D gdb_signal_from_host (WTERMSIG (hoststatus)= ); + } + else + { + ourstatus->kind =3D TARGET_WAITKIND_STOPPED; + ourstatus->value.sig =3D gdb_signal_from_host (WSTOPSIG (hoststatus)= ); + } +} + +static struct target_ops gnu_target_ops =3D { + 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 =3D getproc (); +} + +static void +initialize_low_arch () +{ + init_registers_i386 (); + gnu_tdesc =3D 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 |=3D 0x100 +#define THREAD_STATE_CLEAR_TRACED(state) \ + ((((struct i386_thread_state *) (state))->efl &=3D ~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 . = */ +#ifndef GDBSERVER #include "defs.h" #include "inferior.h" #include "floatformat.h" #include "regcache.h" #include "gdb_assert.h" -#include -#include #include "gdb_string.h" -#include -#include -#include -#include - #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 +#include + +#include +#include +#include +#include +#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[] =3D static void fetch_fpregs (struct regcache *regcache, struct proc *thread) { +#ifndef GDBSERVER mach_msg_type_number_t count =3D 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 =3D 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 =3D 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 =3D ~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 |=3D (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 re= gno) { +#ifndef GDBSERVER mach_msg_type_number_t count =3D 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 =3D=3D -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 =3D get_regcache_arch (regcache); +#else + const struct target_desc *gdbarch =3D regcache->tdesc; +#endif /* Make sure we know about new threads. */ inf_update_procs (gnu_current_inf); thread =3D 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 >=3D 0 && regno !=3D 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 =3D 0; i < I386_NUM_GREGS; i++) +#ifndef GDBSERVER if (REG_VALID =3D=3D 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 =3D=3D 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. --=20 Yue Lu (=E9=99=86=E5=B2=B3)