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: Pedro Alves
Subject: Re: [PATCH 1/2] Port gdbserver to GNU/Hurd
Date: Thu, 05 Sep 2013 20:29:43 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130625 Thunderbird/17.0.7

On 09/05/2013 11:53 AM, Yue Lu wrote:
> Hi,
> 
> This is the my new patch.

Thanks.  Follows a few comments, by no means an in depth review.
We'll probably need to iterate a few times.  I'm counting on
Thomas and others to help as well!

I'm actually very excited to see gdb and gdbserver sharing
a single target backend, even if we still have many wrinkles
in the interfaces to iron out!  It does looks like this way
results in lots of less work, and makes me believe we can
port other targets to gdbserver already without unsurmountable
effort.

It'd be very useful if you send and maintain along
with the patch the rationale for all design divergences between
the ports you found necessary.  E.g., it seems that gdbserver's
task/proc bookkeeping is different from gdb's.  Why?

> I have put some soft link in directory gdbserver like *.defs which
> point to [gdb]/gdb/*.defs.

We'll need to adjust the Makefile etc. instead to use the original
files instead of that.  No symlinks please.

> 2013-09-03  Yue Lu  <address@hidden>
> 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_debug): New function, use for debug printf.
>         (gnu_wait_1): wait for inferior used in gdbserver.
>         (gnu_resume_1): resume inferior used in 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.
>         (gnu_get_tid): New function, return lwp from structure ptid_t,
> this is different with gdb's behavior.
>         (gnu_add_process): New function, add a new process to process list.
>         (gnu_join): New function, a placeholder.
>         (gnu_resume): New function, a wrap function, just call gnu_resume_1().
>         (gnu_wait): New function, a wrap function, just call gnu_wait_1().
>         (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, a placeholder.
>         (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..224cf0f 100644
> --- a/gdb/config/i386/i386gnu.mh
> +++ b/gdb/config/i386/i386gnu.mh
> @@ -1,4 +1,5 @@
>  # Host: Intel 386 running the GNU Hurd
> +ifndef GDBSERVER
>  NATDEPFILES= i386gnu-nat.o gnu-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
> @@ -12,6 +13,10 @@ 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= 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
> diff --git a/gdb/configure.tgt b/gdb/configure.tgt
> index b0bee47..3eb2ff7 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..1cdcd1d 100644
> --- a/gdb/gnu-nat.c
> +++ b/gdb/gnu-nat.c
> @@ -1,6 +1,7 @@
>  /* Interface GDB to the GNU Hurd.
>     Copyright (C) 1992-2013 Free Software Foundation, Inc.
> 
> +
>     This file is part of GDB.

Please go through the patch and remove spurious whitespace
changes line these.

> 
>     Written by Miles Bader <address@hidden>
> @@ -20,6 +21,7 @@
>     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>
> @@ -31,18 +33,6 @@
>  #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_
> @@ -64,17 +54,55 @@
>  #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 "target.h"
> +
> +#include <limits.h>
> +#include <unistd.h>
> +#include <sys/ioctl.h>
> +#include <sys/types.h>
> +#include "gdb_wait.h"
> +#include <signal.h>
> +#include <sys/ptrace.h>
> +#endif /* GDBSERVER */
> +
> +#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 gnu-i386-low.c ?*/

I guess that means i386gnu-nat.c now, but it sounds like
it, yes.

