/* Select target systems and architectures at runtime for GDB.
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Cygnus Support.
#include "gdbcore.h"
#include "exceptions.h"
#include "target-descriptions.h"
-#include "gdb_stdint.h"
+#include "gdbthread.h"
+#include "solib.h"
+#include "exec.h"
+#include "inline-frame.h"
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 int default_watchpoint_addr_within_range (struct target_ops *,
+ CORE_ADDR, CORE_ADDR, int);
+
static int default_region_ok_for_hw_watchpoint (CORE_ADDR, int);
static int nosymbol (char *, CORE_ADDR *);
void *readbuf, const void *writebuf,
ULONGEST offset, LONGEST len);
+static struct gdbarch *default_thread_architecture (struct target_ops *ops,
+ ptid_t ptid);
+
static void init_dummy_target (void);
static struct target_ops debug_target;
static void debug_to_open (char *, int);
-static void debug_to_close (int);
-
-static void debug_to_attach (char *, int);
-
-static void debug_to_detach (char *, int);
-
-static void debug_to_resume (ptid_t, int, enum target_signal);
-
-static ptid_t debug_to_wait (ptid_t, struct target_waitstatus *);
-
-static void debug_to_fetch_registers (struct regcache *, int);
-
-static void debug_to_store_registers (struct regcache *, int);
-
static void debug_to_prepare_to_store (struct regcache *);
static void debug_to_files_info (struct target_ops *);
-static int debug_to_insert_breakpoint (struct bp_target_info *);
+static int debug_to_insert_breakpoint (struct gdbarch *,
+ struct bp_target_info *);
-static int debug_to_remove_breakpoint (struct bp_target_info *);
+static int debug_to_remove_breakpoint (struct gdbarch *,
+ struct bp_target_info *);
static int debug_to_can_use_hw_breakpoint (int, int, int);
-static int debug_to_insert_hw_breakpoint (struct bp_target_info *);
+static int debug_to_insert_hw_breakpoint (struct gdbarch *,
+ struct bp_target_info *);
-static int debug_to_remove_hw_breakpoint (struct bp_target_info *);
+static int debug_to_remove_hw_breakpoint (struct gdbarch *,
+ struct bp_target_info *);
static int debug_to_insert_watchpoint (CORE_ADDR, int, int);
static int debug_to_stopped_data_address (struct target_ops *, CORE_ADDR *);
+static int debug_to_watchpoint_addr_within_range (struct target_ops *,
+ CORE_ADDR, CORE_ADDR, int);
+
static int debug_to_region_ok_for_hw_watchpoint (CORE_ADDR, int);
static void debug_to_terminal_init (void);
static void debug_to_terminal_info (char *, int);
-static void debug_to_kill (void);
-
static void debug_to_load (char *, int);
static int debug_to_lookup_symbol (char *, CORE_ADDR *);
-static void debug_to_mourn_inferior (void);
-
static int debug_to_can_run (void);
static void debug_to_notice_signals (ptid_t);
-static int debug_to_thread_alive (ptid_t);
-
-static void debug_to_stop (void);
+static void debug_to_stop (ptid_t);
/* NOTE: cagney/2004-09-29: Many targets reference this variable in
wierd and mysterious ways. Putting the variable here lets those
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. */
static void setup_target_debug (void);
-DCACHE *target_dcache;
+/* The option sets this. */
+static int stack_cache_enabled_p_1 = 1;
+/* And set_stack_cache_enabled_p updates this.
+ The reason for the separation is so that we don't flush the cache for
+ on->on transitions. */
+static int stack_cache_enabled_p = 1;
+
+/* This is called *after* the stack-cache has been set.
+ Flush the cache for off->on and on->off transitions.
+ There's no real need to flush the cache for on->off transitions,
+ except cleanliness. */
+
+static void
+set_stack_cache_enabled_p (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ if (stack_cache_enabled_p != stack_cache_enabled_p_1)
+ target_dcache_invalidate ();
+
+ stack_cache_enabled_p = stack_cache_enabled_p_1;
+}
+
+static void
+show_stack_cache_enabled_p (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("Cache use for stack accesses is %s.\n"), value);
+}
+
+/* Cache of memory operations, to speed up remote access. */
+static DCACHE *target_dcache;
+
+/* Invalidate the target dcache. */
+
+void
+target_dcache_invalidate (void)
+{
+ dcache_invalidate (target_dcache);
+}
/* The user just typed 'target' without the name of a target. */
gdb_stdout);
}
+/* Default target_has_* methods for process_stratum targets. */
+
+int
+default_child_has_all_memory (struct target_ops *ops)
+{
+ /* If no inferior selected, then we can't read memory here. */
+ if (ptid_equal (inferior_ptid, null_ptid))
+ return 0;
+
+ return 1;
+}
+
+int
+default_child_has_memory (struct target_ops *ops)
+{
+ /* If no inferior selected, then we can't read memory here. */
+ if (ptid_equal (inferior_ptid, null_ptid))
+ return 0;
+
+ return 1;
+}
+
+int
+default_child_has_stack (struct target_ops *ops)
+{
+ /* If no inferior selected, there's no stack. */
+ if (ptid_equal (inferior_ptid, null_ptid))
+ return 0;
+
+ return 1;
+}
+
+int
+default_child_has_registers (struct target_ops *ops)
+{
+ /* Can't read registers from no inferior. */
+ if (ptid_equal (inferior_ptid, null_ptid))
+ return 0;
+
+ return 1;
+}
+
+int
+default_child_has_execution (struct target_ops *ops)
+{
+ /* If there's no thread selected, then we can't make it run through
+ hoops. */
+ if (ptid_equal (inferior_ptid, null_ptid))
+ return 0;
+
+ return 1;
+}
+
+
+int
+target_has_all_memory_1 (void)
+{
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ if (t->to_has_all_memory (t))
+ return 1;
+
+ return 0;
+}
+
+int
+target_has_memory_1 (void)
+{
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ if (t->to_has_memory (t))
+ return 1;
+
+ return 0;
+}
+
+int
+target_has_stack_1 (void)
+{
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ if (t->to_has_stack (t))
+ return 1;
+
+ return 0;
+}
+
+int
+target_has_registers_1 (void)
+{
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ if (t->to_has_registers (t))
+ return 1;
+
+ return 0;
+}
+
+int
+target_has_execution_1 (void)
+{
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ if (t->to_has_execution (t))
+ return 1;
+
+ return 0;
+}
+
/* Add a possible target architecture to the list. */
void
if (t->to_xfer_partial == NULL)
t->to_xfer_partial = default_xfer_partial;
+ if (t->to_has_all_memory == NULL)
+ t->to_has_all_memory = (int (*) (struct target_ops *)) return_zero;
+
+ if (t->to_has_memory == NULL)
+ t->to_has_memory = (int (*) (struct target_ops *)) return_zero;
+
+ if (t->to_has_stack == NULL)
+ t->to_has_stack = (int (*) (struct target_ops *)) return_zero;
+
+ if (t->to_has_registers == NULL)
+ t->to_has_registers = (int (*) (struct target_ops *)) return_zero;
+
+ if (t->to_has_execution == NULL)
+ t->to_has_execution = (int (*) (struct target_ops *)) return_zero;
+
if (!target_structs)
{
target_struct_allocsize = DEFAULT_ALLOCSIZE;
}
void
+target_kill (void)
+{
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ if (t->to_kill != NULL)
+ {
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog, "target_kill ()\n");
+
+ t->to_kill (t);
+ return;
+ }
+
+ noprocess ();
+}
+
+void
target_load (char *arg, int from_tty)
{
- dcache_invalidate (target_dcache);
+ target_dcache_invalidate ();
(*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);
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog,
+ "target_create_inferior (%s, %s, xxx, %d)\n",
+ exec_file, args, from_tty);
+ return;
+ }
+ }
+
+ internal_error (__FILE__, __LINE__,
+ "could not find a target to create inferior");
+}
+
+void
+target_terminal_inferior (void)
+{
+ /* A background resume (``run&'') should leave GDB in control of the
+ terminal. Use target_can_async_p, not target_is_async_p, since at
+ this point the target is not async yet. However, if sync_execution
+ is not set, we know it will become async prior to resume. */
+ if (target_can_async_p () && !sync_execution)
+ return;
+
+ /* If GDB is resuming the inferior in the foreground, install
+ inferior's terminal modes. */
+ (*current_target.to_terminal_inferior) ();
+}
+
static int
nomemory (CORE_ADDR memaddr, char *myaddr, int len, int write,
struct target_ops *t)
{
printf_unfiltered (_("You are already running a program:\n"));
target_files_info ();
- if (query ("Kill it? "))
+ if (query (_("Kill it? ")))
{
target_kill ();
if (target_has_execution)
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. */
+
+static 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_detach, t);
+ INHERIT (to_attach_no_wait, t);
+ /* Do not inherit to_detach. */
/* Do not inherit to_disconnect. */
- INHERIT (to_resume, t);
- INHERIT (to_wait, t);
- INHERIT (to_fetch_registers, t);
- INHERIT (to_store_registers, t);
+ /* Do not inherit to_resume. */
+ /* Do not inherit to_wait. */
+ /* Do not inherit to_fetch_registers. */
+ /* Do not inherit to_store_registers. */
INHERIT (to_prepare_to_store, t);
INHERIT (deprecated_xfer_memory, t);
INHERIT (to_files_info, t);
INHERIT (to_insert_watchpoint, t);
INHERIT (to_remove_watchpoint, t);
INHERIT (to_stopped_data_address, t);
- INHERIT (to_stopped_by_watchpoint, t);
INHERIT (to_have_steppable_watchpoint, t);
INHERIT (to_have_continuable_watchpoint, t);
+ INHERIT (to_stopped_by_watchpoint, t);
+ INHERIT (to_watchpoint_addr_within_range, t);
INHERIT (to_region_ok_for_hw_watchpoint, t);
INHERIT (to_terminal_init, t);
INHERIT (to_terminal_inferior, t);
INHERIT (to_terminal_ours, t);
INHERIT (to_terminal_save_ours, t);
INHERIT (to_terminal_info, t);
- INHERIT (to_kill, t);
+ /* Do not inherit to_kill. */
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);
/* Do not inherit to_follow_fork. */
INHERIT (to_insert_exec_catchpoint, t);
INHERIT (to_remove_exec_catchpoint, t);
+ INHERIT (to_set_syscall_catchpoint, t);
INHERIT (to_has_exited, t);
- INHERIT (to_mourn_inferior, t);
+ /* Do not inherit to_mourn_inferiour. */
INHERIT (to_can_run, t);
INHERIT (to_notice_signals, t);
- INHERIT (to_thread_alive, t);
- INHERIT (to_find_new_threads, t);
- INHERIT (to_pid_to_str, t);
+ /* Do not inherit to_thread_alive. */
+ /* Do not inherit to_find_new_threads. */
+ /* Do not inherit to_pid_to_str. */
INHERIT (to_extra_thread_info, t);
INHERIT (to_stop, t);
/* Do not inherit to_xfer_partial. */
INHERIT (to_pid_to_exec_file, t);
INHERIT (to_log_command, t);
INHERIT (to_stratum, 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);
+ /* Do not inherit to_has_all_memory */
+ /* Do not inherit to_has_memory */
+ /* Do not inherit to_has_stack */
+ /* Do not inherit to_has_registers */
+ /* Do not inherit to_has_execution */
INHERIT (to_has_thread_control, t);
- INHERIT (to_sections, t);
- INHERIT (to_sections_end, t);
INHERIT (to_can_async_p, t);
INHERIT (to_is_async_p, t);
INHERIT (to_async, t);
- INHERIT (to_async_mask_value, t);
+ INHERIT (to_async_mask, t);
INHERIT (to_find_memory_regions, t);
INHERIT (to_make_corefile_notes, t);
- INHERIT (to_get_thread_local_address, t);
+ INHERIT (to_get_bookmark, t);
+ INHERIT (to_goto_bookmark, t);
+ /* Do not inherit to_get_thread_local_address. */
+ INHERIT (to_can_execute_reverse, t);
+ INHERIT (to_thread_architecture, 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_wait,
- (ptid_t (*) (ptid_t, struct target_waitstatus *))
- noprocess);
- de_fault (to_fetch_registers,
- (void (*) (struct regcache *, int))
- target_ignore);
- de_fault (to_store_registers,
- (void (*) (struct regcache *, int))
- noprocess);
de_fault (to_prepare_to_store,
(void (*) (struct regcache *))
noprocess);
(int (*) (int, int, int))
return_zero);
de_fault (to_insert_hw_breakpoint,
- (int (*) (struct bp_target_info *))
+ (int (*) (struct gdbarch *, struct bp_target_info *))
return_minus_one);
de_fault (to_remove_hw_breakpoint,
- (int (*) (struct bp_target_info *))
+ (int (*) (struct gdbarch *, struct bp_target_info *))
return_minus_one);
de_fault (to_insert_watchpoint,
(int (*) (CORE_ADDR, int, int))
de_fault (to_stopped_data_address,
(int (*) (struct target_ops *, CORE_ADDR *))
return_zero);
+ de_fault (to_watchpoint_addr_within_range,
+ default_watchpoint_addr_within_range);
de_fault (to_region_ok_for_hw_watchpoint,
default_region_ok_for_hw_watchpoint);
de_fault (to_terminal_init,
target_ignore);
de_fault (to_terminal_info,
default_terminal_info);
- de_fault (to_kill,
- (void (*) (void))
- noprocess);
de_fault (to_load,
(void (*) (char *, int))
tcomplain);
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_remove_exec_catchpoint,
(int (*) (int))
tcomplain);
+ de_fault (to_set_syscall_catchpoint,
+ (int (*) (int, int, int, int, int *))
+ tcomplain);
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,
(void (*) (ptid_t))
target_ignore);
- de_fault (to_thread_alive,
- (int (*) (ptid_t))
- return_zero);
- de_fault (to_find_new_threads,
- (void (*) (void))
- target_ignore);
de_fault (to_extra_thread_info,
(char *(*) (struct thread_info *))
return_zero);
de_fault (to_stop,
- (void (*) (void))
+ (void (*) (ptid_t))
target_ignore);
current_target.to_xfer_partial = current_xfer_partial;
de_fault (to_rcmd,
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);
+ de_fault (to_async_mask,
+ (int (*) (int))
+ return_one);
+ de_fault (to_thread_architecture,
+ default_thread_architecture);
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
setup_target_debug ();
}
-/* Mark OPS as a running target. This reverses the effect
- of target_mark_exited. */
-
-void
-target_mark_running (struct target_ops *ops)
-{
- struct target_ops *t;
-
- for (t = target_stack; t != NULL; t = t->beneath)
- if (t == ops)
- break;
- if (t == NULL)
- internal_error (__FILE__, __LINE__,
- "Attempted to mark unpushed target \"%s\" as running",
- ops->to_shortname);
-
- ops->to_has_execution = 1;
- ops->to_has_all_memory = 1;
- ops->to_has_memory = 1;
- ops->to_has_stack = 1;
- ops->to_has_registers = 1;
-
- update_current_target ();
-}
-
-/* Mark OPS as a non-running target. This reverses the effect
- of target_mark_running. */
-
-void
-target_mark_exited (struct target_ops *ops)
-{
- struct target_ops *t;
-
- for (t = target_stack; t != NULL; t = t->beneath)
- if (t == ops)
- break;
- if (t == NULL)
- internal_error (__FILE__, __LINE__,
- "Attempted to mark unpushed target \"%s\" as running",
- ops->to_shortname);
-
- ops->to_has_execution = 0;
- ops->to_has_all_memory = 0;
- ops->to_has_memory = 0;
- ops->to_has_stack = 0;
- ops->to_has_registers = 0;
-
- update_current_target ();
-}
-
/* Push a new target type into the stack of the existing target accessors,
possibly superseding some of the existing accessors.
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;
internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
}
+void
+pop_all_targets_above (enum strata above_stratum, int quitting)
+{
+ while ((int) (current_target.to_stratum) > (int) above_stratum)
+ {
+ target_close (target_stack, quitting);
+ if (!unpush_target (target_stack))
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "pop_all_targets couldn't find target %s\n",
+ target_stack->to_shortname);
+ internal_error (__FILE__, __LINE__,
+ _("failed internal consistency check"));
+ break;
+ }
+ }
+}
+
+void
+pop_all_targets (int quitting)
+{
+ pop_all_targets_above (dummy_stratum, quitting);
+}
+
/* Using the objfile specified in OBJFILE, find the address for the
current thread's thread-local storage with offset OFFSET. */
CORE_ADDR
target_translate_tls_address (struct objfile *objfile, CORE_ADDR offset)
{
volatile CORE_ADDR addr = 0;
+ struct target_ops *target;
+
+ for (target = current_target.beneath;
+ target != NULL;
+ target = target->beneath)
+ {
+ if (target->to_get_thread_local_address != NULL)
+ break;
+ }
- if (target_get_thread_local_address_p ()
- && gdbarch_fetch_tls_load_module_address_p (current_gdbarch))
+ if (target != NULL
+ && 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)
throw_error (TLS_LOAD_MODULE_NOT_FOUND_ERROR,
_("TLS load module not found"));
- addr = target_get_thread_local_address (ptid, lm_addr, offset);
+ addr = target->to_get_thread_local_address (target, ptid, lm_addr, offset);
}
/* If an error occurred, print TLS related messages here. Otherwise,
throw the error to some higher catcher. */
return nbytes_read;
}
+struct target_section_table *
+target_get_section_table (struct target_ops *target)
+{
+ struct target_ops *t;
+
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog, "target_get_section_table ()\n");
+
+ for (t = target; t != NULL; t = t->beneath)
+ if (t->to_get_section_table != NULL)
+ return (*t->to_get_section_table) (t);
+
+ return NULL;
+}
+
/* Find a section containing ADDR. */
-struct section_table *
+
+struct target_section *
target_section_by_addr (struct target_ops *target, CORE_ADDR addr)
{
- struct section_table *secp;
- for (secp = target->to_sections;
- secp < target->to_sections_end;
- secp++)
+ struct target_section_table *table = target_get_section_table (target);
+ struct target_section *secp;
+
+ if (table == NULL)
+ return NULL;
+
+ for (secp = table->sections; secp < table->sections_end; secp++)
{
if (addr >= secp->addr && addr < secp->endaddr)
return secp;
return NULL;
}
-/* Perform a partial memory transfer. The arguments and return
- value are just as for target_xfer_partial. */
+/* Perform a partial memory transfer.
+ For docs see target.h, to_xfer_partial. */
static LONGEST
-memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf,
- ULONGEST memaddr, LONGEST len)
+memory_xfer_partial (struct target_ops *ops, enum target_object object,
+ void *readbuf, const void *writebuf, ULONGEST memaddr,
+ LONGEST len)
{
LONGEST res;
int reg_len;
struct mem_region *region;
+ struct inferior *inf;
/* Zero length requests are ok and require no work. */
if (len == 0)
return 0;
- /* Try the executable file, if "trust-readonly-sections" is set. */
+ /* For accesses to unmapped overlay sections, read directly from
+ files. Must do this first, as MEMADDR may need adjustment. */
+ if (readbuf != NULL && overlay_debugging)
+ {
+ struct obj_section *section = find_pc_overlay (memaddr);
+ if (pc_in_unmapped_range (memaddr, section))
+ {
+ struct target_section_table *table
+ = target_get_section_table (ops);
+ const char *section_name = section->the_bfd_section->name;
+ memaddr = overlay_mapped_address (memaddr, section);
+ return section_table_xfer_memory_partial (readbuf, writebuf,
+ memaddr, len,
+ table->sections,
+ table->sections_end,
+ section_name);
+ }
+ }
+
+ /* Try the executable files, if "trust-readonly-sections" is set. */
if (readbuf != NULL && trust_readonly)
{
- struct section_table *secp;
+ struct target_section *secp;
+ struct target_section_table *table;
secp = target_section_by_addr (ops, memaddr);
if (secp != NULL
&& (bfd_get_section_flags (secp->bfd, secp->the_bfd_section)
& SEC_READONLY))
- return xfer_memory (memaddr, readbuf, len, 0, NULL, ops);
- }
-
- /* Likewise for accesses to unmapped overlay sections. */
- if (readbuf != NULL && overlay_debugging)
- {
- asection *section = find_pc_overlay (memaddr);
- if (pc_in_unmapped_range (memaddr, section))
- return xfer_memory (memaddr, readbuf, len, 0, NULL, ops);
+ {
+ table = target_get_section_table (ops);
+ return section_table_xfer_memory_partial (readbuf, writebuf,
+ memaddr, len,
+ table->sections,
+ table->sections_end,
+ NULL);
+ }
}
/* Try GDB's internal data cache. */
return -1;
}
- if (region->attrib.cache)
+ if (!ptid_equal (inferior_ptid, null_ptid))
+ inf = find_inferior_pid (ptid_get_pid (inferior_ptid));
+ else
+ inf = NULL;
+
+ if (inf != NULL
+ && (region->attrib.cache
+ || (stack_cache_enabled_p && object == TARGET_OBJECT_STACK_MEMORY)))
{
- /* FIXME drow/2006-08-09: This call discards OPS, so the raw
- memory request will start back at current_target. */
if (readbuf != NULL)
- res = dcache_xfer_memory (target_dcache, memaddr, readbuf,
+ res = dcache_xfer_memory (ops, target_dcache, memaddr, readbuf,
reg_len, 0);
else
/* FIXME drow/2006-08-09: If we're going to preserve const
correctness dcache_xfer_memory should take readbuf and
writebuf. */
- res = dcache_xfer_memory (target_dcache, memaddr,
+ res = dcache_xfer_memory (ops, target_dcache, memaddr,
(void *) writebuf,
reg_len, 1);
if (res <= 0)
/* We want to continue past core files to executables, but not
past a running target's memory. */
- if (ops->to_has_all_memory)
+ if (ops->to_has_all_memory (ops))
break;
ops = ops->beneath;
if (readbuf && !show_memory_breakpoints)
breakpoint_restore_shadows (readbuf, memaddr, reg_len);
+ /* Make sure the cache gets updated no matter what - if we are writing
+ to the stack. Even if this write is not tagged as such, we still need
+ to update the cache. */
+
+ if (res > 0
+ && inf != NULL
+ && writebuf != NULL
+ && !region->attrib.cache
+ && stack_cache_enabled_p
+ && object != TARGET_OBJECT_STACK_MEMORY)
+ {
+ dcache_update (target_dcache, memaddr, (void *) writebuf, res);
+ }
+
/* If we still haven't got anything, return the last error. We
give up. */
return res;
(void *) (uintptr_t) current);
}
+/* For docs see target.h, to_xfer_partial. */
+
static LONGEST
target_xfer_partial (struct target_ops *ops,
enum target_object object, const char *annex,
/* If this is a memory transfer, let the memory-specific code
have a look at it instead. Memory transfers are more
complicated. */
- if (object == TARGET_OBJECT_MEMORY)
- retval = memory_xfer_partial (ops, readbuf, writebuf, offset, len);
+ if (object == TARGET_OBJECT_MEMORY || object == TARGET_OBJECT_STACK_MEMORY)
+ retval = memory_xfer_partial (ops, object, readbuf,
+ writebuf, offset, len);
else
{
enum target_object raw_object = object;
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, %s, %s, %s, %s) = %s",
ops->to_shortname,
(int) object,
(annex ? annex : "(null)"),
- (long) readbuf, (long) writebuf,
- paddr_nz (offset), paddr_d (len), paddr_d (retval));
+ host_address_to_string (readbuf),
+ host_address_to_string (writebuf),
+ core_addr_to_string_nz (offset),
+ plongest (len), plongest (retval));
if (readbuf)
myaddr = readbuf;
fputs_unfiltered (", bytes =", gdb_stdlog);
for (i = 0; i < retval; i++)
{
- if ((((long) &(myaddr[i])) & 0xf) == 0)
+ if ((((intptr_t) &(myaddr[i])) & 0xf) == 0)
{
if (targetdebug < 2 && i > 0)
{
int
target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
{
- if (target_read (¤t_target, TARGET_OBJECT_MEMORY, NULL,
+ /* Dispatch to the topmost target, not the flattened current_target.
+ Memory accesses check target->to_has_(all_)memory, and the
+ flattened target doesn't inherit those. */
+ if (target_read (current_target.beneath, TARGET_OBJECT_MEMORY, NULL,
myaddr, memaddr, len) == len)
return 0;
else
return EIO;
}
+/* Like target_read_memory, but specify explicitly that this is a read from
+ the target's stack. This may trigger different cache behavior. */
+
+int
+target_read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
+{
+ /* Dispatch to the topmost target, not the flattened current_target.
+ Memory accesses check target->to_has_(all_)memory, and the
+ flattened target doesn't inherit those. */
+
+ if (target_read (current_target.beneath, TARGET_OBJECT_STACK_MEMORY, NULL,
+ myaddr, memaddr, len) == len)
+ return 0;
+ else
+ return EIO;
+}
+
+/* Write LEN bytes from MYADDR to target memory at address MEMADDR.
+ Returns either 0 for success or an errno value if any error occurs.
+ If an error occurs, no guarantee is made about how much data got written.
+ Callers that can deal with partial writes should call target_write. */
+
int
target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, int len)
{
- if (target_write (¤t_target, TARGET_OBJECT_MEMORY, NULL,
+ /* Dispatch to the topmost target, not the flattened current_target.
+ Memory accesses check target->to_has_(all_)memory, and the
+ flattened target doesn't inherit those. */
+ if (target_write (current_target.beneath, TARGET_OBJECT_MEMORY, NULL,
myaddr, memaddr, len) == len)
return 0;
else
{
if (targetdebug)
fprintf_unfiltered (gdb_stdlog, "target_flash_erase (%s, %s)\n",
- paddr (address), phex (length, 0));
+ hex_string (address), phex (length, 0));
t->to_flash_erase (t, address, length);
return;
}
tcomplain ();
}
-#ifndef target_stopped_data_address_p
-int
-target_stopped_data_address_p (struct target_ops *target)
-{
- if (target->to_stopped_data_address
- == (int (*) (struct target_ops *, CORE_ADDR *)) return_zero)
- return 0;
- if (target->to_stopped_data_address == debug_to_stopped_data_address
- && (debug_target.to_stopped_data_address
- == (int (*) (struct target_ops *, CORE_ADDR *)) return_zero))
- return 0;
- return 1;
-}
-#endif
-
static void
show_trust_readonly (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
return -1;
}
-/* Target vector read/write partial wrapper functions.
-
- NOTE: cagney/2003-10-21: I wonder if having "to_xfer_partial
- (inbuf, outbuf)", instead of separate read/write methods, make life
- easier. */
+/* Target vector read/write partial wrapper functions. */
static LONGEST
target_read_partial (struct target_ops *ops,
}
/* Wrappers to perform the full transfer. */
+
+/* For docs on target_read see target.h. */
+
LONGEST
target_read (struct target_ops *ops,
enum target_object object,
return len;
}
+LONGEST
+target_read_until_error (struct target_ops *ops,
+ enum target_object object,
+ const char *annex, gdb_byte *buf,
+ ULONGEST offset, LONGEST len)
+{
+ LONGEST xfered = 0;
+ while (xfered < len)
+ {
+ LONGEST xfer = target_read_partial (ops, object, annex,
+ (gdb_byte *) buf + xfered,
+ offset + xfered, len - xfered);
+ /* Call an observer, notifying them of the xfer progress? */
+ if (xfer == 0)
+ return xfered;
+ if (xfer < 0)
+ {
+ /* We've got an error. Try to read in smaller blocks. */
+ ULONGEST start = offset + xfered;
+ ULONGEST remaining = len - xfered;
+ ULONGEST half;
+
+ /* If an attempt was made to read a random memory address,
+ it's likely that the very first byte is not accessible.
+ Try reading the first byte, to avoid doing log N tries
+ below. */
+ xfer = target_read_partial (ops, object, annex,
+ (gdb_byte *) buf + xfered, start, 1);
+ if (xfer <= 0)
+ return xfered;
+ start += 1;
+ remaining -= 1;
+ half = remaining/2;
+
+ while (half > 0)
+ {
+ xfer = target_read_partial (ops, object, annex,
+ (gdb_byte *) buf + xfered,
+ start, half);
+ if (xfer == 0)
+ return xfered;
+ if (xfer < 0)
+ {
+ remaining = half;
+ }
+ else
+ {
+ /* We have successfully read the first half. So, the
+ error must be in the second half. Adjust start and
+ remaining to point at the second half. */
+ xfered += xfer;
+ start += xfer;
+ remaining -= xfer;
+ }
+ half = remaining/2;
+ }
+
+ return xfered;
+ }
+ xfered += xfer;
+ QUIT;
+ }
+ return len;
+}
+
/* An alternative to target_write with progress callbacks. */
LONGEST
return len;
}
+/* For docs on target_write see target.h. */
+
LONGEST
target_write (struct target_ops *ops,
enum target_object object,
get_target_memory (struct target_ops *ops, CORE_ADDR addr, gdb_byte *buf,
LONGEST len)
{
- if (target_read (ops, TARGET_OBJECT_MEMORY, NULL, buf, addr, len)
+ /* This method is used to read from an alternate, non-current
+ target. This read must bypass the overlay support (as symbols
+ don't match this target), and GDB's internal cache (wrong cache
+ for this target). */
+ if (target_read (ops, TARGET_OBJECT_RAW_MEMORY, NULL, buf, addr, len)
!= len)
memory_error (EIO, addr);
}
ULONGEST
get_target_memory_unsigned (struct target_ops *ops,
- CORE_ADDR addr, int len)
+ CORE_ADDR addr, int len, enum bfd_endian byte_order)
{
gdb_byte buf[sizeof (ULONGEST)];
gdb_assert (len <= sizeof (buf));
get_target_memory (ops, addr, buf, len);
- return extract_unsigned_integer (buf, len);
+ return extract_unsigned_integer (buf, len, byte_order);
}
static void
for (t = target_stack; t != NULL; t = t->beneath)
{
- if (!t->to_has_memory)
+ if (!(*t->to_has_memory) (t))
continue;
if ((int) (t->to_stratum) <= (int) dummy_stratum)
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;
+ has_all_mem = (*t->to_has_all_memory) (t);
}
}
void
target_pre_inferior (int from_tty)
{
- invalidate_target_mem_regions ();
+ /* Clear out solib state. Otherwise the solib state of the previous
+ inferior might have survived and is entirely wrong for the new
+ target. This has been observed on GNU/Linux using glibc 2.3. How
+ to reproduce:
+
+ bash$ ./foo&
+ [1] 4711
+ bash$ ./foo&
+ [1] 4712
+ bash$ gdb ./foo
+ [...]
+ (gdb) attach 4711
+ (gdb) detach
+ (gdb) attach 4712
+ Cannot access memory at address 0xdeadbeef
+ */
+
+ /* 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 ();
+ }
+}
+
+/* Callback for iterate_over_inferiors. Gets rid of the given
+ inferior. */
+
+static int
+dispose_inferior (struct inferior *inf, void *args)
+{
+ struct thread_info *thread;
- target_clear_description ();
+ thread = any_thread_of_process (inf->pid);
+ if (thread)
+ {
+ switch_to_thread (thread->ptid);
+
+ /* Core inferiors actually should be detached, not killed. */
+ if (target_has_execution)
+ target_kill ();
+ else
+ target_detach (NULL, 0);
+ }
+
+ return 0;
}
/* This is to be called by the open routine before it does
{
dont_repeat ();
- if (target_has_execution)
+ if (have_inferiors ())
{
if (!from_tty
- || query (_("A program is being debugged already. Kill it? ")))
- target_kill ();
+ || !have_live_inferiors ()
+ || query (_("A program is being debugged already. Kill it? ")))
+ iterate_over_inferiors (dispose_inferior, NULL);
else
error (_("Program not killed."));
}
/* Calling target_kill may remove the target from the stack. But if
it doesn't (which seems like a win for UDI), remove it now. */
-
- if (target_has_execution)
- pop_target ();
+ /* Leave the exec target, though. The user may be switching from a
+ live process to a core of the same program. */
+ pop_all_targets_above (file_stratum, 0);
target_pre_inferior (from_tty);
}
void
target_detach (char *args, int from_tty)
{
- (current_target.to_detach) (args, from_tty);
+ struct target_ops* t;
+
+ if (gdbarch_has_global_breakpoints (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_pid (PIDGET (inferior_ptid));
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_detach != NULL)
+ {
+ t->to_detach (t, args, from_tty);
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog, "target_detach (%s, %d)\n",
+ args, from_tty);
+ return;
+ }
+ }
+
+ internal_error (__FILE__, __LINE__, "could not find a target to detach");
}
void
{
struct target_ops *t;
+ /* 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)
if (t->to_disconnect != NULL)
{
tcomplain ();
}
-int
-target_async_mask (int mask)
+ptid_t
+target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
{
- int saved_async_masked_status = target_async_mask_value;
- target_async_mask_value = mask;
- return saved_async_masked_status;
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_wait != NULL)
+ {
+ ptid_t retval = (*t->to_wait) (t, ptid, status, options);
+
+ if (targetdebug)
+ {
+ char *status_string;
+
+ status_string = target_waitstatus_to_string (status);
+ fprintf_unfiltered (gdb_stdlog,
+ "target_wait (%d, status) = %d, %s\n",
+ PIDGET (ptid), PIDGET (retval),
+ status_string);
+ xfree (status_string);
+ }
+
+ return retval;
+ }
+ }
+
+ noprocess ();
+}
+
+char *
+target_pid_to_str (ptid_t ptid)
+{
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_pid_to_str != NULL)
+ return (*t->to_pid_to_str) (t, ptid);
+ }
+
+ return normal_pid_to_str (ptid);
}
+void
+target_resume (ptid_t ptid, int step, enum target_signal signal)
+{
+ struct target_ops *t;
+
+ target_dcache_invalidate ();
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_resume != NULL)
+ {
+ t->to_resume (t, ptid, step, signal);
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog, "target_resume (%d, %s, %s)\n",
+ PIDGET (ptid),
+ step ? "step" : "continue",
+ target_signal_to_name (signal));
+
+ set_executing (ptid, 1);
+ set_running (ptid, 1);
+ clear_inline_frame_state (ptid);
+ return;
+ }
+ }
+
+ noprocess ();
+}
/* Look through the list of possible targets for a target that can
follow forks. */
"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);
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog, "target_mourn_inferior ()\n");
+
+ /* We no longer need to keep handles on any of the object files.
+ Make sure to release them to avoid unnecessarily locking any
+ of them while we're not actually debugging. */
+ bfd_cache_close_all ();
+
+ 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. */
-const struct target_desc *
-target_read_description (struct target_ops *target)
+const struct target_desc *
+target_read_description (struct target_ops *target)
+{
+ struct target_ops *t;
+
+ for (t = target; t != NULL; t = t->beneath)
+ if (t->to_read_description != NULL)
+ {
+ const struct target_desc *tdesc;
+
+ tdesc = t->to_read_description (t);
+ if (tdesc)
+ return tdesc;
+ }
+
+ return NULL;
+}
+
+/* The default implementation of to_search_memory.
+ This implements a basic search of memory, reading target memory and
+ performing the search here (as opposed to performing the search in on the
+ target side with, for example, gdbserver). */
+
+int
+simple_search_memory (struct target_ops *ops,
+ CORE_ADDR start_addr, ULONGEST search_space_len,
+ const gdb_byte *pattern, ULONGEST pattern_len,
+ CORE_ADDR *found_addrp)
+{
+ /* NOTE: also defined in find.c testcase. */
+#define SEARCH_CHUNK_SIZE 16000
+ const unsigned chunk_size = SEARCH_CHUNK_SIZE;
+ /* Buffer to hold memory contents for searching. */
+ gdb_byte *search_buf;
+ unsigned search_buf_size;
+ struct cleanup *old_cleanups;
+
+ search_buf_size = chunk_size + pattern_len - 1;
+
+ /* No point in trying to allocate a buffer larger than the search space. */
+ if (search_space_len < search_buf_size)
+ search_buf_size = search_space_len;
+
+ search_buf = malloc (search_buf_size);
+ if (search_buf == NULL)
+ error (_("Unable to allocate memory to perform the search."));
+ old_cleanups = make_cleanup (free_current_contents, &search_buf);
+
+ /* Prime the search buffer. */
+
+ if (target_read (ops, TARGET_OBJECT_MEMORY, NULL,
+ search_buf, start_addr, search_buf_size) != search_buf_size)
+ {
+ warning (_("Unable to access target memory at %s, halting search."),
+ hex_string (start_addr));
+ do_cleanups (old_cleanups);
+ return -1;
+ }
+
+ /* Perform the search.
+
+ The loop is kept simple by allocating [N + pattern-length - 1] bytes.
+ When we've scanned N bytes we copy the trailing bytes to the start and
+ read in another N bytes. */
+
+ while (search_space_len >= pattern_len)
+ {
+ gdb_byte *found_ptr;
+ unsigned nr_search_bytes = min (search_space_len, search_buf_size);
+
+ found_ptr = memmem (search_buf, nr_search_bytes,
+ pattern, pattern_len);
+
+ if (found_ptr != NULL)
+ {
+ CORE_ADDR found_addr = start_addr + (found_ptr - search_buf);
+ *found_addrp = found_addr;
+ do_cleanups (old_cleanups);
+ return 1;
+ }
+
+ /* Not found in this chunk, skip to next chunk. */
+
+ /* Don't let search_space_len wrap here, it's unsigned. */
+ if (search_space_len >= chunk_size)
+ search_space_len -= chunk_size;
+ else
+ search_space_len = 0;
+
+ if (search_space_len >= pattern_len)
+ {
+ unsigned keep_len = search_buf_size - chunk_size;
+ CORE_ADDR read_addr = start_addr + chunk_size + keep_len;
+ int nr_to_read;
+
+ /* Copy the trailing part of the previous iteration to the front
+ of the buffer for the next iteration. */
+ gdb_assert (keep_len == pattern_len - 1);
+ memcpy (search_buf, search_buf + chunk_size, keep_len);
+
+ nr_to_read = min (search_space_len - keep_len, chunk_size);
+
+ if (target_read (ops, TARGET_OBJECT_MEMORY, NULL,
+ search_buf + keep_len, read_addr,
+ nr_to_read) != nr_to_read)
+ {
+ warning (_("Unable to access target memory at %s, halting search."),
+ hex_string (read_addr));
+ do_cleanups (old_cleanups);
+ return -1;
+ }
+
+ start_addr += chunk_size;
+ }
+ }
+
+ /* Not found. */
+
+ do_cleanups (old_cleanups);
+ return 0;
+}
+
+/* Search SEARCH_SPACE_LEN bytes beginning at START_ADDR for the
+ sequence of bytes in PATTERN with length PATTERN_LEN.
+
+ The result is 1 if found, 0 if not found, and -1 if there was an error
+ requiring halting of the search (e.g. memory read error).
+ If the pattern is found the address is recorded in FOUND_ADDRP. */
+
+int
+target_search_memory (CORE_ADDR start_addr, ULONGEST search_space_len,
+ const gdb_byte *pattern, ULONGEST pattern_len,
+ CORE_ADDR *found_addrp)
{
struct target_ops *t;
+ int found;
- for (t = target; t != NULL; t = t->beneath)
- if (t->to_read_description != NULL)
- {
- const struct target_desc *tdesc;
+ /* We don't use INHERIT to set current_target.to_search_memory,
+ so we have to scan the target stack and handle targetdebug
+ ourselves. */
- tdesc = t->to_read_description (t);
- if (tdesc)
- return tdesc;
- }
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog, "target_search_memory (%s, ...)\n",
+ hex_string (start_addr));
- return NULL;
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ if (t->to_search_memory != NULL)
+ break;
+
+ if (t != NULL)
+ {
+ found = t->to_search_memory (t, start_addr, search_space_len,
+ pattern, pattern_len, found_addrp);
+ }
+ else
+ {
+ /* If a special version of to_search_memory isn't available, use the
+ simple version. */
+ found = simple_search_memory (current_target.beneath,
+ start_addr, search_space_len,
+ pattern, pattern_len, found_addrp);
+ }
+
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog, " = %d\n", found);
+
+ return found;
}
/* Look through the currently pushed targets. If none of them will
/* Do not worry about thread_stratum targets that can not
create inferiors. Assume they will be pushed again if
necessary, and continue to the process_stratum. */
- if (t->to_stratum == thread_stratum)
+ if (t->to_stratum == thread_stratum
+ || t->to_stratum == arch_stratum)
continue;
error (_("\
execute a run or attach command without any other data. This is
used to locate the default process stratum.
- Result is always valid (error() is called for errors). */
+ If DO_MESG is not NULL, the result is always valid (error() is
+ called for errors); else, return NULL on error. */
static struct target_ops *
find_default_run_target (char *do_mesg)
}
if (count != 1)
- error (_("Don't know how to %s. Try \"help target\"."), do_mesg);
+ {
+ if (do_mesg)
+ error (_("Don't know how to %s. Try \"help target\"."), do_mesg);
+ else
+ return NULL;
+ }
return runable;
}
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;
}
static int
-default_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
+find_default_can_async_p (void)
{
- return (len <= TYPE_LENGTH (builtin_type_void_data_ptr));
+ struct target_ops *t;
+
+ /* This may be called before the target is pushed on the stack;
+ look for the default process stratum. If there's none, gdb isn't
+ configured with a native debugger, and target remote isn't
+ connected yet. */
+ t = find_default_run_target (NULL);
+ if (t && t->to_can_async_p)
+ return (t->to_can_async_p) ();
+ return 0;
}
static int
-return_zero (void)
+find_default_is_async_p (void)
{
+ struct target_ops *t;
+
+ /* This may be called before the target is pushed on the stack;
+ look for the default process stratum. If there's none, gdb isn't
+ configured with a native debugger, and target remote isn't
+ connected yet. */
+ t = find_default_run_target (NULL);
+ if (t && t->to_is_async_p)
+ return (t->to_is_async_p) ();
return 0;
}
static int
-return_one (void)
+find_default_supports_non_stop (void)
{
- return 1;
+ 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;
}
-static int
-return_minus_one (void)
+int
+target_supports_non_stop (void)
{
- return -1;
+ 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;
}
-/*
- * Resize the to_sections pointer. Also make sure that anyone that
- * was holding on to an old value of it gets updated.
- * Returns the old size.
- */
-int
-target_resize_to_sections (struct target_ops *target, int num_added)
+char *
+target_get_osdata (const char *type)
{
- struct target_ops **t;
- struct section_table *old_value;
- int old_count;
-
- old_value = target->to_sections;
+ char *document;
+ struct target_ops *t;
- if (target->to_sections)
- {
- old_count = target->to_sections_end - target->to_sections;
- target->to_sections = (struct section_table *)
- xrealloc ((char *) target->to_sections,
- (sizeof (struct section_table)) * (num_added + old_count));
- }
+ /* If we're already connected to something that can get us OS
+ related data, use it. Otherwise, try using the native
+ target. */
+ if (current_target.to_stratum >= process_stratum)
+ t = current_target.beneath;
else
- {
- old_count = 0;
- target->to_sections = (struct section_table *)
- xmalloc ((sizeof (struct section_table)) * num_added);
- }
- target->to_sections_end = target->to_sections + (num_added + old_count);
+ t = find_default_run_target ("get OS data");
+
+ if (!t)
+ return NULL;
+
+ return target_read_stralloc (t, TARGET_OBJECT_OSDATA, type);
+}
+
+/* Determine the current address space of thread PTID. */
- /* Check to see if anyone else was pointing to this structure.
- If old_value was null, then no one was. */
+struct address_space *
+target_thread_address_space (ptid_t ptid)
+{
+ struct address_space *aspace;
+ struct inferior *inf;
+ struct target_ops *t;
- if (old_value)
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
{
- for (t = target_structs; t < target_structs + target_struct_size;
- ++t)
- {
- if ((*t)->to_sections == old_value)
- {
- (*t)->to_sections = target->to_sections;
- (*t)->to_sections_end = target->to_sections_end;
- }
- }
- /* There is a flattened view of the target stack in current_target,
- so its to_sections pointer might also need updating. */
- if (current_target.to_sections == old_value)
+ if (t->to_thread_address_space != NULL)
{
- current_target.to_sections = target->to_sections;
- current_target.to_sections_end = target->to_sections_end;
+ aspace = t->to_thread_address_space (t, ptid);
+ gdb_assert (aspace);
+
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog,
+ "target_thread_address_space (%s) = %d\n",
+ target_pid_to_str (ptid),
+ address_space_num (aspace));
+ return aspace;
}
}
- return old_count;
+ /* Fall-back to the "main" address space of the inferior. */
+ inf = find_inferior_pid (ptid_get_pid (ptid));
+
+ if (inf == NULL || inf->aspace == NULL)
+ internal_error (__FILE__, __LINE__, "\
+Can't determine the current address space of thread %s\n",
+ target_pid_to_str (ptid));
+ return inf->aspace;
}
-/* Remove all target sections taken from ABFD.
+static int
+default_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
+{
+ return (len <= gdbarch_ptr_bit (target_gdbarch) / TARGET_CHAR_BIT);
+}
- Scan the current target stack for targets whose section tables
- refer to sections from BFD, and remove those sections. We use this
- when we notice that the inferior has unloaded a shared object, for
- example. */
-void
-remove_target_sections (bfd *abfd)
+static int
+default_watchpoint_addr_within_range (struct target_ops *target,
+ CORE_ADDR addr,
+ CORE_ADDR start, int length)
{
- struct target_ops **t;
+ return addr >= start && addr < start + length;
+}
- for (t = target_structs; t < target_structs + target_struct_size; t++)
- {
- struct section_table *src, *dest;
-
- dest = (*t)->to_sections;
- for (src = (*t)->to_sections; src < (*t)->to_sections_end; src++)
- if (src->bfd != abfd)
- {
- /* Keep this section. */
- if (dest < src) *dest = *src;
- dest++;
- }
-
- /* If we've dropped any sections, resize the section table. */
- if (dest < src)
- target_resize_to_sections (*t, dest - src);
- }
+static struct gdbarch *
+default_thread_architecture (struct target_ops *ops, ptid_t ptid)
+{
+ return target_gdbarch;
}
+static int
+return_zero (void)
+{
+ return 0;
+}
+static int
+return_one (void)
+{
+ return 1;
+}
+static int
+return_minus_one (void)
+{
+ return -1;
+}
/* Find a single runnable target in the stack and return it. If for
some reason there is more than one, return NULL. */
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);
+ exit_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. */
return buf;
}
-/* Error-catcher for target_find_memory_regions */
-static int dummy_find_memory_regions (int (*ignore1) (), void *ignore2)
+static char *
+dummy_pid_to_str (struct target_ops *ops, ptid_t ptid)
+{
+ return normal_pid_to_str (ptid);
+}
+
+/* Error-catcher for target_find_memory_regions. */
+static int
+dummy_find_memory_regions (int (*ignore1) (), void *ignore2)
{
- error (_("No target."));
+ error (_("Command not implemented for this target."));
return 0;
}
-/* Error-catcher for target_make_corefile_notes */
-static char * dummy_make_corefile_notes (bfd *ignore1, int *ignore2)
+/* Error-catcher for target_make_corefile_notes. */
+static char *
+dummy_make_corefile_notes (bfd *ignore1, int *ignore2)
+{
+ error (_("Command not implemented for this target."));
+ return NULL;
+}
+
+/* Error-catcher for target_get_bookmark. */
+static gdb_byte *
+dummy_get_bookmark (char *ignore1, int ignore2)
{
- error (_("No target."));
+ tcomplain ();
return NULL;
}
+/* Error-catcher for target_goto_bookmark. */
+static void
+dummy_goto_bookmark (gdb_byte *ignore, int from_tty)
+{
+ tcomplain ();
+}
+
/* Set up the handful of non-empty slots needed by the dummy target
vector. */
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_pid_to_str = normal_pid_to_str;
+ 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 = dummy_pid_to_str;
dummy_target.to_stratum = dummy_stratum;
dummy_target.to_find_memory_regions = dummy_find_memory_regions;
dummy_target.to_make_corefile_notes = dummy_make_corefile_notes;
+ dummy_target.to_get_bookmark = dummy_get_bookmark;
+ dummy_target.to_goto_bookmark = dummy_goto_bookmark;
dummy_target.to_xfer_partial = default_xfer_partial;
+ dummy_target.to_has_all_memory = (int (*) (struct target_ops *)) return_zero;
+ dummy_target.to_has_memory = (int (*) (struct target_ops *)) return_zero;
+ dummy_target.to_has_stack = (int (*) (struct target_ops *)) return_zero;
+ dummy_target.to_has_registers = (int (*) (struct target_ops *)) return_zero;
+ dummy_target.to_has_execution = (int (*) (struct target_ops *)) return_zero;
dummy_target.to_magic = OPS_MAGIC;
}
\f
fprintf_unfiltered (gdb_stdlog, "target_open (%s, %d)\n", args, from_tty);
}
-static void
-debug_to_close (int quitting)
-{
- target_close (&debug_target, quitting);
- fprintf_unfiltered (gdb_stdlog, "target_close (%d)\n", quitting);
-}
-
void
target_close (struct target_ops *targ, int quitting)
{
targ->to_xclose (targ, quitting);
else if (targ->to_close != NULL)
targ->to_close (quitting);
+
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog, "target_close (%d)\n", quitting);
}
-static void
-debug_to_attach (char *args, int from_tty)
+void
+target_attach (char *args, int from_tty)
{
- debug_target.to_attach (args, 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);
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog, "target_attach (%s, %d)\n",
+ args, from_tty);
+ return;
+ }
+ }
- fprintf_unfiltered (gdb_stdlog, "target_attach (%s, %d)\n", args, from_tty);
+ internal_error (__FILE__, __LINE__,
+ "could not find a target to attach");
}
-
-static void
-debug_to_post_attach (int pid)
+int
+target_thread_alive (ptid_t ptid)
{
- debug_target.to_post_attach (pid);
+ struct target_ops *t;
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_thread_alive != NULL)
+ {
+ int retval;
- fprintf_unfiltered (gdb_stdlog, "target_post_attach (%d)\n", pid);
+ retval = t->to_thread_alive (t, ptid);
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog, "target_thread_alive (%d) = %d\n",
+ PIDGET (ptid), retval);
+
+ return retval;
+ }
+ }
+
+ return 0;
}
-static void
-debug_to_detach (char *args, int from_tty)
+void
+target_find_new_threads (void)
{
- debug_target.to_detach (args, from_tty);
+ struct target_ops *t;
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_find_new_threads != NULL)
+ {
+ t->to_find_new_threads (t);
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog, "target_find_new_threads ()\n");
- fprintf_unfiltered (gdb_stdlog, "target_detach (%s, %d)\n", args, from_tty);
+ return;
+ }
+ }
}
static void
-debug_to_resume (ptid_t ptid, int step, enum target_signal siggnal)
+debug_to_post_attach (int pid)
{
- debug_target.to_resume (ptid, step, siggnal);
+ debug_target.to_post_attach (pid);
- fprintf_unfiltered (gdb_stdlog, "target_resume (%d, %s, %s)\n", PIDGET (ptid),
- step ? "step" : "continue",
- target_signal_to_name (siggnal));
+ fprintf_unfiltered (gdb_stdlog, "target_post_attach (%d)\n", pid);
}
-static ptid_t
-debug_to_wait (ptid_t ptid, struct target_waitstatus *status)
-{
- ptid_t retval;
+/* Return a pretty printed form of target_waitstatus.
+ Space for the result is malloc'd, caller must free. */
- retval = debug_target.to_wait (ptid, status);
+char *
+target_waitstatus_to_string (const struct target_waitstatus *ws)
+{
+ const char *kind_str = "status->kind = ";
- fprintf_unfiltered (gdb_stdlog,
- "target_wait (%d, status) = %d, ", PIDGET (ptid),
- PIDGET (retval));
- fprintf_unfiltered (gdb_stdlog, "status->kind = ");
- switch (status->kind)
+ switch (ws->kind)
{
case TARGET_WAITKIND_EXITED:
- fprintf_unfiltered (gdb_stdlog, "exited, status = %d\n",
- status->value.integer);
- break;
+ return xstrprintf ("%sexited, status = %d",
+ kind_str, ws->value.integer);
case TARGET_WAITKIND_STOPPED:
- fprintf_unfiltered (gdb_stdlog, "stopped, signal = %s\n",
- target_signal_to_name (status->value.sig));
- break;
+ return xstrprintf ("%sstopped, signal = %s",
+ kind_str, target_signal_to_name (ws->value.sig));
case TARGET_WAITKIND_SIGNALLED:
- fprintf_unfiltered (gdb_stdlog, "signalled, signal = %s\n",
- target_signal_to_name (status->value.sig));
- break;
+ return xstrprintf ("%ssignalled, signal = %s",
+ kind_str, target_signal_to_name (ws->value.sig));
case TARGET_WAITKIND_LOADED:
- fprintf_unfiltered (gdb_stdlog, "loaded\n");
- break;
+ return xstrprintf ("%sloaded", kind_str);
case TARGET_WAITKIND_FORKED:
- fprintf_unfiltered (gdb_stdlog, "forked\n");
- break;
+ return xstrprintf ("%sforked", kind_str);
case TARGET_WAITKIND_VFORKED:
- fprintf_unfiltered (gdb_stdlog, "vforked\n");
- break;
+ return xstrprintf ("%svforked", kind_str);
case TARGET_WAITKIND_EXECD:
- fprintf_unfiltered (gdb_stdlog, "execd\n");
- break;
+ return xstrprintf ("%sexecd", kind_str);
+ case TARGET_WAITKIND_SYSCALL_ENTRY:
+ return xstrprintf ("%sentered syscall", kind_str);
+ case TARGET_WAITKIND_SYSCALL_RETURN:
+ return xstrprintf ("%sexited syscall", kind_str);
case TARGET_WAITKIND_SPURIOUS:
- fprintf_unfiltered (gdb_stdlog, "spurious\n");
- break;
+ return xstrprintf ("%sspurious", kind_str);
+ case TARGET_WAITKIND_IGNORE:
+ return xstrprintf ("%signore", kind_str);
+ case TARGET_WAITKIND_NO_HISTORY:
+ return xstrprintf ("%sno-history", kind_str);
default:
- fprintf_unfiltered (gdb_stdlog, "unknown???\n");
- break;
+ return xstrprintf ("%sunknown???", kind_str);
}
-
- return retval;
}
static void
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))
{
+ enum bfd_endian byte_order = gdbarch_byte_order (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));
+ ULONGEST val = extract_unsigned_integer (buf, size, byte_order);
+ fprintf_unfiltered (gdb_stdlog, " %s %s",
+ core_addr_to_string_nz (val), plongest (val));
}
}
fprintf_unfiltered (gdb_stdlog, "\n");
}
-static void
-debug_to_fetch_registers (struct regcache *regcache, int regno)
+void
+target_fetch_registers (struct regcache *regcache, int regno)
{
- debug_target.to_fetch_registers (regcache, regno);
- debug_print_register ("target_fetch_registers", regcache, regno);
+ struct target_ops *t;
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_fetch_registers != NULL)
+ {
+ t->to_fetch_registers (t, regcache, regno);
+ if (targetdebug)
+ debug_print_register ("target_fetch_registers", regcache, regno);
+ return;
+ }
+ }
}
-static void
-debug_to_store_registers (struct regcache *regcache, int regno)
+void
+target_store_registers (struct regcache *regcache, int regno)
{
- debug_target.to_store_registers (regcache, regno);
- debug_print_register ("target_store_registers", regcache, regno);
- fprintf_unfiltered (gdb_stdlog, "\n");
+
+ struct target_ops *t;
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_store_registers != NULL)
+ {
+ t->to_store_registers (t, regcache, regno);
+ if (targetdebug)
+ {
+ debug_print_register ("target_store_registers", regcache, regno);
+ }
+ return;
+ }
+ }
+
+ noprocess ();
}
static void
attrib, target);
fprintf_unfiltered (gdb_stdlog,
- "target_xfer_memory (0x%x, xxx, %d, %s, xxx) = %d",
- (unsigned int) memaddr, /* possable truncate long long */
- len, write ? "write" : "read", retval);
+ "target_xfer_memory (%s, xxx, %d, %s, xxx) = %d",
+ paddress (target_gdbarch, memaddr), len,
+ write ? "write" : "read", retval);
if (retval > 0)
{
fputs_unfiltered (", bytes =", gdb_stdlog);
for (i = 0; i < retval; i++)
{
- if ((((long) &(myaddr[i])) & 0xf) == 0)
+ if ((((intptr_t) &(myaddr[i])) & 0xf) == 0)
{
if (targetdebug < 2 && i > 0)
{
}
static int
-debug_to_insert_breakpoint (struct bp_target_info *bp_tgt)
+debug_to_insert_breakpoint (struct gdbarch *gdbarch,
+ struct bp_target_info *bp_tgt)
{
int retval;
- retval = debug_target.to_insert_breakpoint (bp_tgt);
+ retval = debug_target.to_insert_breakpoint (gdbarch, bp_tgt);
fprintf_unfiltered (gdb_stdlog,
"target_insert_breakpoint (0x%lx, xxx) = %ld\n",
}
static int
-debug_to_remove_breakpoint (struct bp_target_info *bp_tgt)
+debug_to_remove_breakpoint (struct gdbarch *gdbarch,
+ struct bp_target_info *bp_tgt)
{
int retval;
- retval = debug_target.to_remove_breakpoint (bp_tgt);
+ retval = debug_target.to_remove_breakpoint (gdbarch, bp_tgt);
fprintf_unfiltered (gdb_stdlog,
"target_remove_breakpoint (0x%lx, xxx) = %ld\n",
retval = debug_target.to_region_ok_for_hw_watchpoint (addr, len);
fprintf_unfiltered (gdb_stdlog,
- "TARGET_REGION_OK_FOR_HW_WATCHPOINT (%ld, %ld) = 0x%lx\n",
+ "target_region_ok_for_hw_watchpoint (%ld, %ld) = 0x%lx\n",
(unsigned long) addr,
(unsigned long) len,
(unsigned long) retval);
retval = debug_target.to_stopped_by_watchpoint ();
fprintf_unfiltered (gdb_stdlog,
- "STOPPED_BY_WATCHPOINT () = %ld\n",
+ "target_stopped_by_watchpoint () = %ld\n",
(unsigned long) retval);
return retval;
}
}
static int
-debug_to_insert_hw_breakpoint (struct bp_target_info *bp_tgt)
+debug_to_watchpoint_addr_within_range (struct target_ops *target,
+ CORE_ADDR addr,
+ CORE_ADDR start, int length)
+{
+ int retval;
+
+ retval = debug_target.to_watchpoint_addr_within_range (target, addr,
+ start, length);
+
+ fprintf_filtered (gdb_stdlog,
+ "target_watchpoint_addr_within_range (0x%lx, 0x%lx, %d) = %d\n",
+ (unsigned long) addr, (unsigned long) start, length,
+ retval);
+ return retval;
+}
+
+static int
+debug_to_insert_hw_breakpoint (struct gdbarch *gdbarch,
+ struct bp_target_info *bp_tgt)
{
int retval;
- retval = debug_target.to_insert_hw_breakpoint (bp_tgt);
+ retval = debug_target.to_insert_hw_breakpoint (gdbarch, bp_tgt);
fprintf_unfiltered (gdb_stdlog,
"target_insert_hw_breakpoint (0x%lx, xxx) = %ld\n",
}
static int
-debug_to_remove_hw_breakpoint (struct bp_target_info *bp_tgt)
+debug_to_remove_hw_breakpoint (struct gdbarch *gdbarch,
+ struct bp_target_info *bp_tgt)
{
int retval;
- retval = debug_target.to_remove_hw_breakpoint (bp_tgt);
+ retval = debug_target.to_remove_hw_breakpoint (gdbarch, bp_tgt);
fprintf_unfiltered (gdb_stdlog,
"target_remove_hw_breakpoint (0x%lx, xxx) = %ld\n",
}
static void
-debug_to_kill (void)
-{
- debug_target.to_kill ();
-
- fprintf_unfiltered (gdb_stdlog, "target_kill ()\n");
-}
-
-static void
debug_to_load (char *args, int from_tty)
{
debug_target.to_load (args, from_tty);
}
static void
-debug_to_create_inferior (char *exec_file, char *args, char **env,
- int from_tty)
-{
- debug_target.to_create_inferior (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_post_startup_inferior (ptid_t ptid)
{
debug_target.to_post_startup_inferior (ptid);
return has_exited;
}
-static void
-debug_to_mourn_inferior (void)
-{
- debug_target.to_mourn_inferior ();
-
- fprintf_unfiltered (gdb_stdlog, "target_mourn_inferior ()\n");
-}
-
static int
debug_to_can_run (void)
{
PIDGET (ptid));
}
-static int
-debug_to_thread_alive (ptid_t ptid)
+static struct gdbarch *
+debug_to_thread_architecture (struct target_ops *ops, ptid_t ptid)
{
- int retval;
+ struct gdbarch *retval;
- retval = debug_target.to_thread_alive (ptid);
-
- fprintf_unfiltered (gdb_stdlog, "target_thread_alive (%d) = %d\n",
- PIDGET (ptid), retval);
+ retval = debug_target.to_thread_architecture (ops, ptid);
+ fprintf_unfiltered (gdb_stdlog, "target_thread_architecture (%s) = %s [%s]\n",
+ target_pid_to_str (ptid), host_address_to_string (retval),
+ gdbarch_bfd_arch_info (retval)->printable_name);
return retval;
}
static void
-debug_to_find_new_threads (void)
-{
- debug_target.to_find_new_threads ();
-
- fputs_unfiltered ("target_find_new_threads ()\n", gdb_stdlog);
-}
-
-static void
-debug_to_stop (void)
+debug_to_stop (ptid_t ptid)
{
- debug_target.to_stop ();
+ debug_target.to_stop (ptid);
- fprintf_unfiltered (gdb_stdlog, "target_stop ()\n");
+ fprintf_unfiltered (gdb_stdlog, "target_stop (%s)\n",
+ target_pid_to_str (ptid));
}
static void
memcpy (&debug_target, ¤t_target, sizeof debug_target);
current_target.to_open = debug_to_open;
- current_target.to_close = debug_to_close;
- current_target.to_attach = debug_to_attach;
current_target.to_post_attach = debug_to_post_attach;
- current_target.to_detach = debug_to_detach;
- current_target.to_resume = debug_to_resume;
- current_target.to_wait = debug_to_wait;
- current_target.to_fetch_registers = debug_to_fetch_registers;
- current_target.to_store_registers = debug_to_store_registers;
current_target.to_prepare_to_store = debug_to_prepare_to_store;
current_target.deprecated_xfer_memory = deprecated_debug_xfer_memory;
current_target.to_files_info = debug_to_files_info;
current_target.to_remove_watchpoint = debug_to_remove_watchpoint;
current_target.to_stopped_by_watchpoint = debug_to_stopped_by_watchpoint;
current_target.to_stopped_data_address = debug_to_stopped_data_address;
+ current_target.to_watchpoint_addr_within_range = debug_to_watchpoint_addr_within_range;
current_target.to_region_ok_for_hw_watchpoint = debug_to_region_ok_for_hw_watchpoint;
current_target.to_terminal_init = debug_to_terminal_init;
current_target.to_terminal_inferior = debug_to_terminal_inferior;
current_target.to_terminal_ours = debug_to_terminal_ours;
current_target.to_terminal_save_ours = debug_to_terminal_save_ours;
current_target.to_terminal_info = debug_to_terminal_info;
- current_target.to_kill = debug_to_kill;
current_target.to_load = debug_to_load;
current_target.to_lookup_symbol = debug_to_lookup_symbol;
- current_target.to_create_inferior = debug_to_create_inferior;
current_target.to_post_startup_inferior = debug_to_post_startup_inferior;
current_target.to_acknowledge_created_inferior = debug_to_acknowledge_created_inferior;
current_target.to_insert_fork_catchpoint = debug_to_insert_fork_catchpoint;
current_target.to_insert_exec_catchpoint = debug_to_insert_exec_catchpoint;
current_target.to_remove_exec_catchpoint = debug_to_remove_exec_catchpoint;
current_target.to_has_exited = debug_to_has_exited;
- current_target.to_mourn_inferior = debug_to_mourn_inferior;
current_target.to_can_run = debug_to_can_run;
current_target.to_notice_signals = debug_to_notice_signals;
- current_target.to_thread_alive = debug_to_thread_alive;
- current_target.to_find_new_threads = debug_to_find_new_threads;
current_target.to_stop = debug_to_stop;
current_target.to_rcmd = debug_to_rcmd;
current_target.to_pid_to_exec_file = debug_to_pid_to_exec_file;
+ current_target.to_thread_architecture = debug_to_thread_architecture;
}
\f
}
}
+/* 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 (have_live_inferiors ())
+ {
+ 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);
+
+ add_setshow_boolean_cmd ("stack-cache", class_support,
+ &stack_cache_enabled_p_1, _("\
+Set cache use for stack access."), _("\
+Show cache use for stack access."), _("\
+When on, use the data cache for all stack access, regardless of any\n\
+configured memory regions. This improves remote performance significantly.\n\
+By default, caching for stack access is on."),
+ set_stack_cache_enabled_p,
+ show_stack_cache_enabled_p,
+ &setlist, &showlist);
+
target_dcache = dcache_init ();
}