This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[PATCH RFC] Make lin-lwp.c functions use target vectors
- To: gdb-patches at sources dot redhat dot com,kettenis at science dot uva dot nl
- Subject: [PATCH RFC] Make lin-lwp.c functions use target vectors
- From: "John S. Kallal" <kallal at home dot com>
- Date: Thu, 17 May 2001 21:27:18 -0400 (EDT)
- Fcc: sent-mail
This patch comes from my work trying to get Linux threaded
debugging working through GDBSERVER. As a start the following
patch somewhat makes the routines in lin-lwp.c work through
the target stack. However, the lin-lwp.c code still does
many system calls and other calls that do not go through
the target stack.
Am I coding this change correctly?
Is this change, the correct thing to do?
Whould it be better to place the lin-lwp target
into the target stack at some new stratum? Read
http://sources.redhat.com/ml/gdb/2001-05/msg00302.html.
Is it even practical to do threaded debugging
Linux to Linux via GDBSERVER, without doing major
changes to the GDB remote serial protocal and/or
GDBSERVER?
2001-05-18 John S. Kallal <jskallal@home.com>
* lin-lwp.c (get_target_below) : New function to get the current
target at the process_stratum.
* lin-lwp.c (find_target_stratum) : New function. This function
acts as a helper function to get_target_below.
* lin-lwp.c (lin_lwp_attach) : Change code to call target
function via target vector. (lin_lwp_attach) : Ditto.
(lin_lwp_detach) : Ditto. (resume_callback) : Ditto.
(lin_lwp_resume) : Ditto. (lin_lwp_wait) : Ditto at three places.
(lin_lwp_kill) : Ditto. (lin_lwp_create_inferior) : Ditto.
(lin_lwp_mourn_inferio) : Ditto. (lin_lwp_fetch_registers) :
Ditto. (lin_lwp_store_registers) : Ditto
(lin_lwp_xfer_memory) : Ditto.
* lin-lwp.c : Disable reference to external struct child_ops.
--- ../gdb+dejagnu-20010518-org/gdb/lin-lwp.c Wed May 16 12:03:55 2001
+++ gdb/lin-lwp.c Fri May 18 09:36:32 2001
@@ -117,9 +117,11 @@ ptid_t trap_ptid;
/* This module's target-specific operations. */
static struct target_ops lin_lwp_ops;
/* The standard child operations. */
+#if 0
extern struct target_ops child_ops;
+#endif
/* Since we cannot wait (in lin_lwp_wait) for the initial process and
any cloned processes with a single call to waitpid, we have to use
the WNOHANG flag and call waitpid in a loop. To optimize
@@ -143,8 +145,9 @@ static sigset_t blocked_mask;
/* Prototypes for local functions. */
static int stop_wait_callback (struct lwp_info *lp, void *data);
+static struct target_ops *get_target_below( void );
/* Initialize the list of LWPs. Note that this module, contrary to
what GDB's generic threads layer does for its thread list,
@@ -333,12 +336,16 @@ lin_lwp_attach_lwp (ptid_t ptid, int ver
static void
lin_lwp_attach (char *args, int from_tty)
{
struct lwp_info *lp;
+ struct target_ops *process_ops;
+ process_ops = get_target_below ();
/* FIXME: We should probably accept a list of process id's, and
attach all of them. */
- child_ops.to_attach (args, from_tty);
+ if ( process_ops!=NULL )
+ if ( (process_ops->to_attach)!=NULL )
+ process_ops->to_attach (args, from_tty);
/* Add the initial process as the first LWP to the list. */
lp = add_lwp (BUILD_LWP (PIDGET (inferior_ptid), PIDGET (inferior_ptid)));
@@ -391,8 +398,10 @@ detach_callback (struct lwp_info *lp, vo
static void
lin_lwp_detach (char *args, int from_tty)
{
+ struct target_ops *process_ops;
+
iterate_over_lwps (detach_callback, NULL);
/* Only the initial (uncloned) process should be left right now. */
gdb_assert (num_lwps == 1);
@@ -406,9 +415,13 @@ lin_lwp_detach (char *args, int from_tty
sigprocmask (SIG_SETMASK, &normal_mask, NULL);
sigemptyset (&blocked_mask);
inferior_ptid = pid_to_ptid (GET_PID (inferior_ptid));
- child_ops.to_detach (args, from_tty);
+
+ process_ops = get_target_below ();
+ if ( process_ops!=NULL )
+ if ( (process_ops->to_detach)!=NULL )
+ (process_ops->to_detach) (args, from_tty);
}
struct private_thread_info
@@ -434,8 +447,10 @@ find_lwp_callback (struct thread_info *t
static int
resume_callback (struct lwp_info *lp, void *data)
{
+ struct target_ops *process_ops;
+
if (lp->stopped && lp->status == 0)
{
struct thread_info *tp;
@@ -459,9 +474,14 @@ resume_callback (struct lwp_info *lp, vo
tp->step_range_start = tp->step_range_end = 0;
}
#endif
- child_resume (pid_to_ptid (GET_LWP (lp->ptid)), 0, TARGET_SIGNAL_0);
+ process_ops = get_target_below ();
+ if ( process_ops!=NULL )
+ if ( (process_ops->to_resume)!=NULL )
+ (process_ops->to_resume) (pid_to_ptid (GET_LWP (lp->ptid)),
+ 0, TARGET_SIGNAL_0);
+
lp->stopped = 0;
lp->step = 0;
}
@@ -470,8 +490,9 @@ resume_callback (struct lwp_info *lp, vo
static void
lin_lwp_resume (ptid_t ptid, int step, enum target_signal signo)
{
+ struct target_ops *process_ops;
struct lwp_info *lp;
int resume_all;
/* Apparently the interpretation of PID is dependent on STEP: If
@@ -510,9 +531,12 @@ lin_lwp_resume (ptid_t ptid, int step, e
if (resume_all)
iterate_over_lwps (resume_callback, NULL);
- child_resume (ptid, step, signo);
+ process_ops = get_target_below ();
+ if ( process_ops!=NULL )
+ if ( (process_ops->to_resume)!=NULL )
+ (process_ops->to_resume) (ptid, step, signo);
}
/* Send a SIGSTOP to LP. */
@@ -652,8 +676,9 @@ running_callback (struct lwp_info *lp, v
static ptid_t
lin_lwp_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
{
+ struct target_ops *process_ops;
struct lwp_info *lp = NULL;
int options = 0;
int status = 0;
pid_t pid = PIDGET (ptid);
@@ -726,10 +751,14 @@ lin_lwp_wait (ptid_t ptid, struct target
single-stepping LWP A. */
/* Resume the thread. It should halt immediately returning the
pending SIGSTOP. */
- child_resume (pid_to_ptid (GET_LWP (lp->ptid)), lp->step,
- TARGET_SIGNAL_0);
+ process_ops = get_target_below ();
+ if ( process_ops!=NULL )
+ if ( (process_ops->to_resume)!=NULL )
+ (process_ops->to_resume) (pid_to_ptid (GET_LWP (lp->ptid)),
+ lp->step,TARGET_SIGNAL_0);
+
lp->stopped = 0;
/* This should catch the pending SIGSTOP. */
stop_wait_callback (lp, NULL);
@@ -812,10 +841,14 @@ lin_lwp_wait (ptid_t ptid, struct target
/* This is a delayed SIGSTOP. */
lp->signalled = 0;
- child_resume (pid_to_ptid (GET_LWP (lp->ptid)), lp->step,
- TARGET_SIGNAL_0);
+ process_ops = get_target_below ();
+ if ( process_ops!=NULL )
+ if ( (process_ops->to_resume)!=NULL )
+ (process_ops->to_resume) (pid_to_ptid (GET_LWP (lp->ptid)),
+ lp->step, TARGET_SIGNAL_0);
+
lp->stopped = 0;
/* Discard the event. */
status = 0;
@@ -858,9 +891,15 @@ lin_lwp_wait (ptid_t ptid, struct target
if (signal_stop_state (signo) == 0
&& signal_print_state (signo) == 0
&& signal_pass_state (signo) == 1)
{
- child_resume (pid_to_ptid (GET_LWP (lp->ptid)), lp->step, signo);
+
+ process_ops = get_target_below ();
+ if ( process_ops!=NULL )
+ if ( (process_ops->to_resume)!=NULL )
+ (process_ops->to_resume) (pid_to_ptid (GET_LWP (lp->ptid)),
+ lp->step, signo);
+
lp->stopped = 0;
status = 0;
goto retry;
}
@@ -930,26 +969,38 @@ kill_wait_callback (struct lwp_info *lp,
static void
lin_lwp_kill (void)
{
+ struct target_ops *process_ops;
+
/* Kill all LWP's ... */
iterate_over_lwps (kill_callback, NULL);
/* ... and wait until we've flushed all events. */
iterate_over_lwps (kill_wait_callback, NULL);
- target_mourn_inferior ();
+ process_ops = get_target_below ();
+ if ( process_ops!=NULL )
+ if ( (process_ops->to_mourn_inferior)!=NULL )
+ (process_ops->to_mourn_inferior) ();
}
static void
lin_lwp_create_inferior (char *exec_file, char *allargs, char **env)
{
- child_ops.to_create_inferior (exec_file, allargs, env);
+ struct target_ops *process_ops;
+
+ process_ops = get_target_below ();
+ if ( process_ops!=NULL )
+ if ( (process_ops->to_create_inferior)!=NULL )
+ (process_ops->to_create_inferior) (exec_file, allargs, env);
}
-static void
+static void
lin_lwp_mourn_inferior (void)
{
+ struct target_ops *process_ops;
+
trap_ptid = null_ptid;
/* Destroy LWP info; it's no longer valid. */
init_lwp_list ();
@@ -957,33 +1008,44 @@ lin_lwp_mourn_inferior (void)
/* Restore the original signal mask. */
sigprocmask (SIG_SETMASK, &normal_mask, NULL);
sigemptyset (&blocked_mask);
- child_ops.to_mourn_inferior ();
+ process_ops = get_target_below ();
+ if ( process_ops!=NULL )
+ if ( (process_ops->to_mourn_inferior)!=NULL )
+ (process_ops->to_mourn_inferior ) ();
}
static void
lin_lwp_fetch_registers (int regno)
{
+ struct target_ops *process_ops;
struct cleanup *old_chain = save_inferior_ptid ();
if (is_lwp (inferior_ptid))
inferior_ptid = pid_to_ptid (GET_LWP (inferior_ptid));
- fetch_inferior_registers (regno);
+ process_ops = get_target_below ();
+ if ( process_ops!=NULL )
+ if ( (process_ops->to_fetch_registers)!=NULL )
+ (process_ops->to_fetch_registers) (regno);
do_cleanups (old_chain);
}
static void
lin_lwp_store_registers (int regno)
{
+ struct target_ops *process_ops;
struct cleanup *old_chain = save_inferior_ptid ();
if (is_lwp (inferior_ptid))
inferior_ptid = pid_to_ptid (GET_LWP (inferior_ptid));
- store_inferior_registers (regno);
+ process_ops = get_target_below ();
+ if ( process_ops!=NULL )
+ if ( (process_ops->to_store_registers)!=NULL )
+ (process_ops->to_store_registers) (regno);
do_cleanups (old_chain);
}
@@ -991,15 +1053,19 @@ static int
lin_lwp_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
struct mem_attrib *attrib,
struct target_ops *target)
{
+ struct target_ops *process_ops;
struct cleanup *old_chain = save_inferior_ptid ();
- int xfer;
+ int xfer = 0;
if (is_lwp (inferior_ptid))
inferior_ptid = pid_to_ptid (GET_LWP (inferior_ptid));
- xfer = child_xfer_memory (memaddr, myaddr, len, write, attrib, target);
+ process_ops = get_target_below ();
+ if ( process_ops!=NULL )
+ if ( (process_ops->to_xfer_memory)!=NULL )
+ xfer = (process_ops->to_xfer_memory) (memaddr, myaddr, len, write, attrib, target);
do_cleanups (old_chain);
return xfer;
}
@@ -1159,5 +1225,61 @@ lin_thread_get_thread_signals (sigset_t
sigprocmask (SIG_BLOCK, &blocked_mask, NULL);
/* ... except during a sigsuspend. */
sigdelset (&suspend_mask, cancel);
+}
+
+/*
+ * FIXME: I truely should use a target stack macro/function that
+ * returns the next lower target that has a non-NULL pointer in a
+ * given function pointer. What if a new stratum is added just above
+ * the process_stratum? Should the process_stratum or the new
+ * stratum's function be called. I think in general that it
+ * should be the next lower startum's that has the non-NULL
+ * given function pointer.
+ *
+ * This is a job for a portable C coding wizard.
+ *
+ * John S. Kallal 2001-MAY-18
+ */
+
+
+/*
+ * FIXME: Maybe function find_target_stratum() this should go
+ * into the target.c file? But for now only this file needs
+ * this function. Better yet, put the lwp-layer target into
+ * the target stack.
+ * John S. Kallal 2001-MAY-18
+ */
+/* Find a single target at the given stratum level in the target stack
+ * and return a pointer to it. If there is no target at the given
+ * stratum level in the target stack, return NULL.
+ */
+
+static struct target_ops *
+find_target_stratum ( enum strata level )
+{
+ struct target_stack_item *cur;
+
+ for (cur = target_stack; cur; cur = cur->next)
+ {
+ if ( cur->target_ops->to_stratum == level )
+ return cur->target_ops;
+ }
+
+ return NULL;
+}
+
+/*
+ * Find the target below the thread_stratum (i.e process_stratum).
+ * This is needed because currently the lwp-layer
+ * is NOT stacked.
+ */
+static struct target_ops *
+get_target_below ( void )
+{
+ struct target_ops *process_ops;
+
+ process_ops = find_target_stratum( process_stratum );
+
+ return process_ops;
}