> +/* 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 +142,12 @@ void inf_continue (struct inf *inf);
>         debug ("{inf %d %s}: " msg, __inf->pid, \
>         host_address_to_string (__inf) , ##args); } while (0)
> 
> +#ifdef GDBSERVER
> +static ptid_t gnu_ptid_build (int pid, long lwp, long tid);
> +static long gnu_get_tid (ptid_t ptid);

These should be used unconditionally throughout, but implemented
differently on gdb vs gdbserver.  Any other similar case should
have a similar solution.  The goal should be to have the fewest
#ifdefs in the core gnu target code as possible, with the
differences being in the interfacing to gdb/gdbserver core.

Actually,

> +static ptid_t
> +gnu_ptid_build (int pid, long lwp, long tid)
> +{
> +  return ptid_build (pid, tid, 0);
> +}
> +
> +static long
> +gnu_get_tid (ptid_t ptid)
> +{
> +  return ptid_get_lwp (ptid);
> +}
> +

in this case, the difference is that GDB uses the tid
field, while gdbserver uses the lwp field.  But, (correct me if
I'm wrong here), the Hurd's threads are kernel threads, so it'd
be better to just make the GDB side use the lwp field too.
It's really a simple and mechanic change.  Nothing in GDB core
actually cares which field is used.  So in this case, it'd be
better if you send a preparatory patch that does that change
(and nothing else), and then rebase the port on top of that
patch.

> +


> +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,7 +179,27 @@ int proc_trace (struct proc *proc, int set);
>   __e; }) \
>     : EIEIO)
> 
> -
> +#ifdef GDBSERVER
> +struct process_info_private
> +{
> +  struct inf *inf;
> +};
> +
> +void
> +gnu_debug (char *string, ...)
> +{

Sounds like another candidate for always being
available, but with minor differences in implementation.

> +  va_list args;
> +
> +  if (!gnu_debug_flag)
> +    return;
> +  va_start (args, string);
> +  fprintf (stderr, "DEBUG(gnu): ");
> +  vfprintf (stderr, string, args);
> +  fprintf (stderr, "\n");
> +  va_end (args);
> +}
> +#endif
> +
>  /* The state passed by an exception message.  */
>  struct exc_state
>    {
> @@ -242,14 +296,12 @@ struct inf
>      int want_exceptions;
>    };
> 
> -
>  int
>  __proc_pid (struct proc *proc)
>  {
>    return proc->inf->pid;
>  }
> 
> -
>  /* Update PROC's real suspend count to match it's desired one.  Returns true
>     if we think PROC is now in a runnable state.  */
>  int
> @@ -313,7 +365,6 @@ proc_update_sc (struct proc *proc)
>    return running;
>  }
> 
> -
>  /* Thread_abort is called on PROC if needed.  PROC must be a thread proc.
>     If PROC is deemed `precious', then nothing is done unless FORCE is true.
>     In particular, a thread is precious if it's running (in which case forcing
> @@ -390,7 +441,6 @@ proc_get_state (struct proc *proc, int will_modify)
>      return 0;
>  }
> 
> -
>  /* Set PORT to PROC's exception port.  */
>  error_t
>  proc_get_exception_port (struct proc * proc, mach_port_t * port)
> @@ -506,7 +556,6 @@ proc_restore_exc_port (struct proc *proc)
>      }
>  }
> 
> -
>  /* Turns hardware tracing in PROC on or off when SET is true or false,
>     respectively.  Returns true on success.  */
>  int
> @@ -533,7 +582,6 @@ proc_trace (struct proc *proc, int set)
>    return 1;
>  }
> 
> -
>  /* A variable from which to assign new TIDs.  */
>  static int next_thread_id = 1;
> 
> @@ -610,7 +658,6 @@ _proc_free (struct proc *proc)
>    struct proc *next = proc->next;
> 
>    proc_debug (proc, "freeing...");
> -
>    if (proc == inf->step_thread)
>      /* Turn off single stepping.  */
>      inf_set_step_thread (inf, 0);
> @@ -637,7 +684,6 @@ _proc_free (struct proc *proc)
>    return next;
>  }
> 
> -
>  struct inf *
>  make_inf (void)
>  {
> @@ -691,7 +737,6 @@ inf_clear_wait (struct inf *inf)
>      }
>  }
> 
> -
>  void
>  inf_cleanup (struct inf *inf)
>  {
> @@ -736,7 +781,6 @@ inf_startup (struct inf *inf, int pid)
>    inf_set_pid (inf, pid);
>  }
> 
> -
>  /* Close current process, if any, and attach INF to process PORT.  */
>  void
>  inf_set_pid (struct inf *inf, pid_t pid)
> @@ -786,7 +830,6 @@ inf_set_pid (struct inf *inf, pid_t pid)
>      inf->pid = -1;
>  }
> 
> -
>  /* Validates INF's stopped, nomsg and traced field from the actual
>     proc server state.  Note that the traced field is only updated from
>     the proc server state if we do not have a message port.  If we do
> @@ -855,6 +898,7 @@ inf_validate_task_sc (struct inf *inf)
> 
>    if (inf->task->cur_sc < suspend_count)
>      {
> +#ifndef GDBSERVER
>        int abort;
> 
>        target_terminal_ours (); /* Allow I/O.  */
> @@ -865,7 +909,9 @@ inf_validate_task_sc (struct inf *inf)
> 
>        if (abort)
>   error (_("Additional task suspend count left untouched."));
> +#endif
> 
> +      //need fix!

What's the plan here?

