[RFC] Making target layers into a real stack

John S. Kallal
2001-06-20T14:01:00Z

Andrew Cagney,

In message http://sources.redhat.com/ml/gdb/2001-06/msg00015.html you
indicated interest in changes that start converting the target layers
into a real stack.

How about the following patch that use a mix of macros and subroutines
in files target.h and target.c. How to use the macros in shown by
changing the files lin-lwp.c and thread-db.c to using the macros.

If you think that this is the way to make the target layers into
something more stack-like you can apply the patch. If you think
that another way should be used, can you please give me some
pointer as to how to stack should be redesigned?

2001-06-20 John S. Kallal <jskallal@home.com>

* target.h : Added lwp_stratum and top_stratum to enum strata.
Created new macros VECTOR_TYPEDEF, VECTOR_STRUCT,
GET_TARGET_OPS_BELOW, GET_TARGET_OPS_At, and MAKE_TYPE_NAME.
Rewrote struct target_ops in using macros VECTOR_TYPEDEF and
VECTOR_STRUCT. Added protoypes for new functions
find_vector_below, find_vector_at, and find_target_stratum.

* target.c (find_target_stratum) : New function.
(find_vector_below) : New function.
(find_vector_at) : New function.
(push_target) : Added stratum level range check before
inserting target struct into the target stack.

* lin-lwp.c : Disable 'extern struct target_ops child_ops'.
(lin_lwp_open) : Enable function.
(lin_lwp_attach) : Change to code to call target
function using macro GET_TARGET_OPS_BELOW.
(lin_lwp_detach) : Likewise.
(resume_callback) : Likewise.
(lin_lwp_resume) : Likewise.
(lin_lwp_wait) : Likewise in three places.
(lin_lwp_create_inferior) : Likewise.
(lin_lwp_mourn_inferior) : Likewise.
(lin_lwp_fetch_registers) : Likewise.
(init_lin_lwp_ops) : Changed stratum level assigned to
lin_lwp_ops from threads_stratum to lwp_stratum.

* thread-db.c : Changed name of variable from target_beneath
to target_lwp.
(thread_db_new_objfile) : Added a call to activate the
lwp_stratum target.
(thread_db_attach) : Change to code to call target
function using macro GET_TARGET_OPS_BELOW.
(thread_db_detach) : Likewise.
(thread_db_resume) : Likewise.
(thread_db_wait) : Likewise.
(thread_db_xfer_memory) : Likewise.
(thread_db_fetch_registers) : Likewise.
(thread_db_store_registers) : Likewise.
(thread_db_kill) : Likewise.
(thread_db_create_inferior) : Likewise.
(thread_db_post_startup_inferior) : Likewise.
(thread_db_pid_to_str) : Likewise.
(thread_db_thread_alive) : Change to code to call target
function using macro GET_TARGET_OPS_AT.

diff -u4pr ../gdb+dejagnu-20010612-org/gdb/lin-lwp.c gdb/lin-lwp.c
--- ../gdb+dejagnu-20010612-org/gdb/lin-lwp.c Thu Jun 7 15:31:10 2001
+++ gdb/lin-lwp.c Wed Jun 20 09:23:51 2001
@@ -124,10 +124,12 @@ ptid_t trap_ptid;

/* This module's target-specific operations. */
static struct target_ops lin_lwp_ops;

+#if 0
/* The standard child operations. */
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
@@ -309,15 +311,13 @@ lin_lwp_prepare_to_proceed (void)
return 0;
}
\f

-#if 0
static void
lin_lwp_open (char *args, int from_tty)
{
push_target (&lin_lwp_ops);
}
-#endif

/* Attach to the LWP specified by PID. If VERBOSE is non-zero, print
a message telling the user that a new LWP has been added to the
process. */
@@ -353,9 +353,9 @@ lin_lwp_attach (char *args, int from_tty
struct lwp_info *lp;

/* FIXME: We should probably accept a list of process id's, and
attach all of them. */
- child_ops.to_attach (args, from_tty);
+ (GET_TARGET_OPS_BELOW(lwp_stratum,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)));

@@ -425,9 +425,9 @@ 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);
+ (GET_TARGET_OPS_BELOW(lwp_stratum,to_detach)) (args, from_tty);
}
\f

struct private_thread_info
@@ -478,9 +478,10 @@ 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);
+ (GET_TARGET_OPS_BELOW(lwp_stratum,to_resume))
+ (pid_to_ptid (GET_LWP (lp->ptid)), 0, TARGET_SIGNAL_0);
lp->stopped = 0;
lp->step = 0;
}

