bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 1/2] Port gdbserver to GNU/Hurd


From: Yue Lu
Subject: Re: [PATCH 1/2] Port gdbserver to GNU/Hurd
Date: Thu, 12 Sep 2013 11:05:14 +0800

Hi,

On Sat, Sep 7, 2013 at 2:53 AM, Pedro Alves <address@hidden> 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.
address@hidden@
address@hidden@
+# 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 (&region_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 (陆岳)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]