>        inf->task->cur_sc = suspend_count;
>      }
>  }
> @@ -905,7 +951,6 @@ inf_set_traced (struct inf *inf, int on)
>      inf->traced = on;
>  }
> 
> -
>  /* Makes all the real suspend count deltas of all the procs in INF
>     match the desired values.  Careful to always do thread/task suspend
>     counts in the safe order.  Returns true if at least one thread is
> @@ -959,7 +1004,6 @@ inf_update_suspends (struct inf *inf)
>    return 0;
>  }
> 
> -
>  /* Converts a GDB pid to a struct proc.  */
>  struct proc *
>  inf_tid_to_thread (struct inf *inf, int tid)
> @@ -988,7 +1032,6 @@ inf_port_to_thread (struct inf *inf, mach_port_t port)
>    return 0;
>  }
> 
> -
>  /* Make INF's list of threads be consistent with reality of TASK.  */
>  void
>  inf_validate_procs (struct inf *inf)
> @@ -1056,6 +1099,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 +1132,15 @@ inf_validate_procs (struct inf *inf)
>      last = thread;
>      proc_debug (thread, "new thread: %d", threads[i]);
> 
> +#ifndef GDBSERVER
>      ptid = ptid_build (inf->pid, 0, thread->tid);
> +#else
> +    ptid = gnu_ptid_build (inf->pid, 0, thread->tid);
> +#endif
> 
>      /* 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 +1150,15 @@ inf_validate_procs (struct inf *inf)
>        add_thread_silent (ptid);
>      else
>        add_thread (ptid);
> +#else
> +    if (!find_thread_ptid (ptid))
> +      {
> + gnu_debug ("New thread, pid=%d, tid=%d\n", inf->pid,
> +   thread->tid);
> + add_thread (ptid, thread);
> + inferior_ptid = ptid; // need fix!!!!!!!!!!!!!
> +      }
> +#endif
>    }
>        }
> 
> @@ -1104,7 +1167,6 @@ inf_validate_procs (struct inf *inf)
>    }
>  }
> 
> -
>  /* Makes sure that INF's thread list is synced with the actual process.  */
>  int
>  inf_update_procs (struct inf *inf)
> @@ -1135,7 +1197,6 @@ inf_set_threads_resume_sc (struct inf *inf,
>        thread->resume_sc = thread->pause_sc;
>  }
> 
> -
>  /* Cause INF to continue execution immediately; individual threads may still
>     be suspended (but their suspend counts will be updated).  */
>  void
> @@ -1179,7 +1240,6 @@ inf_suspend (struct inf *inf)
>    inf_update_suspends (inf);
>  }
> 
> -
>  /* INF has one thread PROC that is in single-stepping mode.  This
>     function changes it to be PROC, changing any old step_thread to be
>     a normal one.  A PROC of 0 clears any existing value.  */
> @@ -1205,7 +1265,6 @@ inf_set_step_thread (struct inf *inf, struct proc 
> *thread)
>      }
>  }
> 
> -
>  /* Set up the thread resume_sc's so that only the signal thread is running
>     (plus whatever other thread are set to always run).  Returns true if we
>     did so, or false if we can't find a signal thread.  */
> @@ -1221,6 +1280,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,7 +1289,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
>  inf_detach (struct inf *inf)
> @@ -1284,7 +1344,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
>  inf_steal_exc_ports (struct inf *inf)
> @@ -1314,8 +1374,8 @@ 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
>     signal 0, will continue it.  INF is assumed to be in a paused state, and
>     the resume_sc's of INF's threads may be affected.  */
> @@ -1404,7 +1464,6 @@ inf_signal (struct inf *inf, enum gdb_signal sig)
>  #undef NAME
>  }
> 
> -
>  /* Continue INF without delivering a signal.  This is meant to be used
>     when INF does not have a message port.  */
>  void
> @@ -1433,7 +1492,6 @@ inf_continue (struct inf *inf)
>      warning (_("Can't continue process: %s"), safe_strerror (err));
>  }
> 
> -
>  /* The inferior used for all gdb target ops.  */
>  struct inf *gnu_current_inf = 0;
> 
> @@ -1443,8 +1501,13 @@ struct inf *waiting_inf;
> 
>  /* Wait for something to happen in the inferior, returning what in STATUS.  
> */
>  static ptid_t
> +#ifdef GDBSERVER
> +gnu_wait_1 (ptid_t ptid, struct target_waitstatus *status,
> +    int target_options)
> +#else
>  gnu_wait (struct target_ops *ops,
>    ptid_t ptid, struct target_waitstatus *status, int options)
> +#endif

What's the rationale for this, and what's the rationale for
doing it only on the gdbserver side?

>  {
>    struct msg
>      {
> @@ -1613,19 +1676,29 @@ rewait:
> 
>    thread = inf->wait.thread;
>    if (thread)
> +#ifndef GDBSERVER
>      ptid = ptid_build (inf->pid, 0, thread->tid);
> +#else
> +    ptid = gnu_ptid_build (inf->pid, 0, thread->tid);
> +#endif
>    else if (ptid_equal (ptid, minus_one_ptid))
>      thread = inf_tid_to_thread (inf, -1);
>    else
> +#ifndef GDBSERVER
>      thread = inf_tid_to_thread (inf, ptid_get_tid (ptid));
> +#else
> +    thread = inf_tid_to_thread (inf, gnu_get_tid (ptid));
> +#endif
> 
>    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.  */
> +#ifndef GDBSERVER
> + ptid = ptid_build (inf->pid, 0, inf->threads->tid);
> +#else
> + ptid = gnu_ptid_build (inf->pid, 0, inf->threads->tid);
> +#endif /* The first available thread*/
>        else
>   ptid = inferior_ptid; /* let wait_for_inferior handle exit case */
>      }
> @@ -1651,10 +1724,12 @@ rewait:
>       : "?",
>       status->value.integer);
> 
> +#ifdef GDBSERVER
> +  inferior_ptid = ptid;
> +#endif