@@ -551,9 +552,9 @@ lin_lwp_resume (ptid_t ptid, int step, e

if (resume_all)
iterate_over_lwps (resume_callback, NULL);

- child_resume (ptid, step, signo);
+ (GET_TARGET_OPS_BELOW(lwp_stratum,to_resume)) (ptid, step, signo);
}
\f

/* Send a SIGSTOP to LP. */
@@ -797,10 +798,10 @@ 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);
+ (GET_TARGET_OPS_BELOW(lwp_stratum,to_resume))
+ (pid_to_ptid (GET_LWP (lp->ptid)), lp->step,TARGET_SIGNAL_0);
lp->stopped = 0;
gdb_assert (lp->resumed);

/* This should catch the pending SIGSTOP. */
@@ -884,10 +885,10 @@ 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);
+ (GET_TARGET_OPS_BELOW(lwp_stratum,to_resume))
+ (pid_to_ptid (GET_LWP (lp->ptid)), lp->step,
TARGET_SIGNAL_0);
lp->stopped = 0;
gdb_assert (lp->resumed);

/* Discard the event. */
@@ -936,9 +937,10 @@ lin_lwp_wait (ptid_t ptid, struct target
here? It is not clear we should. GDB may not expect
other threads to run. On the other hand, not resuming
newly attached threads may cause an unwanted delay in
getting them running. */
- child_resume (pid_to_ptid (GET_LWP (lp->ptid)), lp->step, signo);
+ (GET_TARGET_OPS_BELOW(lwp_stratum,to_resume))
+ (pid_to_ptid (GET_LWP (lp->ptid)), lp->step, signo);
lp->stopped = 0;
status = 0;
goto retry;
}
@@ -1020,9 +1022,10 @@ lin_lwp_kill (void)

static void
lin_lwp_create_inferior (char *exec_file, char *allargs, char **env)
{
- child_ops.to_create_inferior (exec_file, allargs, env);
+ (GET_TARGET_OPS_BELOW(lwp_stratum,to_create_inferior))
+ (exec_file, allargs, env);
}

static void
lin_lwp_mourn_inferior (void)
@@ -1035,9 +1038,9 @@ lin_lwp_mourn_inferior (void)
/* Restore the original signal mask. */
sigprocmask (SIG_SETMASK, &normal_mask, NULL);
sigemptyset (&blocked_mask);

- child_ops.to_mourn_inferior ();
+ (GET_TARGET_OPS_BELOW(lwp_stratum,to_mourn_inferior)) ();
}

static void
lin_lwp_fetch_registers (int regno)
@@ -1075,10 +1078,10 @@ lin_lwp_xfer_memory (CORE_ADDR memaddr,

if (is_lwp (inferior_ptid))
inferior_ptid = pid_to_ptid (GET_LWP (inferior_ptid));

- xfer = child_xfer_memory (memaddr, myaddr, len, write, attrib, target);
-
+ xfer = (GET_TARGET_OPS_BELOW(lwp_stratum,to_xfer_memory))
+ (memaddr, myaddr, len, write, attrib, target);
do_cleanups (old_chain);
return xfer;
}

@@ -1129,9 +1132,9 @@ init_lin_lwp_ops (void)
lin_lwp_ops.to_create_inferior = lin_lwp_create_inferior;
lin_lwp_ops.to_mourn_inferior = lin_lwp_mourn_inferior;
lin_lwp_ops.to_thread_alive = lin_lwp_thread_alive;
lin_lwp_ops.to_pid_to_str = lin_lwp_pid_to_str;
- lin_lwp_ops.to_stratum = thread_stratum;
+ lin_lwp_ops.to_stratum = lwp_stratum;
lin_lwp_ops.to_has_thread_control = tc_schedlock;
lin_lwp_ops.to_magic = OPS_MAGIC;
}

@@ -1147,13 +1150,13 @@ void
_initialize_lin_lwp (void)
{
struct sigaction action;

- extern void thread_db_init (struct target_ops *);
+ extern void thread_db_init(struct target_ops *);

init_lin_lwp_ops ();
add_target (&lin_lwp_ops);
- thread_db_init (&lin_lwp_ops);
+ thread_db_init(&lin_lwp_ops);

/* Save the original signal mask. */
sigprocmask (SIG_SETMASK, NULL, &normal_mask);

diff -u4pr ../gdb+dejagnu-20010612-org/gdb/target.c gdb/target.c
--- ../gdb+dejagnu-20010612-org/gdb/target.c Fri May 4 00:15:27 2001
+++ gdb/target.c Wed Jun 20 13:23:33 2001
@@ -640,8 +640,18 @@ push_target (struct target_ops *t)
t->to_shortname);
internal_error (__FILE__, __LINE__, "failed internal consistency
check");
}

