tcomplain PARAMS ((void));
static int
-nomemory PARAMS ((CORE_ADDR, char *, int, int));
+nomemory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
static int
return_zero PARAMS ((void));
OPS_MAGIC,
};
-/* The target structure we are currently using to talk to a process
- or file or whatever "inferior" we have. */
+/* Top of target stack. */
-struct target_ops *current_target;
+struct target_stack_item *target_stack;
-/* The stack of target structures that have been pushed. */
+/* The target structure we are currently using to talk to a process
+ or file or whatever "inferior" we have. */
-struct target_ops **current_target_stack;
+struct target_ops current_target;
/* Command list for target. */
static struct cmd_list_element *targetlist = NULL;
+/* Nonzero if we are debugging an attached outside process
+ rather than an inferior. */
+
+int attach_flag;
+
/* The user just typed 'target' without the name of a target. */
/* ARGSUSED */
add_target (t)
struct target_ops *t;
{
- if (t->to_magic != OPS_MAGIC)
- {
- fprintf_unfiltered(gdb_stderr, "Magic number of %s target struct wrong\n",
- t->to_shortname);
- abort();
- }
-
if (!target_structs)
{
target_struct_allocsize = DEFAULT_ALLOCSIZE;
target_struct_allocsize * sizeof (*target_structs));
}
target_structs[target_struct_size++] = t;
- cleanup_target (t);
+/* cleanup_target (t);*/
if (targetlist == NULL)
add_prefix_cmd ("target", class_run, target_command,
/* ARGSUSED */
static int
-nomemory (memaddr, myaddr, len, write)
+nomemory (memaddr, myaddr, len, write, t)
CORE_ADDR memaddr;
char *myaddr;
int len;
int write;
+ struct target_ops *t;
{
errno = EIO; /* Can't read/write this location */
return 0; /* No bytes handled */
tcomplain ()
{
error ("You can't do that when your target is `%s'",
- current_target->to_shortname);
+ current_target.to_shortname);
}
void
printf_unfiltered("No saved terminal information.\n");
}
-#if 0
-/* With strata, this function is no longer needed. FIXME. */
-/* This is the default target_create_inferior function. It looks up
- the stack for some target that cares to create inferiors, then
- calls it -- or complains if not found. */
-
-static void
-upstack_create_inferior (exec, args, env)
- char *exec;
- char *args;
- char **env;
-{
- struct target_ops *t;
-
- for (t = current_target;
- t;
- t = t->to_next)
- {
- if (t->to_create_inferior != upstack_create_inferior)
- {
- t->to_create_inferior (exec, args, env);
- return;
- }
-
- }
- tcomplain();
-}
-#endif
-
/* This is the default target_create_inferior and target_attach function.
If the current target is executing, it asks whether to kill it off.
If this function returns without calling error(), it has killed off
struct target_ops *t;
{
- /* Check magic number. If wrong, it probably means someone changed
- the struct definition, but not all the places that initialize one. */
- if (t->to_magic != OPS_MAGIC)
- {
- fprintf_unfiltered(gdb_stderr, "Magic number of %s target struct wrong\n",
- t->to_shortname);
- abort();
- }
-
#define de_fault(field, value) \
if (!t->field) t->field = value
de_fault (to_mourn_inferior, (void (*)())noprocess);
de_fault (to_can_run, return_zero);
de_fault (to_notice_signals, (void (*)())ignore);
- de_fault (to_next, 0);
- de_fault (to_has_all_memory, 0);
- de_fault (to_has_memory, 0);
- de_fault (to_has_stack, 0);
- de_fault (to_has_registers, 0);
- de_fault (to_has_execution, 0);
#undef de_fault
}
+/* Go through the target stack from top to bottom, copying over zero entries in
+ current_target. In effect, we are doing class inheritance through the
+ pushed target vectors. */
+
+static void
+update_current_target ()
+{
+ struct target_stack_item *item;
+ struct target_ops *t;
+
+ /* First, reset current_target */
+ memset (¤t_target, 0, sizeof current_target);
+
+ for (item = target_stack; item; item = item->next)
+ {
+ t = item->target_ops;
+
+#define INHERIT(FIELD, TARGET) \
+ if (!current_target.FIELD) \
+ current_target.FIELD = TARGET->FIELD
+
+ INHERIT (to_shortname, t);
+ INHERIT (to_longname, t);
+ INHERIT (to_doc, t);
+ INHERIT (to_open, t);
+ INHERIT (to_close, t);
+ INHERIT (to_attach, t);
+ INHERIT (to_detach, t);
+ INHERIT (to_resume, t);
+ INHERIT (to_wait, t);
+ INHERIT (to_fetch_registers, t);
+ INHERIT (to_store_registers, t);
+ INHERIT (to_prepare_to_store, t);
+ INHERIT (to_xfer_memory, t);
+ INHERIT (to_files_info, t);
+ INHERIT (to_insert_breakpoint, t);
+ INHERIT (to_remove_breakpoint, t);
+ INHERIT (to_terminal_init, t);
+ INHERIT (to_terminal_inferior, t);
+ INHERIT (to_terminal_ours_for_output, t);
+ INHERIT (to_terminal_ours, t);
+ INHERIT (to_terminal_info, t);
+ INHERIT (to_kill, t);
+ INHERIT (to_load, t);
+ INHERIT (to_lookup_symbol, t);
+ INHERIT (to_create_inferior, t);
+ INHERIT (to_mourn_inferior, t);
+ INHERIT (to_can_run, t);
+ INHERIT (to_notice_signals, t);
+ INHERIT (to_stratum, t);
+ INHERIT (DONT_USE, t);
+ INHERIT (to_has_all_memory, t);
+ INHERIT (to_has_memory, t);
+ INHERIT (to_has_stack, t);
+ INHERIT (to_has_registers, t);
+ INHERIT (to_has_execution, t);
+ INHERIT (to_sections, t);
+ INHERIT (to_sections_end, t);
+ INHERIT (to_magic, t);
+
+#undef INHERIT
+ }
+}
+
/* Push a new target type into the stack of the existing target accessors,
possibly superseding some of the existing accessors.
push_target (t)
struct target_ops *t;
{
- struct target_ops *st, *prev;
+ struct target_stack_item *cur, *prev, *tmp;
+
+ /* Check magic number. If wrong, it probably means someone changed
+ the struct definition, but not all the places that initialize one. */
+ if (t->to_magic != OPS_MAGIC)
+ {
+ fprintf_unfiltered(gdb_stderr,
+ "Magic number of %s target struct wrong\n",
+ t->to_shortname);
+ abort();
+ }
+
+ /* Find the proper stratum to install this target in. */
+
+ for (prev = NULL, cur = target_stack; cur; prev = cur, cur = cur->next)
+ {
+ if ((int)(t->to_stratum) >= (int)(cur->target_ops->to_stratum))
+ break;
+ }
+
+ /* If there's already targets at this stratum, remove them. */
+
+ if (cur)
+ while (t->to_stratum == cur->target_ops->to_stratum)
+ {
+ /* There's already something on this stratum. Close it off. */
+ (cur->target_ops->to_close) (0);
+ if (prev)
+ prev->next = cur->next; /* Unchain old target_ops */
+ else
+ target_stack = cur->next; /* Unchain first on list */
+ tmp = cur->next;
+ free (cur);
+ cur = tmp;
+ }
+
+ /* We have removed all targets in our stratum, now add the new one. */
+
+ tmp = (struct target_stack_item *)
+ xmalloc (sizeof (struct target_stack_item));
+ tmp->next = cur;
+ tmp->target_ops = t;
- for (prev = 0, st = current_target;
- st;
- prev = st, st = st->to_next) {
- if ((int)(t->to_stratum) >= (int)(st->to_stratum))
- break;
- }
-
- while (t->to_stratum == st->to_stratum) {
- /* There's already something on this stratum. Close it off. */
- (st->to_close) (0);
- if (prev)
- prev->to_next = st->to_next; /* Unchain old target_ops */
- else
- current_target = st->to_next; /* Unchain first on list */
- st = st->to_next;
- }
-
- /* We have removed all targets in our stratum, now add ourself. */
- t->to_next = st;
if (prev)
- prev->to_next = t;
+ prev->next = tmp;
else
- current_target = t;
+ target_stack = tmp;
+
+ update_current_target ();
- cleanup_target (current_target);
+ cleanup_target (¤t_target); /* Fill in the gaps */
return prev != 0;
}
/* Remove a target_ops vector from the stack, wherever it may be.
- Return how many times it was removed (0 or 1 unless bug). */
+ Return how many times it was removed (0 or 1). */
int
unpush_target (t)
struct target_ops *t;
{
- struct target_ops *u, *v;
- int result = 0;
+ struct target_stack_item *cur, *prev;
- for (u = current_target, v = 0;
- u;
- v = u, u = u->to_next)
- if (u == t)
- {
- if (v == 0)
- pop_target(); /* unchain top copy */
- else {
- (t->to_close)(0); /* Let it clean up */
- v->to_next = t->to_next; /* unchain middle copy */
- }
- result++;
- }
- return result;
+ if (t->to_close)
+ t->to_close (0); /* Let it clean up */
+
+ /* Look for the specified target. Note that we assume that a target
+ can only occur once in the target stack. */
+
+ for (cur = target_stack, prev = NULL; cur; prev = cur, cur = cur->next)
+ if (cur->target_ops == t)
+ break;
+
+ if (!cur)
+ return 0; /* Didn't find target_ops, quit now */
+
+ /* Unchain the target */
+
+ if (!prev)
+ target_stack = cur->next;
+ else
+ prev->next = cur->next;
+
+ free (cur); /* Release the target_stack_item */
+
+ update_current_target ();
+ cleanup_target (¤t_target);
+
+ return 1;
}
void
pop_target ()
{
- (current_target->to_close)(0); /* Let it clean up */
- current_target = current_target->to_next;
-#if 0
- /* This will dump core if ever called--push_target expects current_target
- to be non-NULL. But I don't think it's needed; I don't see how the
- dummy_target could ever be removed from the stack. */
- if (!current_target) /* At bottom, push dummy. */
- push_target (&dummy_target);
-#endif
+ (current_target.to_close)(0); /* Let it clean up */
+ if (unpush_target (target_stack->target_ops) == 1)
+ return;
+
+ fprintf_unfiltered(gdb_stderr,
+ "pop_target couldn't find target %s\n",
+ current_target.to_shortname);
+ abort();
}
#undef MIN
int curlen;
int res;
struct target_ops *t;
+ struct target_stack_item *item;
/* to_xfer_memory is not guaranteed to set errno, even when it returns
0. */
errno = 0;
/* The quick case is that the top target does it all. */
- res = current_target->to_xfer_memory
- (memaddr, myaddr, len, write, current_target);
+ res = current_target.to_xfer_memory
+ (memaddr, myaddr, len, write, ¤t_target);
if (res == len)
return 0;
for (; len > 0;)
{
curlen = len; /* Want to do it all */
- for (t = current_target;
- t;
- t = t->to_has_all_memory? 0: t->to_next)
+ for (item = target_stack; item; item = item->next)
{
- res = t->to_xfer_memory(memaddr, myaddr, curlen, write, t);
- if (res > 0) break; /* Handled all or part of xfer */
- if (res == 0) continue; /* Handled none */
- curlen = -res; /* Could handle once we get past res bytes */
+ t = item->target_ops;
+ if (!t->to_has_memory)
+ continue;
+
+ res = t->to_xfer_memory (memaddr, myaddr, curlen, write, t);
+ if (res > 0)
+ break; /* Handled all or part of xfer */
+ if (t->to_has_all_memory)
+ break;
}
+
if (res <= 0)
{
/* If this address is for nonexistent memory,
int from_tty;
{
struct target_ops *t;
+ struct target_stack_item *item;
int has_all_mem = 0;
if (symfile_objfile != NULL)
return;
#endif
- for (t = current_target;
- t;
- t = t->to_next)
+ for (item = target_stack; item; item = item->next)
{
+ t = item->target_ops;
+
+ if (!t->to_has_memory)
+ continue;
+
if ((int)(t->to_stratum) <= (int)dummy_stratum)
continue;
if (has_all_mem)
- printf_unfiltered("\tWhile running this, gdb does not access memory from...\n");
+ printf_unfiltered("\tWhile running this, GDB does not access memory from...\n");
printf_unfiltered("%s:\n", t->to_longname);
(t->to_files_info)(t);
has_all_mem = t->to_has_all_memory;
#ifdef DO_DEFERRED_STORES
DO_DEFERRED_STORES;
#endif
- (current_target->to_detach) (args, from_tty);
+ (current_target.to_detach) (args, from_tty);
}
void
char *modname;
CORE_ADDR *t_reloc;
{
- if (STREQ(current_target->to_shortname, "rombug"))
+ if (STREQ(current_target.to_shortname, "rombug"))
{
- (current_target->to_lookup_symbol) (modname, t_reloc);
+ (current_target.to_lookup_symbol) (modname, t_reloc);
+ if (*t_reloc == 0)
+ error("Unable to link to %s and get relocation in rombug", modname);
}
else
*t_reloc = (CORE_ADDR)-1;
return(count == 1 ? runable : NULL);
}
\f
+/* The inferior process has died. Long live the inferior! */
+
+void
+generic_mourn_inferior ()
+{
+ extern int show_breakpoint_hit_counts;
+
+ inferior_pid = 0;
+ attach_flag = 0;
+ breakpoint_init_inferior ();
+ registers_changed ();
+
+#ifdef CLEAR_DEFERRED_STORES
+ /* Delete any pending stores to the inferior... */
+ CLEAR_DEFERRED_STORES;
+#endif
+
+ reopen_exec_file ();
+ reinit_frame_cache ();
+
+ /* It is confusing to the user for ignore counts to stick around
+ from previous runs of the inferior. So clear them. */
+ /* However, it is more confusing for the ignore counts to disappear when
+ using hit counts. So don't clear them if we're counting hits. */
+ if (!show_breakpoint_hit_counts)
+ breakpoint_clear_ignore_counts ();
+}
+\f
/* This table must match in order and size the signals in enum target_signal
in target.h. */
static struct {
}
}
+\f
+/* Returns zero to leave the inferior alone, one to interrupt it. */
+int (*target_activity_function) PARAMS ((void));
+int target_activity_fd;
\f
/* Convert a normal process ID to a string. Returns the string in a static
buffer. */
core-file, and process, if any), as well as the symbol file name.";
void
-_initialize_targets ()
+initialize_targets ()
{
- current_target = &dummy_target;
- cleanup_target (current_target);
+ push_target (&dummy_target);
add_info ("target", target_info, targ_desc);
add_info ("files", target_info, targ_desc);