This is surprising.  What's this needed for?

>    return ptid;
>  }
> 
> -
>  /* The rpc handler called by exc_server.  */
>  error_t
>  S_exception_raise_request (mach_port_t port, mach_port_t reply_port,
> @@ -1736,11 +1811,9 @@ S_exception_raise_request (mach_port_t port,
> mach_port_t reply_port,
>        inf->wait.suppress = 1;
>        mach_port_deallocate (mach_task_self (), reply_port);
>      }
> -
>    return 0;
>  }
> 
> -
>  /* Fill in INF's wait field after a task has died without giving us more
>     detailed information.  */
>  void
> @@ -1794,7 +1867,6 @@ do_mach_notify_dead_name (mach_port_t notify,
> mach_port_t dead_port)
>    return 0;
>  }
> 
> -
>  static error_t
>  ill_rpc (char *fun)
>  {
> @@ -1832,7 +1904,6 @@ do_mach_notify_send_once (mach_port_t notify)
>    return ill_rpc ("do_mach_notify_send_once");
>  }
> 
> -
>  /* Process_reply server routines.  We only use process_wait_reply.  */
> 
>  error_t
> @@ -1901,7 +1972,6 @@ S_proc_getmsgport_reply (mach_port_t reply,
> error_t err, mach_port_t msg_port)
>    return ill_rpc ("S_proc_getmsgport_reply");
>  }
> 
> -
>  /* Msg_reply server routines.  We only use msg_sig_post_untraced_reply.  */
> 
>  error_t
> @@ -1930,7 +2000,6 @@ S_msg_sig_post_untraced_reply (mach_port_t
> reply, error_t err)
>      inf->stopped = 1;
>    else
>      inf->wait.suppress = 1;
> -
>    return 0;
>  }
> 
> @@ -1940,7 +2009,6 @@ S_msg_sig_post_reply (mach_port_t reply, error_t err)
>    return ill_rpc ("S_msg_sig_post_reply");
>  }
> 
> -
>  /* Returns the number of messages queued for the receive right PORT.  */
>  static mach_port_msgcount_t
>  port_msgs_queued (mach_port_t port)
> @@ -1955,7 +2023,6 @@ port_msgs_queued (mach_port_t port)
>      return status.mps_msgcount;
>  }
> 
> -
>  /* Resume execution of the inferior process.
> 
>     If STEP is nonzero, single-step it.
> @@ -1973,8 +2040,13 @@ port_msgs_queued (mach_port_t port)
>     in multiple events returned by wait).  */
> 
>  static void
> +#ifndef GDBSERVER
>  gnu_resume (struct target_ops *ops,
>      ptid_t ptid, int step, enum gdb_signal sig)
> +#else
> +gnu_resume_1 (struct target_ops *ops,
> +      ptid_t ptid, int step, enum gdb_signal sig)
> +#endif

Again, why is this conditional?