+ /* Check the stratum level. If wrong, we have an internal error. */
+ if (t->to_stratum < dummy_stratum || top_stratum <= t->to_stratum)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Target struct %s have a invalid stratum level of %d\n",
+ t->to_shortname, t->to_stratum);
+ internal_error (__FILE__, __LINE__, "failed internal consistency
check");
+ }
+
+
/* Find the proper stratum to install this target in. */

for (prev = NULL, cur = target_stack; cur; prev = cur, cur = cur->next)
{
@@ -1367,9 +1377,116 @@ find_target_beneath (struct target_ops *
else
return cur->next->target_ops;
}

+/* Search the current target stack for the target of the
+ * indicated stratum. If a target of the given stratam
+ * level is found in the target stack, return a pounter
+ * to the target_ops structure. Otherwise return a NULL
+ * pointer. */
+
+struct target_ops *
+find_target_stratum (enum strata strat_find)
+{
+ struct target_stack_item *cur;
+
+ for (cur = target_stack; cur; cur = cur->next)
+ {
+ if (cur->target_ops->to_stratum == strat_find)
+ return cur->target_ops;
+ }
+
+ return NULL;
+}
+
+/* Lookup in the current target stack starting under and
+ * below the given strata for a non-null target function
+ * pointer at the given offset. Return with the first
+ * non-NULL pointer located. If a non-NULL function pointer
+ * can not be found, this function calls internal_error.
+ *
+ * If this function is called with an offset that is not
+ * function pointer member within the target structure,
+ * the results are undefined.
+ *
+ * This function is called by the macro GET_TARGET_OPS_AT
+ * to get addresses of the indicated target vector function. */
+
+void_funct_t *
+find_vector_below (enum strata strat_under, size_t vec_offset)
+{
+ struct target_stack_item *cur;
+ char * vector;
+ void_funct_t * target_vector = NULL;
+
+ for (cur = target_stack; cur; cur = cur->next)
+ {
+ if (cur->target_ops->to_stratum < strat_under )
+ {
+ vector = vec_offset + (char *)(cur->target_ops);
+ memcpy (&target_vector, vector, sizeof(target_vector));
+ if (target_vector != NULL)
+ break;
+ }
+ }
+
+ if (target_vector == NULL )
+ {
+ internal_error (__FILE__, __LINE__,
+ "failed internal consistency check in find_vector_below");
+ }
+ return target_vector;
+}
+
+
+/* Return the target function pointer of the given
+ * stratum and offset in the target stack.
+ * If a non-NULL target vector can not be found,
+ * a this function calls internal_error.
+ *
+ * If this function is called with an offset that is not
+ * the offset function pointer within the target structure,
+ * the results are undefined.
+ *
+ * This function is called by the macro GET_TARGET_OPS_AT
+ * to get addresses of the indicated target vector function. */
+
+void_funct_t *
+find_vector_at (enum strata strat_at, size_t vec_offset)
+{
+ struct target_stack_item *cur;
+ char * vector;
+ enum strata cur_strata;
+ void_funct_t * target_vector = NULL;
+
+ for (cur = target_stack; cur; cur = cur->next)
+ {
+ cur_strata = (cur->target_ops->to_stratum);
+ if (cur_strata == strat_at)
+ break;
+ }
+
+ if (cur == NULL || cur_strata != strat_at )
+ {
+ internal_error (__FILE__, __LINE__,
+ "failed internal consistency check in find_vector_at");
+ return NULL;
+ }
+
+ vector = vec_offset + (char *)(cur->target_ops);
+ memcpy (&target_vector, vector, sizeof(target_vector));
+
+ if (!target_vector)
+ {
+ internal_error (__FILE__, __LINE__,
+ "failed internal consistency check in find_vector_at");
+ return NULL;
+ }
+ return target_vector;
+}
+
\f
+
/* The inferior process has died. Long live the inferior! */

void
generic_mourn_inferior (void)
diff -u4pr ../gdb+dejagnu-20010612-org/gdb/target.h gdb/target.h
--- ../gdb+dejagnu-20010612-org/gdb/target.h Fri May 4 00:15:27 2001
+++ gdb/target.h Wed Jun 20 13:09:30 2001
@@ -53,9 +53,13 @@ enum strata
file_stratum, /* Executable files, etc */
core_stratum, /* Core dump files */
download_stratum, /* Downloading of remote targets */
process_stratum, /* Executing processes */
- thread_stratum /* Executing threads */
+ lwp_stratum, /* Executing light weight processes */
+ thread_stratum, /* Executing threads */
+ top_stratum /* top stratum level */
+ /* The top_stratum must be the highest stratum
+ level and unused by any target. */
};

