From mboxrd@z Thu Jan 1 00:00:00 1970 From: "John S. Kallal" To: gdb-patches@sources.redhat.com, kettenis@science.uva.nl Subject: [PATCH RFC] Make lin-lwp.c functions use target vectors Date: Fri, 18 May 2001 17:50:00 -0000 Message-id: X-SW-Source: 2001-05/msg00361.html 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 * 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; }