>  {
>    struct proc *step_thread = 0;
>    int resume_all;
> @@ -1997,9 +2069,11 @@ gnu_resume (struct target_ops *ops,
>         abort the faulting thread, which will perhaps retake it.  */
>      {
>        proc_abort (inf->wait.thread, 1);
> +#ifndef GDBSERVER
>        warning (_("Aborting %s with unforwarded exception %s."),
>         proc_string (inf->wait.thread),
>         gdb_signal_to_name (inf->wait.status.value.sig));
> +#endif

Ditto.

>      }
> 
>    if (port_msgs_queued (inf->event_port))
> @@ -2022,7 +2096,12 @@ gnu_resume (struct target_ops *ops,
>    else
>      /* Just allow a single thread to run.  */
>      {
> +#ifdef GDBSERVER
> +      struct proc *thread = inf_tid_to_thread (inf, gnu_get_tid (ptid));
> +#else
>        struct proc *thread = inf_tid_to_thread (inf, ptid_get_tid (ptid));
> +#endif
> +
> 
>        if (!thread)
>   error (_("Can't run single thread id %s: no such thread!"),
> @@ -2033,7 +2112,12 @@ gnu_resume (struct target_ops *ops,
> 
>    if (step)
>      {
> +#ifdef GDBSERVER
> +      step_thread = inf_tid_to_thread (inf, gnu_get_tid (ptid));
> +#else
>        step_thread = inf_tid_to_thread (inf, ptid_get_tid (ptid));
> +#endif
> +
>        if (!step_thread)
>   warning (_("Can't step thread id %s: no such thread."),
>   target_pid_to_str (ptid));
> @@ -2047,7 +2131,7 @@ gnu_resume (struct target_ops *ops,
>    inf_resume (inf);
>  }
> 
> -
> +#ifndef GDBSERVER
>  static void
>  gnu_kill_inferior (struct target_ops *ops)
>  {
> @@ -2061,8 +2145,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;
> +}

Looks like the differences between gdb and gdbserver here
are really minor.  We should be able to merge them better.

> +#endif
> +
> 
>  /* Clean up after the inferior dies.  */
> +#ifndef GDBSERVER
>  static void
>  gnu_mourn_inferior (struct target_ops *ops)
>  {
> @@ -2071,8 +2176,18 @@ 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.  */
> 
>  /* Set INFERIOR_PID to the first thread available in the child, if any.  */
> @@ -2095,6 +2210,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 +2264,34 @@ 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,8 +2347,14 @@ 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

Doesn't look like this should be hard to get going.

> +}
> +#endif
> 
> -
>  /* Take a program previously attached to and detaches it.
>     The program resumes execution and will no longer stop
>     on signals, etc.  We'd better not have left any breakpoints
> @@ -2216,6 +2362,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,7 +2402,25 @@ gnu_stop (ptid_t ptid)
>  {
>    error (_("to_stop target function not implemented"));
>  }
> +#else
> +static int
> +gnu_detach (int pid)
> +{

Eheh, we have detach but not attach.  ;-)

> +  struct process_info *process;
> +
> +  process = find_process_pid (pid);
> +  if (process == NULL)
> +    return -1;
> +
> +  inf_detach (gnu_current_inf);
> 
> +  inferior_ptid = null_ptid;

I'm seeing inferior_ptid references in the gdbserver side,
but gdbserver doesn't have that global.  What's that needed for?

> +  the_target->mourn (process);
> +  return 0;
> +}
> +#endif
> +
> +#ifndef GDBSERVER
>  static int
>  gnu_thread_alive (struct target_ops *ops, ptid_t ptid)
>  {
> @@ -2263,8 +2428,15 @@ gnu_thread_alive (struct target_ops *ops, ptid_t ptid)
>    return !!inf_tid_to_thread (gnu_current_inf,
>        ptid_get_tid (ptid));
>  }
> +#else
> +static int
> +gnu_thread_alive (ptid_t ptid)
> +{
> +  /* this function is copyed from lynx-low.c */

Why?  Why not use the same scheme as the gdb side?

> +  return (find_thread_ptid (ptid) != NULL);
> +}
> +#endif
> 
> -
>  /* Read inferior task's LEN bytes from ADDR and copy it to MYADDR in
>     gdb's address space.  Return 0 on failure; number of bytes read
>     otherwise.  */
> @@ -2310,7 +2482,9 @@ struct vm_region_list
>    vm_size_t length;
>  };
> 
> +#ifndef GDBSERVER
>  struct obstack region_obstack;
> +#endif
> 
>  /* Write gdb's LEN bytes from MYADDR and copy it to ADDR in inferior
>     task's address space.  */
> @@ -2344,7 +2518,9 @@ gnu_write_inferior (task_t task, CORE_ADDR addr,
> char *myaddr, int length)
>     myaddr, length);
>    CHK_GOTO_OUT ("Write to inferior faulted", err);
> 
> +#ifndef GDBSERVER
>    obstack_init (&region_obstack);
> +#endif
> 
>    /* Do writes atomically.
>       First check for holes and unwritable memory.  */
> @@ -2399,7 +2575,11 @@ gnu_write_inferior (task_t task, CORE_ADDR
> addr, char *myaddr, int length)
>   /* Chain the regions for later use.  */
>   region_element =
>    (struct vm_region_list *)
> +#ifndef GDBSERVER
>    obstack_alloc (&region_obstack, sizeof (struct vm_region_list));
> +#else
> +  malloc (sizeof (struct vm_region_list));

Err, malloc without storing the result anywhere is just a leak.

We'll need to do something about this.  We could hack/build libiberty's
obstack.c on gdbserver, like we vasprintf.c (see Makefile.in), or
use struct buffer on both sides.  I think the former would be better.
We already have too many ways to do the same, and we that
would probably allow getting rid of struct buffer.


> +#endif
> 
>   region_element->protection = protection;
>   region_element->start = region_address;
> @@ -2454,7 +2634,9 @@ gnu_write_inferior (task_t task, CORE_ADDR addr,
> char *myaddr, int length)
>  out:
>    if (deallocate)
>      {
> +#ifndef GDBSERVER
>        obstack_free (&region_obstack, 0);
> +#endif
> 
>        (void) vm_deallocate (mach_task_self (),
>      copied,
> @@ -2470,7 +2652,7 @@ out:
>    return length;
>  }
> 
> -
> +#ifndef GDBSERVER
>  /* Return 0 on failure, number of bytes handled otherwise.  TARGET
>     is ignored.  */
>  static int
> @@ -2576,8 +2758,7 @@ gnu_find_memory_regions
> (find_memory_region_ftype func, void *data)
> 
>    return 0;
>  }
> -
> -
> +#endif
>  /* Return printable description of proc.  */
>  char *
>  proc_string (struct proc *proc)
> @@ -2592,6 +2773,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 +3634,214 @@ flush_inferior_icache (CORE_ADDR pc, int amount)
>      warning (_("Error flushing inferior's cache : %s"), safe_strerror (ret));
>  }
>  #endif /* FLUSH_INFERIOR_CACHE */
> +
> +#else
> +
> +static ptid_t
> +gnu_ptid_build (int pid, long lwp, long tid)
> +{
> +  return ptid_build (pid, tid, 0);
> +}
> +
> +static long
> +gnu_get_tid (ptid_t ptid)
> +{
> +  return ptid_get_lwp (ptid);
> +}
> +
> +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 (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 ();
> +
> +  gnu_debug ("in gnu_resume: ptid=%d, step=%d, signal=%d\n", ptid, step,
> +     signal);
> +
> +  /*my_resume(); */
> +  /*static void gnu_resume_1 (struct target_ops *ops,ptid_t ptid, int
> step, enum gdb_signal sig) */
> +  gnu_resume_1 (NULL, ptid, step, signal);
> +
> +}
> +
> +static ptid_t
> +gnu_wait (ptid_t ptid, struct target_waitstatus *status, int target_options)
> +{
> +  ptid_t event_ptid;
> +  gnu_debug ("gnu_wait: [%s]", target_pid_to_str (ptid));
> +  event_ptid = gnu_wait_1 (ptid, status, target_options);
> +  gnu_debug ("          -> (status->kind = %d)\n", status->kind);
> +  return event_ptid;
> +}
> +
> +void
> +gnu_fetch_registers_wrap (struct regcache *regcache, int regno)
> +{
> +  gnu_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)
> +{
> +  gnu_debug ("gnu_store_registers() regno=%d\n", regno);
> +  return gnu_store_registers (NULL, regcache, regno);
> +}
> +
> +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)
> +    {
> +      gnu_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)
> +    {
> +      gnu_debug ("gnu_write_inferior,length=%d, but return %d\n", length,
> + ret);
> +      return -1;
> +    }
> +  return 0;
> +}
> +

These should reall be wrappers around a common shared function.  I have
a patch that I think helps here.  I'll post it in soon.

> +static void
> +gnu_request_interrupt (void)
> +{
> +  printf ("gnu_request_interrupt not support!\n");
> +  exit (-1);

That's quite limiting.  :-/  Doesn't sending a SIGINT
work?

> +}
> +
> +/* 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,
> +  gnu_resume,
> +  gnu_wait,
> +  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..84f507d 100644
> --- a/gdb/gnu-nat.h
> +++ b/gdb/gnu-nat.h
> @@ -93,13 +93,83 @@ 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

Wasn't there already a gnu_debug function?

> 
>  /* Create a prototype generic GNU/Hurd target.  The client can
>     override it with local methods.  */
>  struct target_ops *gnu_target (void);
> 
> +#ifdef GDBSERVER
> +
> +/* All info needed to access an architecture/mode's registers.  */
> +
> +struct regs_info
> +{
> +  /* Regset support bitmap: 1 for registers that are transferred as a part
> +     of a regset, 0 for ones that need to be handled individually.  This
> +     can be NULL if all registers are transferred with regsets or regsets
> +     are not supported.  */
> +  unsigned char *regset_bitmap;
> +
> +  /* Info used when accessing registers with PTRACE_PEEKUSER /
> +     PTRACE_POKEUSER.  This can be NULL if all registers are
> +     transferred with regsets  .*/
> +  struct usrregs_info *usrregs;
> +
> +#ifdef HAVE_gnu_REGSETS
> +  /* Info used when accessing registers with regsets.  */
> +  struct regsets_info *regsets_info;
> +#endif

Why's all this needed?

> +};
> +
> +#define ptid_of(proc) ((proc)->head.id)
> +#define pid_of(proc) ptid_get_pid ((proc)->head.id)
> +#define lwpid_of(proc) ptid_get_lwp ((proc)->head.id)
> +
> +#define get_lwp(inf) ((struct lwp_info *)(inf))
> +#define get_thread_lwp(thr) (get_lwp (inferior_target_data (thr)))
> +#define get_lwp_thread(proc) ((struct thread_info *) \
> +      find_inferior_id (&all_threads, \
> + get_lwp (proc)->head.id))