enum thread_control_capabilities
{
@@ -178,31 +182,43 @@ enum target_signal target_signal_from_na
on TARGET_ACTIVITY_FD. */
extern int target_activity_fd;
/* Returns zero to leave the inferior alone, one to interrupt it. */
extern int (*target_activity_function) (void);
-\f
+
struct thread_info; /* fwd decl for parameter list below: */
+\f

-struct target_ops
- {
- char *to_shortname; /* Name this target type */
- char *to_longname; /* Name for printing */
- char *to_doc; /* Documentation. Does not include trailing
- newline, and starts with a one-line descrip-
- tion (probably similar to to_longname). */
- void (*to_open) (char *, int);
- void (*to_close) (int);
- void (*to_attach) (char *, int);
- void (*to_post_attach) (int);
- void (*to_require_attach) (char *, int);
- void (*to_detach) (char *, int);
- void (*to_require_detach) (int, char *, int);
- void (*to_resume) (ptid_t, int, enum target_signal);
- ptid_t (*to_wait) (ptid_t, struct target_waitstatus *);
- void (*to_post_wait) (ptid_t, int);
- void (*to_fetch_registers) (int);
- void (*to_store_registers) (int);
- void (*to_prepare_to_store) (void);
+#define VECTOR_TYPEDEF(type,name,call) \
+ typedef type (*MAKE_TYPE_NAME(_, name, _td)) call
+
+#define VECTOR_STRUCT(name) MAKE_TYPE_NAME(_, name, _td) name
+
+#define GET_TARGET_OPS_BELOW(stratum,name) \
+ ( (MAKE_TYPE_NAME(_, name, _td)) find_vector_below \
+ (stratum, offsetof(struct target_ops,name)) )
+
+#define GET_TARGET_OPS_AT(stratum,name) \
+ ( (MAKE_TYPE_NAME(_, name, _td)) find_vector_at \
+ (stratum, offsetof(struct target_ops,name)) )
+
+#define MAKE_TYPE_NAME(part1,part2,part3) part1 ## part2 ## part3
+
+/* Now make typedefs for each operation pointer to be included
+ in struct target_ops using macro VECTOR_TYPEDEF. */
+
+VECTOR_TYPEDEF(void,to_open,(char *, int));
+VECTOR_TYPEDEF(void,to_close,(int));
+VECTOR_TYPEDEF(void,to_attach,(char *, int));
+VECTOR_TYPEDEF(void,to_post_attach,(int));
+VECTOR_TYPEDEF(void,to_require_attach,(char *, int));
+VECTOR_TYPEDEF(void,to_detach,(char *, int));
+VECTOR_TYPEDEF(void,to_require_detach,(int, char *, int));
+VECTOR_TYPEDEF(void,to_resume,(ptid_t, int, enum target_signal));
+VECTOR_TYPEDEF(ptid_t,to_wait,(ptid_t, struct target_waitstatus *));
+VECTOR_TYPEDEF(void,to_post_wait,(ptid_t, int));
+VECTOR_TYPEDEF(void,to_fetch_registers,(int));
+VECTOR_TYPEDEF(void,to_store_registers,(int));
+VECTOR_TYPEDEF(void,to_prepare_to_store,(void));

/* Transfer LEN bytes of memory between GDB address MYADDR and
target address MEMADDR. If WRITE, transfer them to the target, else
transfer them from the target. TARGET is the target from which we
@@ -220,12 +236,75 @@ struct target_ops
negative (call its absolute value N) means that we cannot
transfer right at MEMADDR, but we could transfer at least
something at MEMADDR + N. */

- int (*to_xfer_memory) (CORE_ADDR memaddr, char *myaddr,
- int len, int write,
- struct mem_attrib *attrib,
- struct target_ops *target);
+VECTOR_TYPEDEF(int,to_xfer_memory,(CORE_ADDR memaddr,char *myaddr, int len,
int write,struct mem_attrib *attrib,struct target_ops *target));
+VECTOR_TYPEDEF(void,to_files_info,(struct target_ops *));
+VECTOR_TYPEDEF(int,to_insert_breakpoint,(CORE_ADDR, char *));
+VECTOR_TYPEDEF(int,to_remove_breakpoint,(CORE_ADDR, char *));
+VECTOR_TYPEDEF(void,to_terminal_init,(void));
+VECTOR_TYPEDEF(void,to_terminal_inferior,(void));
+VECTOR_TYPEDEF(void,to_terminal_ours_for_output,(void));
+VECTOR_TYPEDEF(void,to_terminal_ours,(void));
+VECTOR_TYPEDEF(void,to_terminal_info,(char *, int));
+VECTOR_TYPEDEF(void,to_kill,(void));
+VECTOR_TYPEDEF(void,to_load,(char *, int));
+VECTOR_TYPEDEF(int,to_lookup_symbol,(char *, CORE_ADDR *));
+VECTOR_TYPEDEF(void,to_create_inferior,(char *, char *, char **));
+VECTOR_TYPEDEF(void,to_post_startup_inferior,(ptid_t));
+VECTOR_TYPEDEF(void,to_acknowledge_created_inferior,(int));
+VECTOR_TYPEDEF(void,to_clone_and_follow_inferior,(int, int *));
+VECTOR_TYPEDEF(void,to_post_follow_inferior_by_clone,(void));
+VECTOR_TYPEDEF(int,to_insert_fork_catchpoint,(int));
+VECTOR_TYPEDEF(int,to_remove_fork_catchpoint,(int));
+VECTOR_TYPEDEF(int,to_insert_vfork_catchpoint,(int));
+VECTOR_TYPEDEF(int,to_remove_vfork_catchpoint,(int));
+VECTOR_TYPEDEF(int,to_has_forked,(int, int *));
+VECTOR_TYPEDEF(int,to_has_vforked,(int, int *));
+VECTOR_TYPEDEF(int,to_can_follow_vfork_prior_to_exec,(void));
+VECTOR_TYPEDEF(void,to_post_follow_vfork,(int, int, int, int));
+VECTOR_TYPEDEF(int,to_insert_exec_catchpoint,(int));
+VECTOR_TYPEDEF(int,to_remove_exec_catchpoint,(int));
+VECTOR_TYPEDEF(int,to_has_execd,(int, char **));
+VECTOR_TYPEDEF(int,to_reported_exec_events_per_exec_call,(void));
+VECTOR_TYPEDEF(int,to_has_syscall_event,(int, enum target_waitkind *, int
*));
+VECTOR_TYPEDEF(int,to_has_exited,(int, int, int *));
+VECTOR_TYPEDEF(void,to_mourn_inferior,(void));
+VECTOR_TYPEDEF(int,to_can_run,(void));
+VECTOR_TYPEDEF(void,to_notice_signals,(ptid_t ptid));
+VECTOR_TYPEDEF(int,to_thread_alive,(ptid_t ptid));
+VECTOR_TYPEDEF(void,to_find_new_threads,(void));
+VECTOR_TYPEDEF(char *,to_pid_to_str,(ptid_t));
+VECTOR_TYPEDEF(char *,to_extra_thread_info,(struct thread_info *));
+VECTOR_TYPEDEF(void,to_stop,(void));
+VECTOR_TYPEDEF(int,to_query,(int /*char */ , char *, char *, int *));
+VECTOR_TYPEDEF(void,to_rcmd,(char *command, struct ui_file *output));
+VECTOR_TYPEDEF(struct symtab_and_line *,to_enable_exception_callback,(enum
exception_event_kind,int));
+VECTOR_TYPEDEF(struct exception_event_record
*,to_get_current_exception_event,(void));
+VECTOR_TYPEDEF(char *,to_pid_to_exec_file,(int pid));
+
+
+struct target_ops
+ {
+ char *to_shortname; /* Name this target type */
+ char *to_longname; /* Name for printing */
+ char *to_doc; /* Documentation. Does not include trailing
+ newline, and starts with a one-line descrip-
+ tion (probably similar to to_longname). */
+ VECTOR_STRUCT(to_open);
+ VECTOR_STRUCT(to_close);
+ VECTOR_STRUCT(to_attach);
+ VECTOR_STRUCT(to_post_attach);
+ VECTOR_STRUCT(to_require_attach);
+ VECTOR_STRUCT(to_detach);
+ VECTOR_STRUCT(to_require_detach);
+ VECTOR_STRUCT(to_resume);
+ VECTOR_STRUCT(to_wait);
+ VECTOR_STRUCT(to_post_wait);
+ VECTOR_STRUCT(to_fetch_registers);
+ VECTOR_STRUCT(to_store_registers);
+ VECTOR_STRUCT(to_prepare_to_store);
+ VECTOR_STRUCT(to_xfer_memory);

#if 0
/* Enable this after 4.12. */

@@ -247,54 +326,52 @@ struct target_ops
#define target_search(len, data, mask, startaddr, increment, lorange,
hirange, addr_found, data_found) \
(*current_target.to_search) (len, data, mask, startaddr, increment, \
lorange, hirange, addr_found, data_found)
#endif /* 0 */
+ VECTOR_STRUCT(to_files_info);
+ VECTOR_STRUCT(to_insert_breakpoint);
+ VECTOR_STRUCT(to_remove_breakpoint);
+ VECTOR_STRUCT(to_terminal_init);
+ VECTOR_STRUCT(to_terminal_inferior);
+ VECTOR_STRUCT(to_terminal_ours_for_output);
+ VECTOR_STRUCT(to_terminal_ours);
+ VECTOR_STRUCT(to_terminal_info);
+ VECTOR_STRUCT(to_kill);
+ VECTOR_STRUCT(to_load);
+ VECTOR_STRUCT(to_lookup_symbol);
+ VECTOR_STRUCT(to_create_inferior);
+ VECTOR_STRUCT(to_post_startup_inferior);
+ VECTOR_STRUCT(to_acknowledge_created_inferior);
+ VECTOR_STRUCT(to_clone_and_follow_inferior);
+ VECTOR_STRUCT(to_post_follow_inferior_by_clone);
+ VECTOR_STRUCT(to_insert_fork_catchpoint);
+ VECTOR_STRUCT(to_remove_fork_catchpoint);
+ VECTOR_STRUCT(to_insert_vfork_catchpoint);
+ VECTOR_STRUCT(to_remove_vfork_catchpoint);
+ VECTOR_STRUCT(to_has_forked);
+ VECTOR_STRUCT(to_has_vforked);
+ VECTOR_STRUCT(to_can_follow_vfork_prior_to_exec);
+ VECTOR_STRUCT(to_post_follow_vfork);
+ VECTOR_STRUCT(to_insert_exec_catchpoint);
+ VECTOR_STRUCT(to_remove_exec_catchpoint);
+ VECTOR_STRUCT(to_has_execd);
+ VECTOR_STRUCT(to_reported_exec_events_per_exec_call);
+ VECTOR_STRUCT(to_has_syscall_event);
+ VECTOR_STRUCT(to_has_exited);
+ VECTOR_STRUCT(to_mourn_inferior);
+ VECTOR_STRUCT(to_can_run);
+ VECTOR_STRUCT(to_notice_signals);
+ VECTOR_STRUCT(to_thread_alive);
+ VECTOR_STRUCT(to_find_new_threads);
+ VECTOR_STRUCT(to_pid_to_str);
+ VECTOR_STRUCT(to_extra_thread_info);
+ VECTOR_STRUCT(to_stop);
+ VECTOR_STRUCT(to_query);
+ VECTOR_STRUCT(to_rcmd);
+ VECTOR_STRUCT(to_enable_exception_callback);
+ VECTOR_STRUCT(to_get_current_exception_event);
+ VECTOR_STRUCT(to_pid_to_exec_file);

- void (*to_files_info) (struct target_ops *);
- int (*to_insert_breakpoint) (CORE_ADDR, char *);
- int (*to_remove_breakpoint) (CORE_ADDR, char *);
- void (*to_terminal_init) (void);
- void (*to_terminal_inferior) (void);
- void (*to_terminal_ours_for_output) (void);
- void (*to_terminal_ours) (void);
- void (*to_terminal_info) (char *, int);
- void (*to_kill) (void);
- void (*to_load) (char *, int);
- int (*to_lookup_symbol) (char *, CORE_ADDR *);
- void (*to_create_inferior) (char *, char *, char **);
- void (*to_post_startup_inferior) (ptid_t);
- void (*to_acknowledge_created_inferior) (int);
- void (*to_clone_and_follow_inferior) (int, int *);
- void (*to_post_follow_inferior_by_clone) (void);
- int (*to_insert_fork_catchpoint) (int);
- int (*to_remove_fork_catchpoint) (int);
- int (*to_insert_vfork_catchpoint) (int);
- int (*to_remove_vfork_catchpoint) (int);
- int (*to_has_forked) (int, int *);
- int (*to_has_vforked) (int, int *);
- int (*to_can_follow_vfork_prior_to_exec) (void);
- void (*to_post_follow_vfork) (int, int, int, int);
- int (*to_insert_exec_catchpoint) (int);
- int (*to_remove_exec_catchpoint) (int);
- int (*to_has_execd) (int, char **);
- int (*to_reported_exec_events_per_exec_call) (void);
- int (*to_has_syscall_event) (int, enum target_waitkind *, int *);
- int (*to_has_exited) (int, int, int *);
- void (*to_mourn_inferior) (void);
- int (*to_can_run) (void);
- void (*to_notice_signals) (ptid_t ptid);
- int (*to_thread_alive) (ptid_t ptid);
- void (*to_find_new_threads) (void);
- char *(*to_pid_to_str) (ptid_t);
- char *(*to_extra_thread_info) (struct thread_info *);
- void (*to_stop) (void);
- int (*to_query) (int /*char */ , char *, char *, int *);
- void (*to_rcmd) (char *command, struct ui_file *output);
- struct symtab_and_line *(*to_enable_exception_callback) (enum
- exception_event_kind,
- int);
- struct exception_event_record *(*to_get_current_exception_event) (void);
- char *(*to_pid_to_exec_file) (int pid);
enum strata to_stratum;
struct target_ops
*DONT_USE; /* formerly to_next */
int to_has_all_memory;
@@ -1195,8 +1272,18 @@ extern struct target_ops *find_run_targe

extern struct target_ops *find_core_target (void);

extern struct target_ops *find_target_beneath (struct target_ops *);
+
+struct target_ops * find_target_stratum (enum strata strat_find);
+
+
+typedef void (void_funct_t)(void);
+
+void_funct_t * find_vector_below (enum strata strat_at, size_t vec_offset);
+
+void_funct_t * find_vector_at (enum strata strat_at, size_t vec_offset);
+

extern int
target_resize_to_sections (struct target_ops *target, int num_added);

diff -u4pr ../gdb+dejagnu-20010612-org/gdb/thread-db.c gdb/thread-db.c
--- ../gdb+dejagnu-20010612-org/gdb/thread-db.c Tue May 22 20:06:15 2001
+++ gdb/thread-db.c Wed Jun 20 13:11:41 2001
@@ -46,10 +46,11 @@

/* This module's target vector. */
static struct target_ops thread_db_ops;

+
/* The target vector that we call for things this module can't handle. */
-static struct target_ops *target_beneath;
+static struct target_ops *target_lwp;

/* Pointer to the next function on the objfile event chain. */
static void (*target_new_objfile_chain) (struct objfile *objfile);

@@ -275,9 +276,9 @@ lwp_from_thread (ptid_t ptid)

void
thread_db_init (struct target_ops *target)
{
- target_beneath = target;
+ target_lwp = target;
}

static int
thread_db_load (void)
@@ -520,8 +521,15 @@ thread_db_new_objfile (struct objfile *o

case TD_OK:
/* The thread library was detected. Activate the thread_db target. */
push_target (&thread_db_ops);
+
+
+ /* Activate lwp_stratum target which this target requires. */
+ /* FIXME: Is this the proper way to activate the lwp_stratum target?
+ John S. Kallal 2001 June 20 */
+ push_target (target_lwp);
+
using_thread_db = 1;

/* If the thread library was detected in the main symbol file
itself, we assume that the program was statically linked
@@ -590,9 +598,9 @@ attach_thread (ptid_t ptid, const td_thr

static void
thread_db_attach (char *args, int from_tty)
{
- target_beneath->to_attach (args, from_tty);
+ (GET_TARGET_OPS_BELOW(thread_stratum,to_attach)) (args, from_tty);

/* Destroy thread info; it's no longer valid. */
init_thread_list ();

@@ -624,9 +632,9 @@ thread_db_detach (char *args, int from_t
/* Forget about the child's process ID. We shouldn't need it
anymore. */
proc_handle.pid = 0;

- target_beneath->to_detach (args, from_tty);
+ (GET_TARGET_OPS_BELOW(thread_stratum,to_detach)) (args, from_tty);
}

static void
thread_db_resume (ptid_t ptid, int step, enum target_signal signo)
@@ -637,9 +645,9 @@ thread_db_resume (ptid_t ptid, int step,
inferior_ptid = lwp_from_thread (inferior_ptid);
else if (is_thread (ptid))
ptid = lwp_from_thread (ptid);

- target_beneath->to_resume (ptid, step, signo);
+ (GET_TARGET_OPS_BELOW(thread_stratum,to_resume)) (ptid, step, signo);

do_cleanups (old_chain);
}

@@ -720,9 +728,9 @@ thread_db_wait (ptid_t ptid, struct targ

if (GET_PID (ptid) != -1 && is_thread (ptid))
ptid = lwp_from_thread (ptid);

- ptid = target_beneath->to_wait (ptid, ourstatus);
+ ptid = (GET_TARGET_OPS_BELOW(thread_stratum,to_wait)) (ptid, ourstatus);

if (proc_handle.pid == 0)
/* The current child process isn't the actual multi-threaded
program yet, so don't try to do any special thread-specific
@@ -760,9 +768,10 @@ thread_db_xfer_memory (CORE_ADDR memaddr
else
inferior_ptid = lwp_from_thread (inferior_ptid);
}

- xfer = target_beneath->to_xfer_memory (memaddr, myaddr, len, write,
attrib, target);
+ xfer = (GET_TARGET_OPS_BELOW(thread_stratum,to_xfer_memory))
+ (memaddr, myaddr, len, write, attrib, target);

do_cleanups (old_chain);
return xfer;
}
@@ -777,9 +786,9 @@ thread_db_fetch_registers (int regno)

if (! is_thread (inferior_ptid))
{
/* Pass the request to the target beneath us. */
- target_beneath->to_fetch_registers (regno);
+ (GET_TARGET_OPS_BELOW(thread_stratum,to_fetch_registers)) (regno);
return;
}

err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th);
@@ -814,9 +823,9 @@ thread_db_store_registers (int regno)

if (! is_thread (inferior_ptid))
{
/* Pass the request to the target beneath us. */
- target_beneath->to_store_registers (regno);
+ (GET_TARGET_OPS_BELOW(thread_stratum,to_store_registers)) (regno);
return;
}

err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th);
@@ -851,9 +860,9 @@ thread_db_kill (void)
{
/* There's no need to save & restore inferior_ptid here, since the
inferior isn't supposed to survive this function call. */
inferior_ptid = lwp_from_thread (inferior_ptid);
- target_beneath->to_kill ();
+ (GET_TARGET_OPS_BELOW(thread_stratum,to_kill)) ();
}

static void
thread_db_create_inferior (char *exec_file, char *allargs, char **env)
@@ -863,9 +872,9 @@ thread_db_create_inferior (char *exec_fi
unpush_target (&thread_db_ops);
using_thread_db = 0;
}

- target_beneath->to_create_inferior (exec_file, allargs, env);
+ (GET_TARGET_OPS_BELOW(thread_stratum,to_create_inferior)) (exec_file,
allargs, env);
}

