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