There seems to be some amount of blind copy&paste from
the linux target here.  struct lwp_info certainly has no
business in this port?  You should go through every line
in the patch, and make sure you're able to justify it.
If you can't, or if you're not sure, revert the change.

> +
> +#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))
> +#define TIDGET(PTID) (ptid_get_lwp (PTID))
> +#define MERGEPID(PID, TID) ptid_build (PID, TID, 0)
> +#endif
> +//gdbserver use ptid_t not the same as gdb does!
> +static ptid_t gnu_ptid_build(int pid,long lwp,long tid);

As said, best would be to make them the same.

> +
> +//add for erase warning
> +extern const char * host_address_to_string (const void *addr);

This should be put in a proper place.  Probably utils.h,
once I commit yesterday's series to split server.h.

> +
> +/* 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..51ca679 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,24 @@
>  # 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"
> +/*#include "gnu-low.h"*/
> +
>  /* Offset to the thread_state_t location where REG is stored.  */
>  #define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
> 
> @@ -78,6 +89,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 +113,12 @@ fetch_fpregs (struct regcache *regcache, struct
> proc *thread)
>        /* Supply the floating-point registers.  */
>        i387_supply_fsave (regcache, -1, state.hw_state);
>      }
> +#else
> +  gnu_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 +136,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 +155,11 @@ gnu_fetch_registers (struct target_ops *ops,
>    inf_update_procs (gnu_current_inf);
> 
>    thread = inf_tid_to_thread (gnu_current_inf,
> +#ifndef GDBSERVER
>        ptid_get_tid (inferior_ptid));
> +#else
> +      TIDGET (inferior_ptid));
> +#endif
>    if (!thread)
>      error (_("Can't fetch registers from thread %s: No such thread"),
>     target_pid_to_str (inferior_ptid));
> @@ -157,17 +184,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