static void
thread_db_post_startup_inferior (ptid_t ptid)
@@ -890,9 +899,9 @@ thread_db_mourn_inferior (void)
/* Forget about the child's process ID. We shouldn't need it
anymore. */
proc_handle.pid = 0;

- target_beneath->to_mourn_inferior ();
+ (GET_TARGET_OPS_BELOW(thread_stratum,to_mourn_inferior)) ();
}

static int
thread_db_thread_alive (ptid_t ptid)
@@ -920,11 +929,12 @@ thread_db_thread_alive (ptid_t ptid)

return 1;
}

- if (target_beneath->to_thread_alive)
- return target_beneath->to_thread_alive (ptid);
-
+ if (find_target_stratum(thread_stratum-1)->to_thread_alive)
+ {
+ return (GET_TARGET_OPS_AT(thread_stratum-1,to_thread_alive)) (ptid);
+ }
return 0;
}

static int
@@ -964,8 +974,10 @@ thread_db_find_new_threads (void)

static char *
thread_db_pid_to_str (ptid_t ptid)
{
+ char * pid_str;
+
if (is_thread (ptid))
{
static char buf[64];
td_thrhandle_t th;
@@ -973,14 +985,14 @@ thread_db_pid_to_str (ptid_t ptid)
td_err_e err;

err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (ptid), &th);
if (err != TD_OK)
- error ("Cannot find thread %ld: %s",
+ error ("Cannot find thread %ld: %s",
(long) GET_THREAD (ptid), thread_db_err_str (err));

err = td_thr_get_info_p (&th, &ti);
if (err != TD_OK)
- error ("Cannot get thread info for thread %ld: %s",
+ error ("Cannot get thread info for thread %ld: %s",
(long) GET_THREAD (ptid), thread_db_err_str (err));

if (ti.ti_state == TD_THR_ACTIVE && ti.ti_lid != 0)
{
@@ -995,12 +1007,15 @@ thread_db_pid_to_str (ptid_t ptid)

return buf;
}

- if (target_beneath->to_pid_to_str (ptid))
- return target_beneath->to_pid_to_str (ptid);
+ pid_str = (GET_TARGET_OPS_BELOW(thread_stratum,to_pid_to_str)) (ptid);
+ if ( pid_str != NULL )
+ {
+ return pid_str;
+ }

- return normal_pid_to_str (ptid);
+ return normal_pid_to_str(ptid);
}

static void
init_thread_db_ops (void)