static void target_info (char *, int);
-static void maybe_kill_then_attach (char *, int);
-
static void kill_or_be_killed (int);
static void default_terminal_info (char *, int);
static void debug_to_close (int);
-static void debug_to_attach (char *, int);
+static void debug_to_attach (struct target_ops *ops, char *, int);
-static void debug_to_detach (char *, int);
+static void debug_to_detach (struct target_ops *ops, char *, int);
static void debug_to_resume (ptid_t, int, enum target_signal);
static int debug_to_lookup_symbol (char *, CORE_ADDR *);
-static void debug_to_mourn_inferior (void);
+static void debug_to_mourn_inferior (struct target_ops *);
static int debug_to_can_run (void);
static struct cmd_list_element *targetlist = NULL;
-/* Nonzero if we are debugging an attached outside process
- rather than an inferior. */
-
-int attach_flag;
-
/* Nonzero if we should trust readonly sections from the
executable when reading memory. */
(*current_target.to_load) (arg, from_tty);
}
+void target_create_inferior (char *exec_file, char *args,
+ char **env, int from_tty)
+{
+ struct target_ops *t;
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_create_inferior != NULL)
+ {
+ t->to_create_inferior (t, exec_file, args, env, from_tty);
+ return;
+ }
+ }
+
+ internal_error (__FILE__, __LINE__,
+ "could not find a target to create inferior");
+}
+
+
static int
nomemory (CORE_ADDR memaddr, char *myaddr, int len, int write,
struct target_ops *t)
tcomplain ();
}
-static void
-maybe_kill_then_attach (char *args, int from_tty)
-{
- kill_or_be_killed (from_tty);
- target_attach (args, from_tty);
-}
+/* A default implementation for the to_get_ada_task_ptid target method.
-static void
-maybe_kill_then_create_inferior (char *exec, char *args, char **env,
- int from_tty)
+ This function builds the PTID by using both LWP and TID as part of
+ the PTID lwp and tid elements. The pid used is the pid of the
+ inferior_ptid. */
+
+ptid_t
+default_get_ada_task_ptid (long lwp, long tid)
{
- kill_or_be_killed (0);
- target_create_inferior (exec, args, env, from_tty);
+ return ptid_build (ptid_get_pid (inferior_ptid), lwp, tid);
}
/* Go through the target stack from top to bottom, copying over zero
INHERIT (to_shortname, t);
INHERIT (to_longname, t);
INHERIT (to_doc, t);
- INHERIT (to_open, t);
- INHERIT (to_close, t);
- INHERIT (to_attach, t);
+ /* Do not inherit to_open. */
+ /* Do not inherit to_close. */
+ /* Do not inherit to_attach. */
INHERIT (to_post_attach, t);
INHERIT (to_attach_no_wait, t);
- INHERIT (to_detach, t);
+ /* Do not inherit to_detach. */
/* Do not inherit to_disconnect. */
INHERIT (to_resume, t);
INHERIT (to_wait, t);
INHERIT (to_kill, t);
INHERIT (to_load, t);
INHERIT (to_lookup_symbol, t);
- INHERIT (to_create_inferior, t);
+ /* Do no inherit to_create_inferior. */
INHERIT (to_post_startup_inferior, t);
INHERIT (to_acknowledge_created_inferior, t);
INHERIT (to_insert_fork_catchpoint, t);
INHERIT (to_insert_exec_catchpoint, t);
INHERIT (to_remove_exec_catchpoint, t);
INHERIT (to_has_exited, t);
- INHERIT (to_mourn_inferior, t);
+ /* Do no inherit to_mourn_inferiour. */
INHERIT (to_can_run, t);
INHERIT (to_notice_signals, t);
INHERIT (to_thread_alive, t);
INHERIT (to_find_memory_regions, t);
INHERIT (to_make_corefile_notes, t);
INHERIT (to_get_thread_local_address, t);
+ INHERIT (to_can_execute_reverse, t);
/* Do not inherit to_read_description. */
+ INHERIT (to_get_ada_task_ptid, t);
/* Do not inherit to_search_memory. */
+ INHERIT (to_supports_multi_process, t);
INHERIT (to_magic, t);
/* Do not inherit to_memory_map. */
/* Do not inherit to_flash_erase. */
de_fault (to_close,
(void (*) (int))
target_ignore);
- de_fault (to_attach,
- maybe_kill_then_attach);
de_fault (to_post_attach,
(void (*) (int))
target_ignore);
- de_fault (to_detach,
- (void (*) (char *, int))
- target_ignore);
de_fault (to_resume,
(void (*) (ptid_t, int, enum target_signal))
noprocess);
de_fault (to_lookup_symbol,
(int (*) (char *, CORE_ADDR *))
nosymbol);
- de_fault (to_create_inferior,
- maybe_kill_then_create_inferior);
de_fault (to_post_startup_inferior,
(void (*) (ptid_t))
target_ignore);
de_fault (to_has_exited,
(int (*) (int, int, int *))
return_zero);
- de_fault (to_mourn_inferior,
- (void (*) (void))
- noprocess);
de_fault (to_can_run,
return_zero);
de_fault (to_notice_signals,
de_fault (to_pid_to_exec_file,
(char *(*) (int))
return_zero);
- de_fault (to_can_async_p,
- (int (*) (void))
- return_zero);
- de_fault (to_is_async_p,
- (int (*) (void))
- return_zero);
de_fault (to_async,
(void (*) (void (*) (enum inferior_event_type, void*), void*))
tcomplain);
(int (*) (int))
return_one);
current_target.to_read_description = NULL;
+ de_fault (to_get_ada_task_ptid,
+ (ptid_t (*) (long, long))
+ default_get_ada_task_ptid);
+ de_fault (to_supports_multi_process,
+ (int (*) (void))
+ return_zero);
#undef de_fault
/* Finally, position the target-stack beneath the squashed
struct target_ops **cur;
struct target_ops *tmp;
+ if (t->to_stratum == dummy_stratum)
+ internal_error (__FILE__, __LINE__,
+ "Attempt to unpush the dummy target");
+
/* Look for the specified target. Note that we assume that a target
can only occur once in the target stack. */
void
pop_target (void)
{
- target_close (¤t_target, 0); /* Let it clean up */
+ target_close (target_stack, 0); /* Let it clean up */
if (unpush_target (target_stack) == 1)
return;
{
while ((int) (current_target.to_stratum) > (int) above_stratum)
{
- target_close (¤t_target, quitting);
+ target_close (target_stack, quitting);
if (!unpush_target (target_stack))
{
fprintf_unfiltered (gdb_stderr,
"pop_all_targets couldn't find target %s\n",
- current_target.to_shortname);
+ target_stack->to_shortname);
internal_error (__FILE__, __LINE__,
_("failed internal consistency check"));
break;
volatile CORE_ADDR addr = 0;
if (target_get_thread_local_address_p ()
- && gdbarch_fetch_tls_load_module_address_p (current_gdbarch))
+ && gdbarch_fetch_tls_load_module_address_p (target_gdbarch))
{
ptid_t ptid = inferior_ptid;
volatile struct gdb_exception ex;
CORE_ADDR lm_addr;
/* Fetch the load module address for this objfile. */
- lm_addr = gdbarch_fetch_tls_load_module_address (current_gdbarch,
+ lm_addr = gdbarch_fetch_tls_load_module_address (target_gdbarch,
objfile);
/* If it's 0, throw the appropriate exception. */
if (lm_addr == 0)
/* Likewise for accesses to unmapped overlay sections. */
if (readbuf != NULL && overlay_debugging)
{
- asection *section = find_pc_overlay (memaddr);
+ struct obj_section *section = find_pc_overlay (memaddr);
if (pc_in_unmapped_range (memaddr, section))
return xfer_memory (memaddr, readbuf, len, 0, NULL, ops);
}
const unsigned char *myaddr = NULL;
fprintf_unfiltered (gdb_stdlog,
- "%s:target_xfer_partial (%d, %s, 0x%lx, 0x%lx, 0x%s, %s) = %s",
+ "%s:target_xfer_partial (%d, %s, 0x%lx, 0x%lx, %s, %s) = %s",
ops->to_shortname,
(int) object,
(annex ? annex : "(null)"),
(long) readbuf, (long) writebuf,
- paddr_nz (offset), paddr_d (len), paddr_d (retval));
+ core_addr_to_string_nz (offset),
+ plongest (len), plongest (retval));
if (readbuf)
myaddr = readbuf;
(gdb) attach 4712
Cannot access memory at address 0xdeadbeef
*/
- no_shared_libraries (NULL, from_tty);
- invalidate_target_mem_regions ();
+ /* In some OSs, the shared library list is the same/global/shared
+ across inferiors. If code is shared between processes, so are
+ memory regions and features. */
+ if (!gdbarch_has_global_solist (target_gdbarch))
+ {
+ no_shared_libraries (NULL, from_tty);
+
+ invalidate_target_mem_regions ();
- target_clear_description ();
+ target_clear_description ();
+ }
}
/* This is to be called by the open routine before it does
void
target_detach (char *args, int from_tty)
{
- /* If we're in breakpoints-always-inserted mode, have to
- remove them before detaching. */
- remove_breakpoints ();
+ struct target_ops* t;
+
+ if (gdbarch_has_global_solist (target_gdbarch))
+ /* Don't remove global breakpoints here. They're removed on
+ disconnection from the target. */
+ ;
+ else
+ /* If we're in breakpoints-always-inserted mode, have to remove
+ them before detaching. */
+ remove_breakpoints ();
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_detach != NULL)
+ {
+ t->to_detach (t, args, from_tty);
+ return;
+ }
+ }
- (current_target.to_detach) (args, from_tty);
+ internal_error (__FILE__, __LINE__, "could not find a target to detach");
}
void
{
struct target_ops *t;
- /* If we're in breakpoints-always-inserted mode, have to
- remove them before disconnecting. */
+ /* If we're in breakpoints-always-inserted mode or if breakpoints
+ are global across processes, we have to remove them before
+ disconnecting. */
remove_breakpoints ();
for (t = current_target.beneath; t != NULL; t = t->beneath)
"could not find a target to follow fork");
}
+void
+target_mourn_inferior (void)
+{
+ struct target_ops *t;
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_mourn_inferior != NULL)
+ {
+ t->to_mourn_inferior (t);
+ return;
+ }
+ }
+
+ internal_error (__FILE__, __LINE__,
+ "could not find a target to follow mourn inferiour");
+}
+
/* Look for a target which can describe architectural features, starting
from TARGET. If we find one, return its description. */
}
void
-find_default_attach (char *args, int from_tty)
+find_default_attach (struct target_ops *ops, char *args, int from_tty)
{
struct target_ops *t;
t = find_default_run_target ("attach");
- (t->to_attach) (args, from_tty);
+ (t->to_attach) (t, args, from_tty);
return;
}
void
-find_default_create_inferior (char *exec_file, char *allargs, char **env,
+find_default_create_inferior (struct target_ops *ops,
+ char *exec_file, char *allargs, char **env,
int from_tty)
{
struct target_ops *t;
t = find_default_run_target ("run");
- (t->to_create_inferior) (exec_file, allargs, env, from_tty);
+ (t->to_create_inferior) (t, exec_file, allargs, env, from_tty);
return;
}
return 0;
}
+int
+find_default_supports_non_stop (void)
+{
+ struct target_ops *t;
+
+ t = find_default_run_target (NULL);
+ if (t && t->to_supports_non_stop)
+ return (t->to_supports_non_stop) ();
+ return 0;
+}
+
+int
+target_supports_non_stop ()
+{
+ struct target_ops *t;
+ for (t = ¤t_target; t != NULL; t = t->beneath)
+ if (t->to_supports_non_stop)
+ return t->to_supports_non_stop ();
+
+ return 0;
+}
+
+
+char *
+target_get_osdata (const char *type)
+{
+ char *document;
+ struct target_ops *t;
+
+ if (target_can_run (¤t_target))
+ t = ¤t_target;
+ else
+ t = find_default_run_target ("get OS data");
+
+ if (!t)
+ return NULL;
+
+ document = target_read_stralloc (t,
+ TARGET_OBJECT_OSDATA,
+ type);
+ return document;
+}
+
static int
default_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
{
- return (len <= TYPE_LENGTH (builtin_type_void_data_ptr));
+ return (len <= gdbarch_ptr_bit (target_gdbarch) / TARGET_CHAR_BIT);
}
static int
void
generic_mourn_inferior (void)
{
- extern int show_breakpoint_hit_counts;
+ ptid_t ptid;
+ ptid = inferior_ptid;
inferior_ptid = null_ptid;
- attach_flag = 0;
+
+ if (!ptid_equal (ptid, null_ptid))
+ {
+ int pid = ptid_get_pid (ptid);
+ delete_inferior (pid);
+ }
+
breakpoint_init_inferior (inf_exited);
registers_changed ();
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 ();
-
if (deprecated_detach_hook)
deprecated_detach_hook ();
}
}
}
\f
-/* Returns zero to leave the inferior alone, one to interrupt it. */
-int (*target_activity_function) (void);
-int target_activity_fd;
-\f
/* Convert a normal process ID to a string. Returns the string in a
static buffer. */
dummy_target.to_longname = "None";
dummy_target.to_doc = "";
dummy_target.to_attach = find_default_attach;
+ dummy_target.to_detach =
+ (void (*)(struct target_ops *, char *, int))target_ignore;
dummy_target.to_create_inferior = find_default_create_inferior;
dummy_target.to_can_async_p = find_default_can_async_p;
dummy_target.to_is_async_p = find_default_is_async_p;
+ dummy_target.to_supports_non_stop = find_default_supports_non_stop;
dummy_target.to_pid_to_str = normal_pid_to_str;
dummy_target.to_stratum = dummy_stratum;
dummy_target.to_find_memory_regions = dummy_find_memory_regions;
targ->to_close (quitting);
}
+void
+target_attach (char *args, int from_tty)
+{
+ struct target_ops *t;
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_attach != NULL)
+ {
+ t->to_attach (t, args, from_tty);
+ return;
+ }
+ }
+
+ internal_error (__FILE__, __LINE__,
+ "could not find a target to attach");
+}
+
+
static void
-debug_to_attach (char *args, int from_tty)
+debug_to_attach (struct target_ops *ops, char *args, int from_tty)
{
- debug_target.to_attach (args, from_tty);
+ debug_target.to_attach (&debug_target, args, from_tty);
fprintf_unfiltered (gdb_stdlog, "target_attach (%s, %d)\n", args, from_tty);
}
}
static void
-debug_to_detach (char *args, int from_tty)
+debug_to_detach (struct target_ops *ops, char *args, int from_tty)
{
- debug_target.to_detach (args, from_tty);
+ debug_target.to_detach (&debug_target, args, from_tty);
fprintf_unfiltered (gdb_stdlog, "target_detach (%s, %d)\n", args, from_tty);
}
struct gdbarch *gdbarch = get_regcache_arch (regcache);
fprintf_unfiltered (gdb_stdlog, "%s ", func);
if (regno >= 0 && regno < gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch)
&& gdbarch_register_name (gdbarch, regno) != NULL
&& gdbarch_register_name (gdbarch, regno)[0] != '\0')
fprintf_unfiltered (gdb_stdlog, "(%s)",
gdbarch_register_name (gdbarch, regno));
else
fprintf_unfiltered (gdb_stdlog, "(%d)", regno);
- if (regno >= 0)
+ if (regno >= 0 && regno < gdbarch_num_regs (gdbarch))
{
int i, size = register_size (gdbarch, regno);
unsigned char buf[MAX_REGISTER_SIZE];
- regcache_cooked_read (regcache, regno, buf);
+ regcache_raw_collect (regcache, regno, buf);
fprintf_unfiltered (gdb_stdlog, " = ");
for (i = 0; i < size; i++)
{
if (size <= sizeof (LONGEST))
{
ULONGEST val = extract_unsigned_integer (buf, size);
- fprintf_unfiltered (gdb_stdlog, " 0x%s %s",
- paddr_nz (val), paddr_d (val));
+ fprintf_unfiltered (gdb_stdlog, " %s %s",
+ core_addr_to_string_nz (val), plongest (val));
}
}
fprintf_unfiltered (gdb_stdlog, "\n");
}
static void
-debug_to_create_inferior (char *exec_file, char *args, char **env,
+debug_to_create_inferior (struct target_ops *ops,
+ char *exec_file, char *args, char **env,
int from_tty)
{
- debug_target.to_create_inferior (exec_file, args, env, from_tty);
+ debug_target.to_create_inferior (ops, exec_file, args, env, from_tty);
fprintf_unfiltered (gdb_stdlog, "target_create_inferior (%s, %s, xxx, %d)\n",
exec_file, args, from_tty);
}
static void
-debug_to_mourn_inferior (void)
+debug_to_mourn_inferior (struct target_ops *ops)
{
- debug_target.to_mourn_inferior ();
+ debug_target.to_mourn_inferior (&debug_target);
fprintf_unfiltered (gdb_stdlog, "target_mourn_inferior ()\n");
}
}
}
+/* Controls if async mode is permitted. */
+int target_async_permitted = 0;
+
+/* The set command writes to this variable. If the inferior is
+ executing, linux_nat_async_permitted is *not* updated. */
+static int target_async_permitted_1 = 0;
+
+static void
+set_maintenance_target_async_permitted (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ if (target_has_execution)
+ {
+ target_async_permitted_1 = target_async_permitted;
+ error (_("Cannot change this setting while the inferior is running."));
+ }
+
+ target_async_permitted = target_async_permitted_1;
+}
+
+static void
+show_maintenance_target_async_permitted (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+ fprintf_filtered (file, _("\
+Controlling the inferior in asynchronous mode is %s.\n"), value);
+}
+
void
initialize_targets (void)
{
_("Print the name of each layer of the internal target stack."),
&maintenanceprintlist);
+ add_setshow_boolean_cmd ("target-async", no_class,
+ &target_async_permitted_1, _("\
+Set whether gdb controls the inferior in asynchronous mode."), _("\
+Show whether gdb controls the inferior in asynchronous mode."), _("\
+Tells gdb whether to control the inferior in asynchronous mode."),
+ set_maintenance_target_async_permitted,
+ show_maintenance_target_async_permitted,
+ &setlist,
+ &showlist);
+
target_dcache = dcache_init ();
}