I think it'd be better to add a wrapper function that adapts
the interfaces in one of the directions.

>    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 +218,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 +251,36 @@ store_fpregs (const struct regcache *regcache,
> struct proc *thread, int regno)
>         proc_string (thread));
>        return;
>      }
> +#else
> +  gnu_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,
> +#ifndef GDBSERVER
>        ptid_get_tid (inferior_ptid));
> +#else
> +        TIDGET (inferior_ptid));
> +#endif
>    if (!thread)
>      error (_("Couldn't store registers into thread %s: No such thread"),
>     target_pid_to_str (inferior_ptid));
> @@ -265,12 +320,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 +346,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 +379,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 +397,4 @@ _initialize_i386gnu_nat (void)
>    /* Register the target.  */
>    add_target (t);
>  }
> +#endif
> 
> ======================================================================
> 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.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 gnui386.mh.
>         (MIG): New tools.
>         (AWK): New tools.
>         * exc_request.defs: New file. Softlink to [gdb]/gdb/exc_request.defs.
>         * i386gnu-nat.c: New file. Softlink to [gdb]/gdb/i386gnu-nat.c.
>         * gnu-low.c: New file. Softlink to [gdb]/gdb/gnu-nat.c.
>         * gnu-low.h: New file. Softlink to [gdb]/gdb/gnu-nat.h.
>         * hostio.c: Add macro define PATH_MAX 512.
>         * i386gnu.mh: New file. Softlink to [gdb]/gdb/config/i386/i386gnu.mh.
>         * msg.defs: New file. Softlink to [gdb]/gdb/msg.defs.
>         * msg_reply.defs: New file. Softlink to [gdb]/gdb/msg_reply.defs.
>         * notify.defs: New file. Softlink to [gdb]/gdb/notify.defs.
>         * process_reply.defs: New file. Softlink to
> [gdb]/gdb/process_reply.defs.
>         * reply_mid_hack.awk: New file. Softlink to
> [gdb]/gdb/reply_mid_hack.awk.
>         * server.h: Add typedef long CORE_ADDR;
>         * 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 e8470a8..967cf57 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@
> @@ -172,7 +174,7 @@ OBS = agent.o ax.o inferiors.o regcache.o
> remote-utils.o server.o signals.o targ
>   xml-utils.o common-utils.o ptid.o buffer.o format.o filestuff.o \
>   dll.o notif.o tdesc.o \
>   $(XML_BUILTIN) \
> - $(DEPFILES) $(LIBOBJS)
> + $(DEPFILES) $(LIBOBJS) $(NATDEPFILES)
>  GDBREPLAY_OBS = gdbreplay.o version.o
>  GDBSERVER_LIBS = @GDBSERVER_LIBS@
>  XM_CLIBS = @LIBS@
> @@ -195,6 +197,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)" \
> @@ -228,7 +235,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) $<
> diff --git a/gdb/gdbserver/configure.ac b/gdb/gdbserver/configure.ac
> index b9928d7..21685db 100644
> --- a/gdb/gdbserver/configure.ac
> +++ b/gdb/gdbserver/configure.ac
> @@ -456,6 +456,31 @@ if $want_ipa ; then
>     fi
>  fi
> 
> +frags=
> +GDBSERVER=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}/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)
> +
>  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 879d0de..1d9bf7a 100644
> --- a/gdb/gdbserver/configure.srv
> +++ b/gdb/gdbserver/configure.srv
> @@ -118,6 +118,11 @@ 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="gnu-nat.o i386gnu-nat.o"
> + 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/exc_request.defs b/gdb/gdbserver/exc_request.defs
> new file mode 120000
> index 0000000..1b8d3cd
> --- /dev/null
> +++ b/gdb/gdbserver/exc_request.defs
> @@ -0,0 +1 @@
> +../exc_request.defs
> \ No newline at end of file
> diff --git a/gdb/gdbserver/gnu-nat.c b/gdb/gdbserver/gnu-nat.c
> new file mode 120000
> index 0000000..d72e184
> --- /dev/null
> +++ b/gdb/gdbserver/gnu-nat.c
> @@ -0,0 +1 @@
> +../gnu-nat.c
> \ No newline at end of file
> diff --git a/gdb/gdbserver/gnu-nat.h b/gdb/gdbserver/gnu-nat.h
> new file mode 120000
> index 0000000..397c15c
> --- /dev/null
> +++ b/gdb/gdbserver/gnu-nat.h
> @@ -0,0 +1 @@
> +../gnu-nat.h
> \ No newline at end of file
> diff --git a/gdb/gdbserver/hostio.c b/gdb/gdbserver/hostio.c
> index df94d31..f3af499 100644
> --- a/gdb/gdbserver/hostio.c
> +++ b/gdb/gdbserver/hostio.c
> @@ -25,6 +25,10 @@
>  #include <limits.h>
>  #include <unistd.h>
> 
> +#ifndef PATH_MAX
> +#define PATH_MAX 512
> +#endif

