X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Ftarget.c;h=ab5f2b9f36d35f9568026975268bf6aacfb1db9a;hb=f4943d8253e8c9c539fd72d23e94a65f84c92d1a;hp=0432dfd06d0c31fd135ec72e479106dd7a5df0be;hpb=46ee7e8d84bb33c3c6c5dc8673ee2ca5457462b0;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/target.c b/gdb/target.c index 0432dfd06d..ab5f2b9f36 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -20,22 +20,19 @@ along with this program. If not, see . */ #include "defs.h" -#include -#include #include "target.h" #include "target-dcache.h" #include "gdbcmd.h" #include "symtab.h" #include "inferior.h" +#include "infrun.h" #include "bfd.h" #include "symfile.h" #include "objfiles.h" #include "dcache.h" #include #include "regcache.h" -#include "gdb_assert.h" #include "gdbcore.h" -#include "exceptions.h" #include "target-descriptions.h" #include "gdbthread.h" #include "solib.h" @@ -44,9 +41,13 @@ #include "tracepoint.h" #include "gdb/fileio.h" #include "agent.h" +#include "auxv.h" +#include "target-debug.h" static void target_info (char *, int); +static void generic_tls_error (void) ATTRIBUTE_NORETURN; + static void default_terminal_info (struct target_ops *, const char *, int); static int default_watchpoint_addr_within_range (struct target_ops *, @@ -55,25 +56,40 @@ static int default_watchpoint_addr_within_range (struct target_ops *, static int default_region_ok_for_hw_watchpoint (struct target_ops *, CORE_ADDR, int); -static void default_rcmd (struct target_ops *, char *, struct ui_file *); +static void default_rcmd (struct target_ops *, const char *, struct ui_file *); static ptid_t default_get_ada_task_ptid (struct target_ops *self, long lwp, long tid); -static void tcomplain (void) ATTRIBUTE_NORETURN; +static int default_follow_fork (struct target_ops *self, int follow_child, + int detach_fork); + +static void default_mourn_inferior (struct target_ops *self); + +static int default_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); -static int nomemory (CORE_ADDR, char *, int, int, struct target_ops *); +static int default_verify_memory (struct target_ops *self, + const gdb_byte *data, + CORE_ADDR memaddr, ULONGEST size); -static int return_zero (void); +static struct address_space *default_thread_address_space + (struct target_ops *self, ptid_t ptid); -void target_ignore (void); +static void tcomplain (void) ATTRIBUTE_NORETURN; + +static int return_zero (struct target_ops *); + +static int return_zero_has_execution (struct target_ops *, ptid_t); static void target_command (char *, int); static struct target_ops *find_default_run_target (char *); -static target_xfer_partial_ftype default_xfer_partial; - static struct gdbarch *default_thread_architecture (struct target_ops *ops, ptid_t ptid); @@ -84,86 +100,26 @@ static int dummy_find_memory_regions (struct target_ops *self, static char *dummy_make_corefile_notes (struct target_ops *self, bfd *ignore1, int *ignore2); -static int find_default_can_async_p (struct target_ops *ignore); - -static int find_default_is_async_p (struct target_ops *ignore); +static char *default_pid_to_str (struct target_ops *ops, ptid_t ptid); static enum exec_direction_kind default_execution_direction (struct target_ops *self); -#include "target-delegates.c" - -static void init_dummy_target (void); +static CORE_ADDR default_target_decr_pc_after_break (struct target_ops *ops, + struct gdbarch *gdbarch); static struct target_ops debug_target; -static void debug_to_open (char *, int); - -static void debug_to_prepare_to_store (struct target_ops *self, - struct regcache *); - -static void debug_to_files_info (struct target_ops *); - -static int debug_to_insert_breakpoint (struct target_ops *, struct gdbarch *, - struct bp_target_info *); - -static int debug_to_remove_breakpoint (struct target_ops *, struct gdbarch *, - struct bp_target_info *); - -static int debug_to_can_use_hw_breakpoint (struct target_ops *self, - int, int, int); - -static int debug_to_insert_hw_breakpoint (struct target_ops *self, - struct gdbarch *, - struct bp_target_info *); - -static int debug_to_remove_hw_breakpoint (struct target_ops *self, - struct gdbarch *, - struct bp_target_info *); - -static int debug_to_insert_watchpoint (struct target_ops *self, - CORE_ADDR, int, int, - struct expression *); - -static int debug_to_remove_watchpoint (struct target_ops *self, - CORE_ADDR, int, int, - struct expression *); - -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 (struct target_ops *self, - CORE_ADDR, int); - -static int debug_to_can_accel_watchpoint_condition (struct target_ops *self, - CORE_ADDR, int, int, - struct expression *); - -static void debug_to_terminal_init (struct target_ops *self); - -static void debug_to_terminal_inferior (struct target_ops *self); - -static void debug_to_terminal_ours_for_output (struct target_ops *self); - -static void debug_to_terminal_save_ours (struct target_ops *self); - -static void debug_to_terminal_ours (struct target_ops *self); - -static void debug_to_load (struct target_ops *self, char *, int); +#include "target-delegates.c" -static int debug_to_can_run (struct target_ops *self); +static void init_dummy_target (void); -static void debug_to_stop (struct target_ops *self, ptid_t); +static void update_current_target (void); -/* Pointer to array of target architecture structures; the size of the - array; the current index into the array; the allocated size of the - array. */ -struct target_ops **target_structs; -unsigned target_struct_size; -unsigned target_struct_allocsize; -#define DEFAULT_ALLOCSIZE 10 +/* Vector of existing target structures. */ +typedef struct target_ops *target_ops_p; +DEF_VEC_P (target_ops_p); +static VEC (target_ops_p) *target_structs; /* The initial current target, so that there is always a semi-valid current target. */ @@ -212,6 +168,13 @@ int may_stop = 1; /* Non-zero if we want to see trace of target level stuff. */ static unsigned int targetdebug = 0; + +static void +set_targetdebug (char *args, int from_tty, struct cmd_list_element *c) +{ + update_current_target (); +} + static void show_targetdebug (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) @@ -357,27 +320,49 @@ void complete_target_initialization (struct target_ops *t) { /* Provide default values for all "must have" methods. */ - 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; + t->to_has_all_memory = return_zero; if (t->to_has_memory == NULL) - t->to_has_memory = (int (*) (struct target_ops *)) return_zero; + t->to_has_memory = return_zero; if (t->to_has_stack == NULL) - t->to_has_stack = (int (*) (struct target_ops *)) return_zero; + t->to_has_stack = return_zero; if (t->to_has_registers == NULL) - t->to_has_registers = (int (*) (struct target_ops *)) return_zero; + t->to_has_registers = return_zero; if (t->to_has_execution == NULL) - t->to_has_execution = (int (*) (struct target_ops *, ptid_t)) return_zero; + t->to_has_execution = return_zero_has_execution; + + /* These methods can be called on an unpushed target and so require + a default implementation if the target might plausibly be the + default run target. */ + gdb_assert (t->to_can_run == NULL || (t->to_can_async_p != NULL + && t->to_supports_non_stop != NULL)); install_delegators (t); } +/* This is used to implement the various target commands. */ + +static void +open_target (char *args, int from_tty, struct cmd_list_element *command) +{ + struct target_ops *ops = get_cmd_context (command); + + if (targetdebug) + fprintf_unfiltered (gdb_stdlog, "-> %s->to_open (...)\n", + ops->to_shortname); + + ops->to_open (args, from_tty); + + if (targetdebug) + fprintf_unfiltered (gdb_stdlog, "<- %s->to_open (%s, %d)\n", + ops->to_shortname, args, from_tty); +} + /* Add possible target architecture T to the list and add a new command 'target T->to_shortname'. Set COMPLETER as the command's completer if not NULL. */ @@ -390,20 +375,7 @@ add_target_with_completer (struct target_ops *t, complete_target_initialization (t); - if (!target_structs) - { - target_struct_allocsize = DEFAULT_ALLOCSIZE; - target_structs = (struct target_ops **) xmalloc - (target_struct_allocsize * sizeof (*target_structs)); - } - if (target_struct_size >= target_struct_allocsize) - { - target_struct_allocsize *= 2; - target_structs = (struct target_ops **) - xrealloc ((char *) target_structs, - target_struct_allocsize * sizeof (*target_structs)); - } - target_structs[target_struct_size++] = t; + VEC_safe_push (target_ops_p, target_structs, t); if (targetlist == NULL) add_prefix_cmd ("target", class_run, target_command, _("\ @@ -413,8 +385,9 @@ Remaining arguments are interpreted by the target protocol. For more\n\ information on the arguments for a particular protocol, type\n\ `help target ' followed by the protocol name."), &targetlist, "target ", 0, &cmdlist); - c = add_cmd (t->to_shortname, no_class, t->to_open, t->to_doc, - &targetlist); + c = add_cmd (t->to_shortname, no_class, NULL, t->to_doc, &targetlist); + set_cmd_sfunc (c, open_target); + set_cmd_context (c, t); if (completer != NULL) set_cmd_completer (c, completer); } @@ -437,66 +410,65 @@ add_deprecated_target_alias (struct target_ops *t, char *alias) /* If we use add_alias_cmd, here, we do not get the deprecated warning, see PR cli/15104. */ - c = add_cmd (alias, no_class, t->to_open, t->to_doc, &targetlist); + c = add_cmd (alias, no_class, NULL, t->to_doc, &targetlist); + set_cmd_sfunc (c, open_target); + set_cmd_context (c, t); alt = xstrprintf ("target %s", t->to_shortname); deprecate_cmd (c, alt); } /* Stub functions */ -void -target_ignore (void) -{ -} - 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 (); + current_target.to_kill (¤t_target); } void -target_load (char *arg, int from_tty) +target_load (const char *arg, int from_tty) { target_dcache_invalidate (); (*current_target.to_load) (¤t_target, arg, from_tty); } +/* Possible terminal states. */ + +enum terminal_state + { + /* The inferior's terminal settings are in effect. */ + terminal_is_inferior = 0, + + /* Some of our terminal settings are in effect, enough to get + proper output. */ + terminal_is_ours_for_output = 1, + + /* Our terminal settings are in effect, for output and input. */ + terminal_is_ours = 2 + }; + +static enum terminal_state terminal_state; + +/* See target.h. */ + void -target_create_inferior (char *exec_file, char *args, - char **env, int from_tty) +target_terminal_init (void) { - struct target_ops *t; + (*current_target.to_terminal_init) (¤t_target); - 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; - } - } + terminal_state = terminal_is_ours; +} - internal_error (__FILE__, __LINE__, - _("could not find a target to create inferior")); +/* See target.h. */ + +int +target_terminal_is_inferior (void) +{ + return (terminal_state == terminal_is_inferior); } +/* See target.h. */ + void target_terminal_inferior (void) { @@ -507,17 +479,53 @@ target_terminal_inferior (void) if (target_can_async_p () && !sync_execution) return; + if (terminal_state == terminal_is_inferior) + return; + /* If GDB is resuming the inferior in the foreground, install inferior's terminal modes. */ (*current_target.to_terminal_inferior) (¤t_target); + terminal_state = terminal_is_inferior; } -static int -nomemory (CORE_ADDR memaddr, char *myaddr, int len, int write, - struct target_ops *t) +/* See target.h. */ + +void +target_terminal_ours (void) +{ + if (terminal_state == terminal_is_ours) + return; + + (*current_target.to_terminal_ours) (¤t_target); + terminal_state = terminal_is_ours; +} + +/* See target.h. */ + +void +target_terminal_ours_for_output (void) +{ + if (terminal_state != terminal_is_inferior) + return; + (*current_target.to_terminal_ours_for_output) (¤t_target); + terminal_state = terminal_is_ours_for_output; +} + +/* See target.h. */ + +int +target_supports_terminal_ours (void) { - errno = EIO; /* Can't read/write this location. */ - return 0; /* No bytes handled. */ + struct target_ops *t; + + for (t = current_target.beneath; t != NULL; t = t->beneath) + { + if (t->to_terminal_ours != delegate_terminal_ours + && t->to_terminal_ours != tdefault_terminal_ours) + return 1; + } + + return 0; } static void @@ -586,169 +594,25 @@ update_current_target (void) /* Install the delegators. */ install_delegators (¤t_target); + current_target.to_stratum = target_stack->to_stratum; + #define INHERIT(FIELD, TARGET) \ if (!current_target.FIELD) \ current_target.FIELD = (TARGET)->FIELD + /* Do not add any new INHERITs here. Instead, use the delegation + mechanism provided by make-target-delegates. */ for (t = target_stack; t; t = t->beneath) { INHERIT (to_shortname, t); INHERIT (to_longname, t); - INHERIT (to_doc, t); - /* Do not inherit to_open. */ - /* Do not inherit to_close. */ - /* Do not inherit to_attach. */ - /* Do not inherit to_post_attach. */ INHERIT (to_attach_no_wait, t); - /* Do not inherit to_detach. */ - /* Do not inherit to_disconnect. */ - /* Do not inherit to_resume. */ - /* Do not inherit to_wait. */ - /* Do not inherit to_fetch_registers. */ - /* Do not inherit to_store_registers. */ - /* Do not inherit to_prepare_to_store. */ - INHERIT (deprecated_xfer_memory, t); - /* Do not inherit to_files_info. */ - /* Do not inherit to_insert_breakpoint. */ - /* Do not inherit to_remove_breakpoint. */ - /* Do not inherit to_can_use_hw_breakpoint. */ - /* Do not inherit to_insert_hw_breakpoint. */ - /* Do not inherit to_remove_hw_breakpoint. */ - /* Do not inherit to_ranged_break_num_registers. */ - /* Do not inherit to_insert_watchpoint. */ - /* Do not inherit to_remove_watchpoint. */ - /* Do not inherit to_insert_mask_watchpoint. */ - /* Do not inherit to_remove_mask_watchpoint. */ - /* Do not inherit to_stopped_data_address. */ INHERIT (to_have_steppable_watchpoint, t); INHERIT (to_have_continuable_watchpoint, t); - /* Do not inherit to_stopped_by_watchpoint. */ - /* Do not inherit to_watchpoint_addr_within_range. */ - /* Do not inherit to_region_ok_for_hw_watchpoint. */ - /* Do not inherit to_can_accel_watchpoint_condition. */ - /* Do not inherit to_masked_watch_num_registers. */ - /* Do not inherit to_terminal_init. */ - /* Do not inherit to_terminal_inferior. */ - /* Do not inherit to_terminal_ours_for_output. */ - /* Do not inherit to_terminal_ours. */ - /* Do not inherit to_terminal_save_ours. */ - /* Do not inherit to_terminal_info. */ - /* Do not inherit to_kill. */ - /* Do not inherit to_load. */ - /* Do no inherit to_create_inferior. */ - /* Do not inherit to_post_startup_inferior. */ - /* Do not inherit to_insert_fork_catchpoint. */ - /* Do not inherit to_remove_fork_catchpoint. */ - /* Do not inherit to_insert_vfork_catchpoint. */ - /* Do not inherit to_remove_vfork_catchpoint. */ - /* Do not inherit to_follow_fork. */ - /* Do not inherit to_insert_exec_catchpoint. */ - /* Do not inherit to_remove_exec_catchpoint. */ - /* Do not inherit to_set_syscall_catchpoint. */ - /* Do not inherit to_has_exited. */ - /* Do not inherit to_mourn_inferior. */ - INHERIT (to_can_run, t); - /* Do not inherit to_pass_signals. */ - /* Do not inherit to_program_signals. */ - /* Do not inherit to_thread_alive. */ - /* Do not inherit to_find_new_threads. */ - /* Do not inherit to_pid_to_str. */ - /* Do not inherit to_extra_thread_info. */ - /* Do not inherit to_thread_name. */ - /* Do not inherit to_stop. */ - /* Do not inherit to_xfer_partial. */ - /* Do not inherit to_rcmd. */ - /* Do not inherit to_pid_to_exec_file. */ - /* Do not inherit to_log_command. */ - INHERIT (to_stratum, 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); - /* Do not inherit to_can_async_p. */ - /* Do not inherit to_is_async_p. */ - /* Do not inherit to_async. */ - /* Do not inherit to_find_memory_regions. */ - /* Do not inherit to_make_corefile_notes. */ - /* Do not inherit to_get_bookmark. */ - /* Do not inherit to_goto_bookmark. */ - /* Do not inherit to_get_thread_local_address. */ - /* Do not inherit to_can_execute_reverse. */ - /* Do not inherit to_execution_direction. */ - /* Do not inherit to_thread_architecture. */ - /* Do not inherit to_read_description. */ - /* Do not inherit to_get_ada_task_ptid. */ - /* Do not inherit to_search_memory. */ - /* Do not inherit to_supports_multi_process. */ - /* Do not inherit to_supports_enable_disable_tracepoint. */ - /* Do not inherit to_supports_string_tracing. */ - /* Do not inherit to_trace_init. */ - /* Do not inherit to_download_tracepoint. */ - /* Do not inherit to_can_download_tracepoint. */ - /* Do not inherit to_download_trace_state_variable. */ - /* Do not inherit to_enable_tracepoint. */ - /* Do not inherit to_disable_tracepoint. */ - /* Do not inherit to_trace_set_readonly_regions. */ - /* Do not inherit to_trace_start. */ - /* Do not inherit to_get_trace_status. */ - /* Do not inherit to_get_tracepoint_status. */ - /* Do not inherit to_trace_stop. */ - /* Do not inherit to_trace_find. */ - /* Do not inherit to_get_trace_state_variable_value. */ - /* Do not inherit to_save_trace_data. */ - /* Do not inherit to_upload_tracepoints. */ - /* Do not inherit to_upload_trace_state_variables. */ - /* Do not inherit to_get_raw_trace_data. */ - /* Do not inherit to_get_min_fast_tracepoint_insn_len. */ - /* Do not inherit to_set_disconnected_tracing. */ - /* Do not inherit to_set_circular_trace_buffer. */ - /* Do not inherit to_set_trace_buffer_size. */ - /* Do not inherit to_set_trace_notes. */ - /* Do not inherit to_get_tib_address. */ - /* Do not inherit to_set_permissions. */ - /* Do not inherit to_static_tracepoint_marker_at. */ - /* Do not inherit to_static_tracepoint_markers_by_strid. */ - /* Do not inherit to_traceframe_info. */ - /* Do not inherit to_use_agent. */ - /* Do not inherit to_can_use_agent. */ - /* Do not inherit to_augmented_libraries_svr4_read. */ - INHERIT (to_magic, t); - /* Do not inherit - to_supports_evaluation_of_breakpoint_conditions. */ - /* Do not inherit to_can_run_breakpoint_commands. */ - /* Do not inherit to_memory_map. */ - /* Do not inherit to_flash_erase. */ - /* Do not inherit to_flash_done. */ } #undef INHERIT - /* Clean up a target struct so it no longer has any zero pointers in - it. Some entries are defaulted to a method that print an error, - others are hard-wired to a standard recursive default. */ - -#define de_fault(field, value) \ - if (!current_target.field) \ - current_target.field = value - - de_fault (to_open, - (void (*) (char *, int)) - tcomplain); - de_fault (to_close, - (void (*) (struct target_ops *)) - target_ignore); - de_fault (deprecated_xfer_memory, - (int (*) (CORE_ADDR, gdb_byte *, int, int, - struct mem_attrib *, struct target_ops *)) - nomemory); - de_fault (to_can_run, - (int (*) (struct target_ops *)) - return_zero); - current_target.to_read_description = NULL; - -#undef de_fault - /* Finally, position the target-stack beneath the squashed "current_target". That way code looking for a non-inherited target method can quickly and simply find it. */ @@ -879,7 +743,7 @@ pop_all_targets (void) int target_is_pushed (struct target_ops *t) { - struct target_ops **cur; + struct target_ops *cur; /* Check magic number. If wrong, it probably means someone changed the struct definition, but not all the places that initialize one. */ @@ -892,31 +756,31 @@ target_is_pushed (struct target_ops *t) _("failed internal consistency check")); } - for (cur = &target_stack; (*cur) != NULL; cur = &(*cur)->beneath) - if (*cur == t) + for (cur = target_stack; cur != NULL; cur = cur->beneath) + if (cur == t) return 1; return 0; } +/* Default implementation of to_get_thread_local_address. */ + +static void +generic_tls_error (void) +{ + throw_error (TLS_GENERIC_ERROR, + _("Cannot find thread-local variables on this target")); +} + /* 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; - } + struct target_ops *target = ¤t_target; - if (target != NULL - && gdbarch_fetch_tls_load_module_address_p (target_gdbarch ())) + if (gdbarch_fetch_tls_load_module_address_p (target_gdbarch ())) { ptid_t ptid = inferior_ptid; volatile struct gdb_exception ex; @@ -928,10 +792,6 @@ target_translate_tls_address (struct objfile *objfile, CORE_ADDR offset) /* Fetch the load module address for this objfile. */ 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->to_get_thread_local_address (target, ptid, lm_addr, offset); @@ -997,13 +857,13 @@ target_translate_tls_address (struct objfile *objfile, CORE_ADDR offset) } const char * -target_xfer_status_to_string (enum target_xfer_status err) +target_xfer_status_to_string (enum target_xfer_status status) { #define CASE(X) case X: return #X - switch (err) + switch (status) { CASE(TARGET_XFER_E_IO); - CASE(TARGET_XFER_E_UNAVAILABLE); + CASE(TARGET_XFER_UNAVAILABLE); default: return ""; } @@ -1090,16 +950,7 @@ done: 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; + return (*target->to_get_section_table) (target); } /* Find a section containing ADDR. */ @@ -1121,85 +972,57 @@ target_section_by_addr (struct target_ops *target, CORE_ADDR addr) return NULL; } -/* Read memory from the live target, even if currently inspecting a - traceframe. The return is the same as that of target_read. */ -static enum target_xfer_status -target_read_live_memory (enum target_object object, - ULONGEST memaddr, gdb_byte *myaddr, ULONGEST len, - ULONGEST *xfered_len) -{ - enum target_xfer_status ret; - struct cleanup *cleanup; - - /* Switch momentarily out of tfind mode so to access live memory. - Note that this must not clear global state, such as the frame - cache, which must still remain valid for the previous traceframe. - We may be _building_ the frame cache at this point. */ - cleanup = make_cleanup_restore_traceframe_number (); - set_traceframe_number (-1); - - ret = target_xfer_partial (current_target.beneath, object, NULL, - myaddr, NULL, memaddr, len, xfered_len); - - do_cleanups (cleanup); - return ret; -} +/* Helper for the memory xfer routines. Checks the attributes of the + memory region of MEMADDR against the read or write being attempted. + If the access is permitted returns true, otherwise returns false. + REGION_P is an optional output parameter. If not-NULL, it is + filled with a pointer to the memory region of MEMADDR. REG_LEN + returns LEN trimmed to the end of the region. This is how much the + caller can continue requesting, if the access is permitted. A + single xfer request must not straddle memory region boundaries. */ -/* Using the set of read-only target sections of OPS, read live - read-only memory. Note that the actual reads start from the - top-most target again. +static int +memory_xfer_check_region (gdb_byte *readbuf, const gdb_byte *writebuf, + ULONGEST memaddr, ULONGEST len, ULONGEST *reg_len, + struct mem_region **region_p) +{ + struct mem_region *region; - For interface/parameters/return description see target.h, - to_xfer_partial. */ + region = lookup_mem_region (memaddr); -static enum target_xfer_status -memory_xfer_live_readonly_partial (struct target_ops *ops, - enum target_object object, - gdb_byte *readbuf, ULONGEST memaddr, - ULONGEST len, ULONGEST *xfered_len) -{ - struct target_section *secp; - struct target_section_table *table; + if (region_p != NULL) + *region_p = region; - secp = target_section_by_addr (ops, memaddr); - if (secp != NULL - && (bfd_get_section_flags (secp->the_bfd_section->owner, - secp->the_bfd_section) - & SEC_READONLY)) + switch (region->attrib.mode) { - struct target_section *p; - ULONGEST memend = memaddr + len; + case MEM_RO: + if (writebuf != NULL) + return 0; + break; - table = target_get_section_table (ops); + case MEM_WO: + if (readbuf != NULL) + return 0; + break; - for (p = table->sections; p < table->sections_end; p++) - { - if (memaddr >= p->addr) - { - if (memend <= p->endaddr) - { - /* Entire transfer is within this section. */ - return target_read_live_memory (object, memaddr, - readbuf, len, xfered_len); - } - else if (memaddr >= p->endaddr) - { - /* This section ends before the transfer starts. */ - continue; - } - else - { - /* This section overlaps the transfer. Just do half. */ - len = p->endaddr - memaddr; - return target_read_live_memory (object, memaddr, - readbuf, len, xfered_len); - } - } - } + case MEM_FLASH: + /* We only support writing to flash during "load" for now. */ + if (writebuf != NULL) + error (_("Writing to flash memory forbidden in this context")); + break; + + case MEM_NONE: + return 0; } - return TARGET_XFER_EOF; + /* region->hi == 0 means there's no upper bound. */ + if (memaddr + len < region->hi || region->hi == 0) + *reg_len = len; + else + *reg_len = region->hi - memaddr; + + return 1; } /* Read memory from more than one valid target. A core file, for @@ -1222,7 +1045,7 @@ raw_memory_xfer_partial (struct target_ops *ops, gdb_byte *readbuf, break; /* Stop if the target reports that the memory is not available. */ - if (res == TARGET_XFER_E_UNAVAILABLE) + if (res == TARGET_XFER_UNAVAILABLE) break; /* We want to continue past core files to executables, but not @@ -1234,6 +1057,23 @@ raw_memory_xfer_partial (struct target_ops *ops, gdb_byte *readbuf, } while (ops != NULL); + /* The cache works at the raw memory level. Make sure the cache + gets updated with raw contents no matter what kind of memory + object was originally being written. Note we do write-through + first, so that if it fails, we don't write to the cache contents + that never made it to the target. */ + if (writebuf != NULL + && !ptid_equal (inferior_ptid, null_ptid) + && target_dcache_init_p () + && (stack_cache_enabled_p () || code_cache_enabled_p ())) + { + DCACHE *dcache = target_dcache_get (); + + /* Note that writing to an area of memory which wasn't present + in the cache doesn't cause it to be loaded in. */ + dcache_update (dcache, res, memaddr, writebuf, *xfered_len); + } + return res; } @@ -1246,7 +1086,7 @@ memory_xfer_partial_1 (struct target_ops *ops, enum target_object object, ULONGEST len, ULONGEST *xfered_len) { enum target_xfer_status res; - int reg_len; + ULONGEST reg_len; struct mem_region *region; struct inferior *inf; @@ -1292,92 +1132,11 @@ memory_xfer_partial_1 (struct target_ops *ops, enum target_object object, } } - /* If reading unavailable memory in the context of traceframes, and - this address falls within a read-only section, fallback to - reading from live memory. */ - if (readbuf != NULL && get_traceframe_number () != -1) - { - VEC(mem_range_s) *available; - - /* If we fail to get the set of available memory, then the - target does not support querying traceframe info, and so we - attempt reading from the traceframe anyway (assuming the - target implements the old QTro packet then). */ - if (traceframe_available_memory (&available, memaddr, len)) - { - struct cleanup *old_chain; - - old_chain = make_cleanup (VEC_cleanup(mem_range_s), &available); - - if (VEC_empty (mem_range_s, available) - || VEC_index (mem_range_s, available, 0)->start != memaddr) - { - /* Don't read into the traceframe's available - memory. */ - if (!VEC_empty (mem_range_s, available)) - { - LONGEST oldlen = len; - - len = VEC_index (mem_range_s, available, 0)->start - memaddr; - gdb_assert (len <= oldlen); - } - - do_cleanups (old_chain); - - /* This goes through the topmost target again. */ - res = memory_xfer_live_readonly_partial (ops, object, - readbuf, memaddr, - len, xfered_len); - if (res == TARGET_XFER_OK) - return TARGET_XFER_OK; - else - { - /* No use trying further, we know some memory starting - at MEMADDR isn't available. */ - *xfered_len = len; - return TARGET_XFER_E_UNAVAILABLE; - } - } - - /* Don't try to read more than how much is available, in - case the target implements the deprecated QTro packet to - cater for older GDBs (the target's knowledge of read-only - sections may be outdated by now). */ - len = VEC_index (mem_range_s, available, 0)->length; - - do_cleanups (old_chain); - } - } - /* Try GDB's internal data cache. */ - region = lookup_mem_region (memaddr); - /* region->hi == 0 means there's no upper bound. */ - if (memaddr + len < region->hi || region->hi == 0) - reg_len = len; - else - reg_len = region->hi - memaddr; - - switch (region->attrib.mode) - { - case MEM_RO: - if (writebuf != NULL) - return TARGET_XFER_E_IO; - break; - - case MEM_WO: - if (readbuf != NULL) - return TARGET_XFER_E_IO; - break; - case MEM_FLASH: - /* We only support writing to flash during "load" for now. */ - if (writebuf != NULL) - error (_("Writing to flash memory forbidden in this context")); - break; - - case MEM_NONE: - return TARGET_XFER_E_IO; - } + if (!memory_xfer_check_region (readbuf, writebuf, memaddr, len, ®_len, + ®ion)) + return TARGET_XFER_E_IO; if (!ptid_equal (inferior_ptid, null_ptid)) inf = find_inferior_pid (ptid_get_pid (inferior_ptid)); @@ -1385,6 +1144,7 @@ memory_xfer_partial_1 (struct target_ops *ops, enum target_object object, inf = NULL; if (inf != NULL + && readbuf != NULL /* The dcache reads whole cache lines; that doesn't play well with reading from a trace buffer, because reading outside of the collected memory range fails. */ @@ -1394,23 +1154,9 @@ memory_xfer_partial_1 (struct target_ops *ops, enum target_object object, || (code_cache_enabled_p () && object == TARGET_OBJECT_CODE_MEMORY))) { DCACHE *dcache = target_dcache_get_or_init (); - int l; - if (readbuf != NULL) - l = dcache_xfer_memory (ops, 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. */ - l = dcache_xfer_memory (ops, dcache, memaddr, (void *) writebuf, - reg_len, 1); - if (l <= 0) - return TARGET_XFER_E_IO; - else - { - *xfered_len = (ULONGEST) l; - return TARGET_XFER_OK; - } + return dcache_read_memory_partial (ops, dcache, memaddr, readbuf, + reg_len, xfered_len); } /* If none of those methods found the memory we wanted, fall back @@ -1426,23 +1172,6 @@ memory_xfer_partial_1 (struct target_ops *ops, enum target_object object, res = raw_memory_xfer_partial (ops, readbuf, writebuf, memaddr, reg_len, xfered_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 == TARGET_XFER_OK - && inf != NULL - && writebuf != NULL - && target_dcache_init_p () - && !region->attrib.cache - && ((stack_cache_enabled_p () && object != TARGET_OBJECT_STACK_MEMORY) - || (code_cache_enabled_p () && object != TARGET_OBJECT_CODE_MEMORY))) - { - DCACHE *dcache = target_dcache_get (); - - dcache_update (dcache, memaddr, (void *) writebuf, reg_len); - } - /* If we still haven't got anything, return the last error. We give up. */ return res; @@ -1471,7 +1200,7 @@ memory_xfer_partial (struct target_ops *ops, enum target_object object, xfered_len); if (res == TARGET_XFER_OK && !show_memory_breakpoints) - breakpoint_xfer_memory (readbuf, NULL, NULL, memaddr, res); + breakpoint_xfer_memory (readbuf, NULL, NULL, memaddr, *xfered_len); } else { @@ -1547,6 +1276,16 @@ target_xfer_partial (struct target_ops *ops, writebuf, offset, len, xfered_len); else if (object == TARGET_OBJECT_RAW_MEMORY) { + /* Skip/avoid accessing the target if the memory region + attributes block the access. Check this here instead of in + raw_memory_xfer_partial as otherwise we'd end up checking + this twice in the case of the memory_xfer_partial path is + taken; once before checking the dcache, and another in the + tail call to raw_memory_xfer_partial. */ + if (!memory_xfer_check_region (readbuf, writebuf, offset, len, &len, + NULL)) + return TARGET_XFER_E_IO; + /* Request the normal memory object from other layers. */ retval = raw_memory_xfer_partial (ops, readbuf, writebuf, offset, len, xfered_len); @@ -1602,7 +1341,7 @@ target_xfer_partial (struct target_ops *ops, /* Check implementations of to_xfer_partial update *XFERED_LEN properly. Do assertion after printing debug messages, so that we can find more clues on assertion failure from debugging messages. */ - if (retval == TARGET_XFER_OK || retval == TARGET_XFER_E_UNAVAILABLE) + if (retval == TARGET_XFER_OK || retval == TARGET_XFER_UNAVAILABLE) gdb_assert (*xfered_len > 0); return retval; @@ -1632,6 +1371,22 @@ target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len) return TARGET_XFER_E_IO; } +/* See target/target.h. */ + +int +target_read_uint32 (CORE_ADDR memaddr, uint32_t *result) +{ + gdb_byte buf[4]; + int r; + + r = target_read_memory (memaddr, buf, sizeof buf); + if (r != 0) + return r; + *result = extract_unsigned_integer (buf, sizeof buf, + gdbarch_byte_order (target_gdbarch ())); + return 0; +} + /* Like target_read_memory, but specify explicitly that this is a read from the target's raw memory. That is, this read bypasses the dcache, breakpoint shadowing, etc. */ @@ -1724,17 +1479,7 @@ target_memory_map (void) int ix; struct target_ops *t; - if (targetdebug) - fprintf_unfiltered (gdb_stdlog, "target_memory_map ()\n"); - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_memory_map != NULL) - break; - - if (t == NULL) - return NULL; - - result = t->to_memory_map (t); + result = current_target.to_memory_map (¤t_target); if (result == NULL) return NULL; @@ -1765,36 +1510,13 @@ target_memory_map (void) void target_flash_erase (ULONGEST address, LONGEST length) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_flash_erase != NULL) - { - if (targetdebug) - fprintf_unfiltered (gdb_stdlog, "target_flash_erase (%s, %s)\n", - hex_string (address), phex (length, 0)); - t->to_flash_erase (t, address, length); - return; - } - - tcomplain (); + current_target.to_flash_erase (¤t_target, address, length); } void target_flash_done (void) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_flash_done != NULL) - { - if (targetdebug) - fprintf_unfiltered (gdb_stdlog, "target_flash_done\n"); - t->to_flash_done (t); - return; - } - - tcomplain (); + current_target.to_flash_done (¤t_target); } static void @@ -1806,56 +1528,6 @@ show_trust_readonly (struct ui_file *file, int from_tty, value); } -/* More generic transfers. */ - -static enum target_xfer_status -default_xfer_partial (struct target_ops *ops, enum target_object object, - const char *annex, gdb_byte *readbuf, - const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, - ULONGEST *xfered_len) -{ - if (object == TARGET_OBJECT_MEMORY - && ops->deprecated_xfer_memory != NULL) - /* If available, fall back to the target's - "deprecated_xfer_memory" method. */ - { - int xfered = -1; - - errno = 0; - if (writebuf != NULL) - { - void *buffer = xmalloc (len); - struct cleanup *cleanup = make_cleanup (xfree, buffer); - - memcpy (buffer, writebuf, len); - xfered = ops->deprecated_xfer_memory (offset, buffer, len, - 1/*write*/, NULL, ops); - do_cleanups (cleanup); - } - if (readbuf != NULL) - xfered = ops->deprecated_xfer_memory (offset, readbuf, len, - 0/*read*/, NULL, ops); - if (xfered > 0) - { - *xfered_len = (ULONGEST) xfered; - return TARGET_XFER_E_IO; - } - else if (xfered == 0 && errno == 0) - /* "deprecated_xfer_memory" uses 0, cross checked against - ERRNO as one indication of an error. */ - return TARGET_XFER_EOF; - else - return TARGET_XFER_E_IO; - } - else - { - gdb_assert (ops->beneath != NULL); - return ops->beneath->to_xfer_partial (ops->beneath, object, annex, - readbuf, writebuf, offset, len, - xfered_len); - } -} - /* Target vector read/write partial wrapper functions. */ static enum target_xfer_status @@ -2150,12 +1822,9 @@ target_write_with_progress (struct target_ops *ops, offset + xfered, len - xfered, &xfered_len); - if (status == TARGET_XFER_EOF) - return xfered; - if (TARGET_XFER_STATUS_ERROR_P (status)) - return -1; + if (status != TARGET_XFER_OK) + return status == TARGET_XFER_EOF ? xfered : -1; - gdb_assert (status == TARGET_XFER_OK); if (progress) (*progress) (xfered_len, baton); @@ -2487,72 +2156,29 @@ target_detach (const char *args, int from_tty) prepare_for_detach (); current_target.to_detach (¤t_target, args, from_tty); - if (targetdebug) - fprintf_unfiltered (gdb_stdlog, "target_detach (%s, %d)\n", - args, from_tty); } void -target_disconnect (char *args, int from_tty) +target_disconnect (const char *args, int from_tty) { - 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) - { - if (targetdebug) - fprintf_unfiltered (gdb_stdlog, "target_disconnect (%s, %d)\n", - args, from_tty); - t->to_disconnect (t, args, from_tty); - return; - } - - tcomplain (); + current_target.to_disconnect (¤t_target, args, from_tty); } ptid_t target_wait (ptid_t ptid, struct target_waitstatus *status, int options) { - struct target_ops *t; - ptid_t retval = (current_target.to_wait) (¤t_target, ptid, - status, options); - - if (targetdebug) - { - char *status_string; - char *options_string; - - status_string = target_waitstatus_to_string (status); - options_string = target_options_to_string (options); - fprintf_unfiltered (gdb_stdlog, - "target_wait (%d, status, options={%s})" - " = %d, %s\n", - ptid_get_pid (ptid), options_string, - ptid_get_pid (retval), status_string); - xfree (status_string); - xfree (options_string); - } - - return retval; + return (current_target.to_wait) (¤t_target, ptid, status, options); } 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); + return (*current_target.to_pid_to_str) (¤t_target, ptid); } char * @@ -2569,76 +2195,34 @@ target_resume (ptid_t ptid, int step, enum gdb_signal signal) target_dcache_invalidate (); current_target.to_resume (¤t_target, ptid, step, signal); - if (targetdebug) - fprintf_unfiltered (gdb_stdlog, "target_resume (%d, %s, %s)\n", - ptid_get_pid (ptid), - step ? "step" : "continue", - gdb_signal_to_name (signal)); registers_changed_ptid (ptid); + /* We only set the internal executing state here. The user/frontend + running state is set at a higher level. */ set_executing (ptid, 1); - set_running (ptid, 1); clear_inline_frame_state (ptid); } void target_pass_signals (int numsigs, unsigned char *pass_signals) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - { - if (t->to_pass_signals != NULL) - { - if (targetdebug) - { - int i; - - fprintf_unfiltered (gdb_stdlog, "target_pass_signals (%d, {", - numsigs); - - for (i = 0; i < numsigs; i++) - if (pass_signals[i]) - fprintf_unfiltered (gdb_stdlog, " %s", - gdb_signal_to_name (i)); - - fprintf_unfiltered (gdb_stdlog, " })\n"); - } - - (*t->to_pass_signals) (t, numsigs, pass_signals); - return; - } - } + (*current_target.to_pass_signals) (¤t_target, numsigs, pass_signals); } void target_program_signals (int numsigs, unsigned char *program_signals) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - { - if (t->to_program_signals != NULL) - { - if (targetdebug) - { - int i; - - fprintf_unfiltered (gdb_stdlog, "target_program_signals (%d, {", - numsigs); - - for (i = 0; i < numsigs; i++) - if (program_signals[i]) - fprintf_unfiltered (gdb_stdlog, " %s", - gdb_signal_to_name (i)); - - fprintf_unfiltered (gdb_stdlog, " })\n"); - } + (*current_target.to_program_signals) (¤t_target, + numsigs, program_signals); +} - (*t->to_program_signals) (t, numsigs, program_signals); - return; - } - } +static int +default_follow_fork (struct target_ops *self, int follow_child, + int detach_fork) +{ + /* Some target returned a fork event, but did not know how to follow it. */ + internal_error (__FILE__, __LINE__, + _("could not find a target to follow fork")); } /* Look through the list of possible targets for a target that can @@ -2647,51 +2231,26 @@ target_program_signals (int numsigs, unsigned char *program_signals) int target_follow_fork (int follow_child, int detach_fork) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - { - if (t->to_follow_fork != NULL) - { - int retval = t->to_follow_fork (t, follow_child, detach_fork); - - if (targetdebug) - fprintf_unfiltered (gdb_stdlog, - "target_follow_fork (%d, %d) = %d\n", - follow_child, detach_fork, retval); - return retval; - } - } + return current_target.to_follow_fork (¤t_target, + follow_child, detach_fork); +} - /* Some target returned a fork event, but did not know how to follow it. */ +static void +default_mourn_inferior (struct target_ops *self) +{ internal_error (__FILE__, __LINE__, - _("could not find a target to follow fork")); + _("could not find a target to follow mourn inferior")); } 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; - } - } + current_target.to_mourn_inferior (¤t_target); - internal_error (__FILE__, __LINE__, - _("could not find a target to follow mourn inferior")); + /* 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 (); } /* Look for a target which can describe architectural features, starting @@ -2700,23 +2259,10 @@ target_mourn_inferior (void) 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; + return target->to_read_description (target); } -/* The default implementation of to_search_memory. - This implements a basic search of memory, reading target memory and +/* 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). */ @@ -2823,6 +2369,20 @@ simple_search_memory (struct target_ops *ops, return 0; } +/* Default implementation of memory-searching. */ + +static int +default_search_memory (struct target_ops *self, + CORE_ADDR start_addr, ULONGEST search_space_len, + const gdb_byte *pattern, ULONGEST pattern_len, + CORE_ADDR *found_addrp) +{ + /* Start over from the top of the target stack. */ + return simple_search_memory (current_target.beneath, + start_addr, search_space_len, + pattern, pattern_len, found_addrp); +} + /* Search SEARCH_SPACE_LEN bytes beginning at START_ADDR for the sequence of bytes in PATTERN with length PATTERN_LEN. @@ -2835,39 +2395,9 @@ 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; - - /* We don't use INHERIT to set current_target.to_search_memory, - so we have to scan the target stack and handle targetdebug - ourselves. */ - - if (targetdebug) - fprintf_unfiltered (gdb_stdlog, "target_search_memory (%s, ...)\n", - hex_string (start_addr)); - - 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; + return current_target.to_search_memory (¤t_target, start_addr, + search_space_len, + pattern, pattern_len, found_addrp); } /* Look through the currently pushed targets. If none of them will @@ -2888,10 +2418,11 @@ target_require_runnable (void) if (t->to_create_inferior != NULL) return; - /* Do not worry about thread_stratum targets that can not + /* Do not worry about targets at certain strata 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 + || t->to_stratum == record_stratum || t->to_stratum == arch_stratum) continue; @@ -2906,6 +2437,20 @@ target_require_runnable (void) internal_error (__FILE__, __LINE__, _("No targets found")); } +/* Whether GDB is allowed to fall back to the default run target for + "run", "attach", etc. when no target is connected yet. */ +static int auto_connect_native_target = 1; + +static void +show_auto_connect_native_target (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, + _("Whether GDB may automatically connect to the " + "native target is %s.\n"), + value); +} + /* Look through the list of possible targets for a target that can execute a run or attach command without any other data. This is used to locate the default process stratum. @@ -2916,23 +2461,28 @@ target_require_runnable (void) static struct target_ops * find_default_run_target (char *do_mesg) { - struct target_ops **t; struct target_ops *runable = NULL; - int count; - count = 0; - - for (t = target_structs; t < target_structs + target_struct_size; - ++t) + if (auto_connect_native_target) { - if ((*t)->to_can_run && target_can_run (*t)) + struct target_ops *t; + int count = 0; + int i; + + for (i = 0; VEC_iterate (target_ops_p, target_structs, i, t); ++i) { - runable = *t; - ++count; + if (t->to_can_run != delegate_can_run && target_can_run (t)) + { + runable = t; + ++count; + } } + + if (count != 1) + runable = NULL; } - if (count != 1) + if (runable == NULL) { if (do_mesg) error (_("Don't know how to %s. Try \"help target\"."), do_mesg); @@ -2943,85 +2493,52 @@ find_default_run_target (char *do_mesg) return runable; } -void -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) (t, args, from_tty); - return; -} +/* See target.h. */ -void -find_default_create_inferior (struct target_ops *ops, - char *exec_file, char *allargs, char **env, - int from_tty) +struct target_ops * +find_attach_target (void) { struct target_ops *t; - t = find_default_run_target ("run"); - (t->to_create_inferior) (t, exec_file, allargs, env, from_tty); - return; -} + /* If a target on the current stack can attach, use it. */ + for (t = current_target.beneath; t != NULL; t = t->beneath) + { + if (t->to_attach != NULL) + break; + } -static int -find_default_can_async_p (struct target_ops *ignore) -{ - struct target_ops *t; + /* Otherwise, use the default run target for attaching. */ + if (t == NULL) + t = find_default_run_target ("attach"); - /* 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 != delegate_can_async_p) - return (t->to_can_async_p) (t); - return 0; + return t; } -static int -find_default_is_async_p (struct target_ops *ignore) -{ - 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 != delegate_is_async_p) - return (t->to_is_async_p) (t); - return 0; -} +/* See target.h. */ -static int -find_default_supports_non_stop (struct target_ops *self) +struct target_ops * +find_run_target (void) { struct target_ops *t; - t = find_default_run_target (NULL); - if (t && t->to_supports_non_stop) - return (t->to_supports_non_stop) (t); - return 0; -} - -int -target_supports_non_stop (void) -{ - struct target_ops *t; + /* If a target on the current stack can attach, use it. */ + for (t = current_target.beneath; t != NULL; t = t->beneath) + { + if (t->to_create_inferior != NULL) + break; + } - for (t = ¤t_target; t != NULL; t = t->beneath) - if (t->to_supports_non_stop) - return t->to_supports_non_stop (t); + /* Otherwise, use the default run target. */ + if (t == NULL) + t = find_default_run_target ("run"); - return 0; + return t; } /* Implement the "info proc" command. */ int -target_info_proc (char *args, enum info_proc_what what) +target_info_proc (const char *args, enum info_proc_what what) { struct target_ops *t; @@ -3092,30 +2609,10 @@ target_get_osdata (const char *type) return target_read_stralloc (t, TARGET_OBJECT_OSDATA, type); } -/* Determine the current address space of thread PTID. */ - -struct address_space * -target_thread_address_space (ptid_t ptid) +static struct address_space * +default_thread_address_space (struct target_ops *self, ptid_t ptid) { - struct address_space *aspace; struct inferior *inf; - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - { - if (t->to_thread_address_space != NULL) - { - 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; - } - } /* Fall-back to the "main" address space of the inferior. */ inf = find_inferior_pid (ptid_get_pid (ptid)); @@ -3129,6 +2626,19 @@ target_thread_address_space (ptid_t ptid) return inf->aspace; } +/* Determine the current address space of thread PTID. */ + +struct address_space * +target_thread_address_space (ptid_t ptid) +{ + struct address_space *aspace; + + aspace = current_target.to_thread_address_space (¤t_target, ptid); + gdb_assert (aspace != NULL); + + return aspace; +} + /* Target file operations. */ @@ -3451,7 +2961,13 @@ default_thread_architecture (struct target_ops *ops, ptid_t ptid) } static int -return_zero (void) +return_zero (struct target_ops *ignore) +{ + return 0; +} + +static int +return_zero_has_execution (struct target_ops *ignore, ptid_t ignore2) { return 0; } @@ -3529,7 +3045,7 @@ normal_pid_to_str (ptid_t ptid) } static char * -dummy_pid_to_str (struct target_ops *ops, ptid_t ptid) +default_pid_to_str (struct target_ops *ops, ptid_t ptid) { return normal_pid_to_str (ptid); } @@ -3561,30 +3077,19 @@ init_dummy_target (void) dummy_target.to_shortname = "None"; dummy_target.to_longname = "None"; dummy_target.to_doc = ""; - dummy_target.to_create_inferior = find_default_create_inferior; - dummy_target.to_supports_non_stop = find_default_supports_non_stop; dummy_target.to_supports_disable_randomization = find_default_supports_disable_randomization; - dummy_target.to_pid_to_str = dummy_pid_to_str; dummy_target.to_stratum = dummy_stratum; - 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 *, ptid_t)) return_zero; + dummy_target.to_has_all_memory = return_zero; + dummy_target.to_has_memory = return_zero; + dummy_target.to_has_stack = return_zero; + dummy_target.to_has_registers = return_zero; + dummy_target.to_has_execution = return_zero_has_execution; dummy_target.to_magic = OPS_MAGIC; install_dummy_methods (&dummy_target); } -static void -debug_to_open (char *args, int from_tty) -{ - debug_target.to_open (args, from_tty); - - fprintf_unfiltered (gdb_stdlog, "target_open (%s, %d)\n", args, from_tty); -} void target_close (struct target_ops *targ) @@ -3600,54 +3105,16 @@ target_close (struct target_ops *targ) fprintf_unfiltered (gdb_stdlog, "target_close ()\n"); } +int +target_thread_alive (ptid_t ptid) +{ + return current_target.to_thread_alive (¤t_target, ptid); +} + void -target_attach (char *args, int from_tty) +target_update_thread_list (void) { - current_target.to_attach (¤t_target, args, from_tty); - if (targetdebug) - fprintf_unfiltered (gdb_stdlog, "target_attach (%s, %d)\n", - args, from_tty); -} - -int -target_thread_alive (ptid_t ptid) -{ - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - { - if (t->to_thread_alive != NULL) - { - int retval; - - retval = t->to_thread_alive (t, ptid); - if (targetdebug) - fprintf_unfiltered (gdb_stdlog, "target_thread_alive (%d) = %d\n", - ptid_get_pid (ptid), retval); - - return retval; - } - } - - return 0; -} - -void -target_find_new_threads (void) -{ - 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"); - - return; - } - } + current_target.to_update_thread_list (¤t_target); } void @@ -3662,12 +3129,29 @@ target_stop (ptid_t ptid) (*current_target.to_stop) (¤t_target, ptid); } -static void -debug_to_post_attach (struct target_ops *self, int pid) +/* See target/target.h. */ + +void +target_stop_and_wait (ptid_t ptid) { - debug_target.to_post_attach (&debug_target, pid); + struct target_waitstatus status; + int was_non_stop = non_stop; + + non_stop = 1; + target_stop (ptid); + + memset (&status, 0, sizeof (status)); + target_wait (ptid, &status, 0); - fprintf_unfiltered (gdb_stdlog, "target_post_attach (%d)\n", pid); + non_stop = was_non_stop; +} + +/* See target/target.h. */ + +void +target_continue_no_signal (ptid_t ptid) +{ + target_resume (ptid, 0, GDB_SIGNAL_0); } /* Concatenate ELEM to LIST, a comma separate list, and return the @@ -3758,18 +3242,9 @@ debug_print_register (const char * func, void target_fetch_registers (struct regcache *regcache, int 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; - } - } + current_target.to_fetch_registers (¤t_target, regcache, regno); + if (targetdebug) + debug_print_register ("target_fetch_registers", regcache, regno); } void @@ -3790,47 +3265,53 @@ target_store_registers (struct regcache *regcache, int regno) int target_core_of_thread (ptid_t ptid) { - struct target_ops *t; + return current_target.to_core_of_thread (¤t_target, ptid); +} - for (t = current_target.beneath; t != NULL; t = t->beneath) +int +simple_verify_memory (struct target_ops *ops, + const gdb_byte *data, CORE_ADDR lma, ULONGEST size) +{ + LONGEST total_xfered = 0; + + while (total_xfered < size) { - if (t->to_core_of_thread != NULL) - { - int retval = t->to_core_of_thread (t, ptid); + ULONGEST xfered_len; + enum target_xfer_status status; + gdb_byte buf[1024]; + ULONGEST howmuch = min (sizeof (buf), size - total_xfered); - if (targetdebug) - fprintf_unfiltered (gdb_stdlog, - "target_core_of_thread (%d) = %d\n", - ptid_get_pid (ptid), retval); - return retval; + status = target_xfer_partial (ops, TARGET_OBJECT_MEMORY, NULL, + buf, NULL, lma + total_xfered, howmuch, + &xfered_len); + if (status == TARGET_XFER_OK + && memcmp (data + total_xfered, buf, xfered_len) == 0) + { + total_xfered += xfered_len; + QUIT; } + else + return 0; } + return 1; +} - return -1; +/* Default implementation of memory verification. */ + +static int +default_verify_memory (struct target_ops *self, + const gdb_byte *data, CORE_ADDR memaddr, ULONGEST size) +{ + /* Start over from the top of the target stack. */ + return simple_verify_memory (current_target.beneath, + data, memaddr, size); } int target_verify_memory (const gdb_byte *data, CORE_ADDR memaddr, ULONGEST size) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - { - if (t->to_verify_memory != NULL) - { - int retval = t->to_verify_memory (t, data, memaddr, size); - - if (targetdebug) - fprintf_unfiltered (gdb_stdlog, - "target_verify_memory (%s, %s) = %d\n", - paddress (target_gdbarch (), memaddr), - pulongest (size), - retval); - return retval; - } - } - - tcomplain (); + return current_target.to_verify_memory (¤t_target, + data, memaddr, size); } /* The documentation for this function is in its prototype declaration in @@ -3839,25 +3320,8 @@ target_verify_memory (const gdb_byte *data, CORE_ADDR memaddr, ULONGEST size) int target_insert_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask, int rw) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_insert_mask_watchpoint != NULL) - { - int ret; - - ret = t->to_insert_mask_watchpoint (t, addr, mask, rw); - - if (targetdebug) - fprintf_unfiltered (gdb_stdlog, "\ -target_insert_mask_watchpoint (%s, %s, %d) = %d\n", - core_addr_to_string (addr), - core_addr_to_string (mask), rw, ret); - - return ret; - } - - return 1; + return current_target.to_insert_mask_watchpoint (¤t_target, + addr, mask, rw); } /* The documentation for this function is in its prototype declaration in @@ -3866,25 +3330,8 @@ target_insert_mask_watchpoint (%s, %s, %d) = %d\n", int target_remove_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask, int rw) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_remove_mask_watchpoint != NULL) - { - int ret; - - ret = t->to_remove_mask_watchpoint (t, addr, mask, rw); - - if (targetdebug) - fprintf_unfiltered (gdb_stdlog, "\ -target_remove_mask_watchpoint (%s, %s, %d) = %d\n", - core_addr_to_string (addr), - core_addr_to_string (mask), rw, ret); - - return ret; - } - - return 1; + return current_target.to_remove_mask_watchpoint (¤t_target, + addr, mask, rw); } /* The documentation for this function is in its prototype declaration @@ -3893,13 +3340,8 @@ target_remove_mask_watchpoint (%s, %s, %d) = %d\n", int target_masked_watch_num_registers (CORE_ADDR addr, CORE_ADDR mask) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_masked_watch_num_registers != NULL) - return t->to_masked_watch_num_registers (t, addr, mask); - - return -1; + return current_target.to_masked_watch_num_registers (¤t_target, + addr, mask); } /* The documentation for this function is in its prototype declaration @@ -3908,13 +3350,7 @@ target_masked_watch_num_registers (CORE_ADDR addr, CORE_ADDR mask) int target_ranged_break_num_registers (void) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_ranged_break_num_registers != NULL) - return t->to_ranged_break_num_registers (t); - - return -1; + return current_target.to_ranged_break_num_registers (¤t_target); } /* See target.h. */ @@ -3922,14 +3358,7 @@ target_ranged_break_num_registers (void) struct btrace_target_info * target_enable_btrace (ptid_t ptid) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_enable_btrace != NULL) - return t->to_enable_btrace (t, ptid); - - tcomplain (); - return NULL; + return current_target.to_enable_btrace (¤t_target, ptid); } /* See target.h. */ @@ -3937,16 +3366,7 @@ target_enable_btrace (ptid_t ptid) void target_disable_btrace (struct btrace_target_info *btinfo) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_disable_btrace != NULL) - { - t->to_disable_btrace (t, btinfo); - return; - } - - tcomplain (); + current_target.to_disable_btrace (¤t_target, btinfo); } /* See target.h. */ @@ -3954,16 +3374,7 @@ target_disable_btrace (struct btrace_target_info *btinfo) void target_teardown_btrace (struct btrace_target_info *btinfo) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_teardown_btrace != NULL) - { - t->to_teardown_btrace (t, btinfo); - return; - } - - tcomplain (); + current_target.to_teardown_btrace (¤t_target, btinfo); } /* See target.h. */ @@ -3973,14 +3384,7 @@ target_read_btrace (VEC (btrace_block_s) **btrace, struct btrace_target_info *btinfo, enum btrace_read_type type) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_read_btrace != NULL) - return t->to_read_btrace (t, btrace, btinfo, type); - - tcomplain (); - return BTRACE_ERR_NOT_SUPPORTED; + return current_target.to_read_btrace (¤t_target, btrace, btinfo, type); } /* See target.h. */ @@ -3988,33 +3392,7 @@ target_read_btrace (VEC (btrace_block_s) **btrace, void target_stop_recording (void) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_stop_recording != NULL) - { - t->to_stop_recording (t); - return; - } - - /* This is optional. */ -} - -/* See target.h. */ - -void -target_info_record (void) -{ - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_info_record != NULL) - { - t->to_info_record (t); - return; - } - - tcomplain (); + current_target.to_stop_recording (¤t_target); } /* See target.h. */ @@ -4022,16 +3400,7 @@ target_info_record (void) void target_save_record (const char *filename) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_save_record != NULL) - { - t->to_save_record (t, filename); - return; - } - - tcomplain (); + current_target.to_save_record (¤t_target, filename); } /* See target.h. */ @@ -4042,7 +3411,8 @@ target_supports_delete_record (void) struct target_ops *t; for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_delete_record != NULL) + if (t->to_delete_record != delegate_delete_record + && t->to_delete_record != tdefault_delete_record) return 1; return 0; @@ -4053,16 +3423,7 @@ target_supports_delete_record (void) void target_delete_record (void) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_delete_record != NULL) - { - t->to_delete_record (t); - return; - } - - tcomplain (); + current_target.to_delete_record (¤t_target); } /* See target.h. */ @@ -4070,13 +3431,7 @@ target_delete_record (void) int target_record_is_replaying (void) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_record_is_replaying != NULL) - return t->to_record_is_replaying (t); - - return 0; + return current_target.to_record_is_replaying (¤t_target); } /* See target.h. */ @@ -4084,16 +3439,7 @@ target_record_is_replaying (void) void target_goto_record_begin (void) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_goto_record_begin != NULL) - { - t->to_goto_record_begin (t); - return; - } - - tcomplain (); + current_target.to_goto_record_begin (¤t_target); } /* See target.h. */ @@ -4101,16 +3447,7 @@ target_goto_record_begin (void) void target_goto_record_end (void) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_goto_record_end != NULL) - { - t->to_goto_record_end (t); - return; - } - - tcomplain (); + current_target.to_goto_record_end (¤t_target); } /* See target.h. */ @@ -4118,16 +3455,7 @@ target_goto_record_end (void) void target_goto_record (ULONGEST insn) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_goto_record != NULL) - { - t->to_goto_record (t, insn); - return; - } - - tcomplain (); + current_target.to_goto_record (¤t_target, insn); } /* See target.h. */ @@ -4135,16 +3463,7 @@ target_goto_record (ULONGEST insn) void target_insn_history (int size, int flags) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_insn_history != NULL) - { - t->to_insn_history (t, size, flags); - return; - } - - tcomplain (); + current_target.to_insn_history (¤t_target, size, flags); } /* See target.h. */ @@ -4152,16 +3471,7 @@ target_insn_history (int size, int flags) void target_insn_history_from (ULONGEST from, int size, int flags) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_insn_history_from != NULL) - { - t->to_insn_history_from (t, from, size, flags); - return; - } - - tcomplain (); + current_target.to_insn_history_from (¤t_target, from, size, flags); } /* See target.h. */ @@ -4169,16 +3479,7 @@ target_insn_history_from (ULONGEST from, int size, int flags) void target_insn_history_range (ULONGEST begin, ULONGEST end, int flags) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_insn_history_range != NULL) - { - t->to_insn_history_range (t, begin, end, flags); - return; - } - - tcomplain (); + current_target.to_insn_history_range (¤t_target, begin, end, flags); } /* See target.h. */ @@ -4186,16 +3487,7 @@ target_insn_history_range (ULONGEST begin, ULONGEST end, int flags) void target_call_history (int size, int flags) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_call_history != NULL) - { - t->to_call_history (t, size, flags); - return; - } - - tcomplain (); + current_target.to_call_history (¤t_target, size, flags); } /* See target.h. */ @@ -4203,16 +3495,7 @@ target_call_history (int size, int flags) void target_call_history_from (ULONGEST begin, int size, int flags) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_call_history_from != NULL) - { - t->to_call_history_from (t, begin, size, flags); - return; - } - - tcomplain (); + current_target.to_call_history_from (¤t_target, begin, size, flags); } /* See target.h. */ @@ -4220,24 +3503,7 @@ target_call_history_from (ULONGEST begin, int size, int flags) void target_call_history_range (ULONGEST begin, ULONGEST end, int flags) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_call_history_range != NULL) - { - t->to_call_history_range (t, begin, end, flags); - return; - } - - tcomplain (); -} - -static void -debug_to_prepare_to_store (struct target_ops *self, struct regcache *regcache) -{ - debug_target.to_prepare_to_store (&debug_target, regcache); - - fprintf_unfiltered (gdb_stdlog, "target_prepare_to_store ()\n"); + current_target.to_call_history_range (¤t_target, begin, end, flags); } /* See target.h. */ @@ -4245,13 +3511,7 @@ debug_to_prepare_to_store (struct target_ops *self, struct regcache *regcache) const struct frame_unwind * target_get_unwinder (void) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_get_unwinder != NULL) - return t->to_get_unwinder; - - return NULL; + return current_target.to_get_unwinder (¤t_target); } /* See target.h. */ @@ -4259,25 +3519,15 @@ target_get_unwinder (void) const struct frame_unwind * target_get_tailcall_unwinder (void) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - if (t->to_get_tailcall_unwinder != NULL) - return t->to_get_tailcall_unwinder; - - return NULL; + return current_target.to_get_tailcall_unwinder (¤t_target); } -/* See target.h. */ +/* Default implementation of to_decr_pc_after_break. */ -CORE_ADDR -forward_target_decr_pc_after_break (struct target_ops *ops, +static CORE_ADDR +default_target_decr_pc_after_break (struct target_ops *ops, struct gdbarch *gdbarch) { - for (; ops != NULL; ops = ops->beneath) - if (ops->to_decr_pc_after_break != NULL) - return ops->to_decr_pc_after_break (ops, gdbarch); - return gdbarch_decr_pc_after_break (gdbarch); } @@ -4286,468 +3536,23 @@ forward_target_decr_pc_after_break (struct target_ops *ops, CORE_ADDR target_decr_pc_after_break (struct gdbarch *gdbarch) { - return forward_target_decr_pc_after_break (current_target.beneath, gdbarch); -} - -static int -deprecated_debug_xfer_memory (CORE_ADDR memaddr, bfd_byte *myaddr, int len, - int write, struct mem_attrib *attrib, - struct target_ops *target) -{ - int retval; - - retval = debug_target.deprecated_xfer_memory (memaddr, myaddr, len, write, - attrib, target); - - fprintf_unfiltered (gdb_stdlog, - "target_xfer_memory (%s, xxx, %d, %s, xxx) = %d", - paddress (target_gdbarch (), memaddr), len, - write ? "write" : "read", retval); - - if (retval > 0) - { - int i; - - fputs_unfiltered (", bytes =", gdb_stdlog); - for (i = 0; i < retval; i++) - { - if ((((intptr_t) &(myaddr[i])) & 0xf) == 0) - { - if (targetdebug < 2 && i > 0) - { - fprintf_unfiltered (gdb_stdlog, " ..."); - break; - } - fprintf_unfiltered (gdb_stdlog, "\n"); - } - - fprintf_unfiltered (gdb_stdlog, " %02x", myaddr[i] & 0xff); - } - } - - fputc_unfiltered ('\n', gdb_stdlog); - - return retval; -} - -static void -debug_to_files_info (struct target_ops *target) -{ - debug_target.to_files_info (target); - - fprintf_unfiltered (gdb_stdlog, "target_files_info (xxx)\n"); -} - -static int -debug_to_insert_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch, - struct bp_target_info *bp_tgt) -{ - int retval; - - retval = debug_target.to_insert_breakpoint (&debug_target, gdbarch, bp_tgt); - - fprintf_unfiltered (gdb_stdlog, - "target_insert_breakpoint (%s, xxx) = %ld\n", - core_addr_to_string (bp_tgt->placed_address), - (unsigned long) retval); - return retval; -} - -static int -debug_to_remove_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch, - struct bp_target_info *bp_tgt) -{ - int retval; - - retval = debug_target.to_remove_breakpoint (&debug_target, gdbarch, bp_tgt); - - fprintf_unfiltered (gdb_stdlog, - "target_remove_breakpoint (%s, xxx) = %ld\n", - core_addr_to_string (bp_tgt->placed_address), - (unsigned long) retval); - return retval; -} - -static int -debug_to_can_use_hw_breakpoint (struct target_ops *self, - int type, int cnt, int from_tty) -{ - int retval; - - retval = debug_target.to_can_use_hw_breakpoint (&debug_target, - type, cnt, from_tty); - - fprintf_unfiltered (gdb_stdlog, - "target_can_use_hw_breakpoint (%ld, %ld, %ld) = %ld\n", - (unsigned long) type, - (unsigned long) cnt, - (unsigned long) from_tty, - (unsigned long) retval); - return retval; -} - -static int -debug_to_region_ok_for_hw_watchpoint (struct target_ops *self, - CORE_ADDR addr, int len) -{ - CORE_ADDR retval; - - retval = debug_target.to_region_ok_for_hw_watchpoint (&debug_target, - addr, len); - - fprintf_unfiltered (gdb_stdlog, - "target_region_ok_for_hw_watchpoint (%s, %ld) = %s\n", - core_addr_to_string (addr), (unsigned long) len, - core_addr_to_string (retval)); - return retval; -} - -static int -debug_to_can_accel_watchpoint_condition (struct target_ops *self, - CORE_ADDR addr, int len, int rw, - struct expression *cond) -{ - int retval; - - retval = debug_target.to_can_accel_watchpoint_condition (&debug_target, - addr, len, - rw, cond); - - fprintf_unfiltered (gdb_stdlog, - "target_can_accel_watchpoint_condition " - "(%s, %d, %d, %s) = %ld\n", - core_addr_to_string (addr), len, rw, - host_address_to_string (cond), (unsigned long) retval); - return retval; -} - -static int -debug_to_stopped_by_watchpoint (struct target_ops *ops) -{ - int retval; - - retval = debug_target.to_stopped_by_watchpoint (&debug_target); - - fprintf_unfiltered (gdb_stdlog, - "target_stopped_by_watchpoint () = %ld\n", - (unsigned long) retval); - return retval; -} - -static int -debug_to_stopped_data_address (struct target_ops *target, CORE_ADDR *addr) -{ - int retval; - - retval = debug_target.to_stopped_data_address (target, addr); - - fprintf_unfiltered (gdb_stdlog, - "target_stopped_data_address ([%s]) = %ld\n", - core_addr_to_string (*addr), - (unsigned long)retval); - return retval; -} - -static int -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 (%s, %s, %d) = %d\n", - core_addr_to_string (addr), core_addr_to_string (start), - length, retval); - return retval; -} - -static int -debug_to_insert_hw_breakpoint (struct target_ops *self, - struct gdbarch *gdbarch, - struct bp_target_info *bp_tgt) -{ - int retval; - - retval = debug_target.to_insert_hw_breakpoint (&debug_target, - gdbarch, bp_tgt); - - fprintf_unfiltered (gdb_stdlog, - "target_insert_hw_breakpoint (%s, xxx) = %ld\n", - core_addr_to_string (bp_tgt->placed_address), - (unsigned long) retval); - return retval; -} - -static int -debug_to_remove_hw_breakpoint (struct target_ops *self, - struct gdbarch *gdbarch, - struct bp_target_info *bp_tgt) -{ - int retval; - - retval = debug_target.to_remove_hw_breakpoint (&debug_target, - gdbarch, bp_tgt); - - fprintf_unfiltered (gdb_stdlog, - "target_remove_hw_breakpoint (%s, xxx) = %ld\n", - core_addr_to_string (bp_tgt->placed_address), - (unsigned long) retval); - return retval; -} - -static int -debug_to_insert_watchpoint (struct target_ops *self, - CORE_ADDR addr, int len, int type, - struct expression *cond) -{ - int retval; - - retval = debug_target.to_insert_watchpoint (&debug_target, - addr, len, type, cond); - - fprintf_unfiltered (gdb_stdlog, - "target_insert_watchpoint (%s, %d, %d, %s) = %ld\n", - core_addr_to_string (addr), len, type, - host_address_to_string (cond), (unsigned long) retval); - return retval; -} - -static int -debug_to_remove_watchpoint (struct target_ops *self, - CORE_ADDR addr, int len, int type, - struct expression *cond) -{ - int retval; - - retval = debug_target.to_remove_watchpoint (&debug_target, - addr, len, type, cond); - - fprintf_unfiltered (gdb_stdlog, - "target_remove_watchpoint (%s, %d, %d, %s) = %ld\n", - core_addr_to_string (addr), len, type, - host_address_to_string (cond), (unsigned long) retval); - return retval; -} - -static void -debug_to_terminal_init (struct target_ops *self) -{ - debug_target.to_terminal_init (&debug_target); - - fprintf_unfiltered (gdb_stdlog, "target_terminal_init ()\n"); -} - -static void -debug_to_terminal_inferior (struct target_ops *self) -{ - debug_target.to_terminal_inferior (&debug_target); - - fprintf_unfiltered (gdb_stdlog, "target_terminal_inferior ()\n"); -} - -static void -debug_to_terminal_ours_for_output (struct target_ops *self) -{ - debug_target.to_terminal_ours_for_output (&debug_target); - - fprintf_unfiltered (gdb_stdlog, "target_terminal_ours_for_output ()\n"); -} - -static void -debug_to_terminal_ours (struct target_ops *self) -{ - debug_target.to_terminal_ours (&debug_target); - - fprintf_unfiltered (gdb_stdlog, "target_terminal_ours ()\n"); -} - -static void -debug_to_terminal_save_ours (struct target_ops *self) -{ - debug_target.to_terminal_save_ours (&debug_target); - - fprintf_unfiltered (gdb_stdlog, "target_terminal_save_ours ()\n"); -} - -static void -debug_to_terminal_info (struct target_ops *self, - const char *arg, int from_tty) -{ - debug_target.to_terminal_info (&debug_target, arg, from_tty); - - fprintf_unfiltered (gdb_stdlog, "target_terminal_info (%s, %d)\n", arg, - from_tty); -} - -static void -debug_to_load (struct target_ops *self, char *args, int from_tty) -{ - debug_target.to_load (&debug_target, args, from_tty); - - fprintf_unfiltered (gdb_stdlog, "target_load (%s, %d)\n", args, from_tty); -} - -static void -debug_to_post_startup_inferior (struct target_ops *self, ptid_t ptid) -{ - debug_target.to_post_startup_inferior (&debug_target, ptid); - - fprintf_unfiltered (gdb_stdlog, "target_post_startup_inferior (%d)\n", - ptid_get_pid (ptid)); -} - -static int -debug_to_insert_fork_catchpoint (struct target_ops *self, int pid) -{ - int retval; - - retval = debug_target.to_insert_fork_catchpoint (&debug_target, pid); - - fprintf_unfiltered (gdb_stdlog, "target_insert_fork_catchpoint (%d) = %d\n", - pid, retval); - - return retval; -} - -static int -debug_to_remove_fork_catchpoint (struct target_ops *self, int pid) -{ - int retval; - - retval = debug_target.to_remove_fork_catchpoint (&debug_target, pid); - - fprintf_unfiltered (gdb_stdlog, "target_remove_fork_catchpoint (%d) = %d\n", - pid, retval); - - return retval; -} - -static int -debug_to_insert_vfork_catchpoint (struct target_ops *self, int pid) -{ - int retval; - - retval = debug_target.to_insert_vfork_catchpoint (&debug_target, pid); - - fprintf_unfiltered (gdb_stdlog, "target_insert_vfork_catchpoint (%d) = %d\n", - pid, retval); - - return retval; -} - -static int -debug_to_remove_vfork_catchpoint (struct target_ops *self, int pid) -{ - int retval; - - retval = debug_target.to_remove_vfork_catchpoint (&debug_target, pid); - - fprintf_unfiltered (gdb_stdlog, "target_remove_vfork_catchpoint (%d) = %d\n", - pid, retval); - - return retval; + return current_target.to_decr_pc_after_break (¤t_target, gdbarch); } -static int -debug_to_insert_exec_catchpoint (struct target_ops *self, int pid) -{ - int retval; - - retval = debug_target.to_insert_exec_catchpoint (&debug_target, pid); - - fprintf_unfiltered (gdb_stdlog, "target_insert_exec_catchpoint (%d) = %d\n", - pid, retval); - - return retval; -} - -static int -debug_to_remove_exec_catchpoint (struct target_ops *self, int pid) -{ - int retval; - - retval = debug_target.to_remove_exec_catchpoint (&debug_target, pid); - - fprintf_unfiltered (gdb_stdlog, "target_remove_exec_catchpoint (%d) = %d\n", - pid, retval); - - return retval; -} - -static int -debug_to_has_exited (struct target_ops *self, - int pid, int wait_status, int *exit_status) -{ - int has_exited; - - has_exited = debug_target.to_has_exited (&debug_target, - pid, wait_status, exit_status); - - fprintf_unfiltered (gdb_stdlog, "target_has_exited (%d, %d, %d) = %d\n", - pid, wait_status, *exit_status, has_exited); - - return has_exited; -} - -static int -debug_to_can_run (struct target_ops *self) -{ - int retval; - - retval = debug_target.to_can_run (&debug_target); - - fprintf_unfiltered (gdb_stdlog, "target_can_run () = %d\n", retval); - - return retval; -} - -static struct gdbarch * -debug_to_thread_architecture (struct target_ops *ops, ptid_t ptid) -{ - struct gdbarch *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; -} +/* See target.h. */ -static void -debug_to_stop (struct target_ops *self, ptid_t ptid) +void +target_prepare_to_generate_core (void) { - debug_target.to_stop (&debug_target, ptid); - - fprintf_unfiltered (gdb_stdlog, "target_stop (%s)\n", - target_pid_to_str (ptid)); + current_target.to_prepare_to_generate_core (¤t_target); } -static void -debug_to_rcmd (struct target_ops *self, char *command, - struct ui_file *outbuf) -{ - debug_target.to_rcmd (&debug_target, command, outbuf); - fprintf_unfiltered (gdb_stdlog, "target_rcmd (%s, ...)\n", command); -} +/* See target.h. */ -static char * -debug_to_pid_to_exec_file (struct target_ops *self, int pid) +void +target_done_generating_core (void) { - char *exec_file; - - exec_file = debug_target.to_pid_to_exec_file (&debug_target, pid); - - fprintf_unfiltered (gdb_stdlog, "target_pid_to_exec_file (%d) = %s\n", - pid, exec_file); - - return exec_file; + current_target.to_done_generating_core (¤t_target); } static void @@ -4755,47 +3560,7 @@ setup_target_debug (void) { memcpy (&debug_target, ¤t_target, sizeof debug_target); - current_target.to_open = debug_to_open; - current_target.to_post_attach = debug_to_post_attach; - 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_insert_breakpoint = debug_to_insert_breakpoint; - current_target.to_remove_breakpoint = debug_to_remove_breakpoint; - current_target.to_can_use_hw_breakpoint = debug_to_can_use_hw_breakpoint; - current_target.to_insert_hw_breakpoint = debug_to_insert_hw_breakpoint; - current_target.to_remove_hw_breakpoint = debug_to_remove_hw_breakpoint; - current_target.to_insert_watchpoint = debug_to_insert_watchpoint; - 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_can_accel_watchpoint_condition - = debug_to_can_accel_watchpoint_condition; - current_target.to_terminal_init = debug_to_terminal_init; - current_target.to_terminal_inferior = debug_to_terminal_inferior; - current_target.to_terminal_ours_for_output - = debug_to_terminal_ours_for_output; - 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_load = debug_to_load; - current_target.to_post_startup_inferior = debug_to_post_startup_inferior; - current_target.to_insert_fork_catchpoint = debug_to_insert_fork_catchpoint; - current_target.to_remove_fork_catchpoint = debug_to_remove_fork_catchpoint; - current_target.to_insert_vfork_catchpoint = debug_to_insert_vfork_catchpoint; - current_target.to_remove_vfork_catchpoint = debug_to_remove_vfork_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_can_run = debug_to_can_run; - 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; + init_debug_target (¤t_target); } @@ -4805,7 +3570,8 @@ stack of targets currently in use (including the exec-file,\n\ core-file, and process, if any), as well as the symbol file name."; static void -default_rcmd (struct target_ops *self, char *command, struct ui_file *output) +default_rcmd (struct target_ops *self, const char *command, + struct ui_file *output) { error (_("\"monitor\" command not supported by this target.")); } @@ -4832,16 +3598,17 @@ maintenance_print_target_stack (char *cmd, int from_tty) } } -/* Controls if async mode is permitted. */ -int target_async_permitted = 0; +/* Controls if targets can report that they can/are async. This is + just for maintainers to use when debugging gdb. */ +int target_async_permitted = 1; /* The set command writes to this variable. If the inferior is executing, target_async_permitted is *not* updated. */ -static int target_async_permitted_1 = 0; +static int target_async_permitted_1 = 1; static void -set_target_async_command (char *args, int from_tty, - struct cmd_list_element *c) +maint_set_target_async_command (char *args, int from_tty, + struct cmd_list_element *c) { if (have_live_inferiors ()) { @@ -4853,9 +3620,9 @@ set_target_async_command (char *args, int from_tty, } static void -show_target_async_command (struct ui_file *file, int from_tty, - struct cmd_list_element *c, - const char *value) +maint_show_target_async_command (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *value) { fprintf_filtered (file, _("Controlling the inferior in " @@ -4931,9 +3698,8 @@ initialize_targets (void) Set target debugging."), _("\ Show target debugging."), _("\ When non-zero, target debugging is enabled. Higher numbers are more\n\ -verbose. Changes do not take effect until the next \"run\" or \"target\"\n\ -command."), - NULL, +verbose."), + set_targetdebug, show_targetdebug, &setdebuglist, &showdebuglist); @@ -4960,10 +3726,10 @@ result in significant performance improvement for remote targets."), 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_target_async_command, - show_target_async_command, - &setlist, - &showlist); + maint_set_target_async_command, + maint_show_target_async_command, + &maintenance_set_cmdlist, + &maintenance_show_cmdlist); add_setshow_boolean_cmd ("may-write-registers", class_support, &may_write_registers_1, _("\ @@ -5018,4 +3784,13 @@ When this permission is on, GDB may interrupt/stop the target's execution.\n\ Otherwise, any attempt to interrupt or stop will be ignored."), set_target_permissions, NULL, &setlist, &showlist); + + add_setshow_boolean_cmd ("auto-connect-native-target", class_support, + &auto_connect_native_target, _("\ +Set whether GDB may automatically connect to the native target."), _("\ +Show whether GDB may automatically connect to the native target."), _("\ +When on, and GDB is not connected to a target yet, GDB\n\ +attempts \"run\" and other commands with the native target."), + NULL, show_auto_connect_native_target, + &setlist, &showlist); }