This should not be necessary anymore.  If your patch
against current mainline?

> +
>  extern int remote_debug;
> 
>  struct fd_list
> diff --git a/gdb/gdbserver/i386gnu-nat.c b/gdb/gdbserver/i386gnu-nat.c
> new file mode 120000
> index 0000000..c547b9b
> --- /dev/null
> +++ b/gdb/gdbserver/i386gnu-nat.c
> @@ -0,0 +1 @@
> +../i386gnu-nat.c
> \ No newline at end of file
> diff --git a/gdb/gdbserver/i386gnu.mh b/gdb/gdbserver/i386gnu.mh
> new file mode 120000
> index 0000000..0497c22
> --- /dev/null
> +++ b/gdb/gdbserver/i386gnu.mh
> @@ -0,0 +1 @@
> +../config/i386/i386gnu.mh
> \ No newline at end of file
> diff --git a/gdb/gdbserver/msg.defs b/gdb/gdbserver/msg.defs
> new file mode 120000
> index 0000000..a663adb
> --- /dev/null
> +++ b/gdb/gdbserver/msg.defs
> @@ -0,0 +1 @@
> +../msg.defs
> \ No newline at end of file
> diff --git a/gdb/gdbserver/msg_reply.defs b/gdb/gdbserver/msg_reply.defs
> new file mode 120000
> index 0000000..61e8053
> --- /dev/null
> +++ b/gdb/gdbserver/msg_reply.defs
> @@ -0,0 +1 @@
> +../msg_reply.defs
> \ No newline at end of file
> diff --git a/gdb/gdbserver/notify.defs b/gdb/gdbserver/notify.defs
> new file mode 120000
> index 0000000..8a2c79d
> --- /dev/null
> +++ b/gdb/gdbserver/notify.defs
> @@ -0,0 +1 @@
> +../notify.defs
> \ No newline at end of file
> diff --git a/gdb/gdbserver/process_reply.defs 
> b/gdb/gdbserver/process_reply.defs
> new file mode 120000
> index 0000000..7106ac0
> --- /dev/null
> +++ b/gdb/gdbserver/process_reply.defs
> @@ -0,0 +1 @@
> +../process_reply.defs
> \ No newline at end of file
> diff --git a/gdb/gdbserver/reply_mig_hack.awk 
> b/gdb/gdbserver/reply_mig_hack.awk
> new file mode 120000
> index 0000000..fa7d33a
> --- /dev/null
> +++ b/gdb/gdbserver/reply_mig_hack.awk
> @@ -0,0 +1 @@
> +../reply_mig_hack.awk
> \ No newline at end of file
> diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
> index 18d060c..20e88bf 100644
> --- a/gdb/gdbserver/server.h
> +++ b/gdb/gdbserver/server.h
> @@ -91,7 +91,8 @@ typedef unsigned char gdb_byte;
> 
>  /* FIXME: This should probably be autoconf'd for.  It's an integer type at
>     least the size of a (void *).  */
> -typedef long long CORE_ADDR;
> +//typedef long long CORE_ADDR;
> +typedef long CORE_ADDR;
> 
>  typedef long long LONGEST;
>  typedef unsigned long long ULONGEST;
> diff --git a/gdb/gdbserver/utils.c b/gdb/gdbserver/utils.c
> index 9706d74..d6dd4f9 100644
> --- a/gdb/gdbserver/utils.c
> +++ b/gdb/gdbserver/utils.c
> @@ -170,7 +170,6 @@ internal_error (const char *file, int line, const
> char *fmt, ...)
>  #define CELLSIZE 50
> 
>  /* Return the next entry in the circular buffer.  */
> -
>  static char *
>  get_cell (void)
>  {
> @@ -181,6 +180,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)
>  {
> 

Thanks,
-- 
Pedro Alves



reply via email to

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