X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Ftarget.c;h=fd0165a19ba9129011486db90892eb50cb445ccb;hb=430329a943352cb440b1075a1b753483985f74bf;hp=6abbd00e340328362b48e4266aa8cb57e2f291bd;hpb=a3ecbe7c52aebaf22ee74dde39964487d606bdb0;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/target.c b/gdb/target.c index 6abbd00e34..fd0165a19b 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1,26 +1,29 @@ /* Select target systems and architectures at runtime for GDB. - Copyright 1990, 1992, 1993, 1994 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001, 2002 + Free Software Foundation, Inc. Contributed by Cygnus Support. -This file is part of GDB. + This file is part of GDB. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ #include "defs.h" #include -#include +#include "gdb_string.h" #include "target.h" #include "gdbcmd.h" #include "symtab.h" @@ -28,49 +31,136 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "bfd.h" #include "symfile.h" #include "objfiles.h" -#include "wait.h" +#include "gdb_wait.h" +#include "dcache.h" #include +#include "regcache.h" extern int errno; -static void -target_info PARAMS ((char *, int)); +static void target_info (char *, int); -static void -cleanup_target PARAMS ((struct target_ops *)); +static void cleanup_target (struct target_ops *); -static void -maybe_kill_then_create_inferior PARAMS ((char *, char *, char **)); +static void maybe_kill_then_create_inferior (char *, char *, char **); -static void -maybe_kill_then_attach PARAMS ((char *, int)); +static void maybe_kill_then_attach (char *, int); -static void -kill_or_be_killed PARAMS ((int)); +static void kill_or_be_killed (int); -static void -default_terminal_info PARAMS ((char *, int)); +static void default_terminal_info (char *, int); -static int -nosymbol PARAMS ((char *, CORE_ADDR *)); +static int default_region_size_ok_for_hw_watchpoint (int); -static void -tcomplain PARAMS ((void)); +static int nosymbol (char *, CORE_ADDR *); -static int -nomemory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *)); +static void tcomplain (void); -static int -return_zero PARAMS ((void)); +static int nomemory (CORE_ADDR, char *, int, int, struct target_ops *); -static void -ignore PARAMS ((void)); +static int return_zero (void); -static void -target_command PARAMS ((char *, int)); +static int return_one (void); -static struct target_ops * -find_default_run_target PARAMS ((char *)); +static int return_minus_one (void); + +void target_ignore (void); + +static void target_command (char *, int); + +static struct target_ops *find_default_run_target (char *); + +static void update_current_target (void); + +static void nosupport_runtime (void); + +static void normal_target_post_startup_inferior (ptid_t ptid); + +/* Transfer LEN bytes between target address MEMADDR and GDB address + MYADDR. Returns 0 for success, errno code for failure (which + includes partial transfers -- if you want a more useful response to + partial transfers, try either target_read_memory_partial or + target_write_memory_partial). */ + +static int target_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, + int write); + +static void init_dummy_target (void); + +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 (int); + +static void debug_to_store_registers (int); + +static void debug_to_prepare_to_store (void); + +static int debug_to_xfer_memory (CORE_ADDR, char *, int, int, + struct mem_attrib *, struct target_ops *); + +static void debug_to_files_info (struct target_ops *); + +static int debug_to_insert_breakpoint (CORE_ADDR, char *); + +static int debug_to_remove_breakpoint (CORE_ADDR, char *); + +static int debug_to_can_use_hw_breakpoint (int, int, int); + +static int debug_to_insert_hw_breakpoint (CORE_ADDR, char *); + +static int debug_to_remove_hw_breakpoint (CORE_ADDR, char *); + +static int debug_to_insert_watchpoint (CORE_ADDR, int, int); + +static int debug_to_remove_watchpoint (CORE_ADDR, int, int); + +static int debug_to_stopped_by_watchpoint (void); + +static CORE_ADDR debug_to_stopped_data_address (void); + +static int debug_to_region_size_ok_for_hw_watchpoint (int); + +static void debug_to_terminal_init (void); + +static void debug_to_terminal_inferior (void); + +static void debug_to_terminal_ours_for_output (void); + +static void debug_to_terminal_save_ours (void); + +static void debug_to_terminal_ours (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_create_inferior (char *, char *, char **); + +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 int debug_to_query (int /*char */ , char *, char *, int *); /* Pointer to array of target architecture structures; the size of the array; the current index into the array; the allocated size of the @@ -84,25 +174,7 @@ unsigned target_struct_allocsize; /* The initial current target, so that there is always a semi-valid current target. */ -struct target_ops dummy_target = {"None", "None", "", - 0, 0, /* open, close */ - find_default_attach, 0, /* attach, detach */ - 0, 0, /* resume, wait */ - 0, 0, 0, /* registers */ - 0, 0, /* memory */ - 0, 0, /* bkpts */ - 0, 0, 0, 0, 0, /* terminal */ - 0, 0, /* kill, load */ - 0, /* lookup_symbol */ - find_default_create_inferior, /* create_inferior */ - 0, /* mourn_inferior */ - 0, /* can_run */ - 0, /* notice_signals */ - dummy_stratum, 0, /* stratum, next */ - 0, 0, 0, 0, 0, /* all mem, mem, stack, regs, exec */ - 0, 0, /* section pointers */ - OPS_MAGIC, -}; +static struct target_ops dummy_target; /* Top of target stack. */ @@ -122,13 +194,19 @@ static struct cmd_list_element *targetlist = NULL; int attach_flag; +/* Non-zero if we want to see trace of target level stuff. */ + +static int targetdebug = 0; + +static void setup_target_debug (void); + +DCACHE *target_dcache; + /* The user just typed 'target' without the name of a target. */ /* ARGSUSED */ static void -target_command (arg, from_tty) - char *arg; - int from_tty; +target_command (char *arg, int from_tty) { fputs_filtered ("Argument required (target name). Try `help target'\n", gdb_stdout); @@ -137,8 +215,7 @@ target_command (arg, from_tty) /* Add a possible target architecture to the list. */ void -add_target (t) - struct target_ops *t; +add_target (struct target_ops *t) { if (!target_structs) { @@ -150,11 +227,11 @@ add_target (t) { target_struct_allocsize *= 2; target_structs = (struct target_ops **) - xrealloc ((char *) target_structs, - target_struct_allocsize * sizeof (*target_structs)); + xrealloc ((char *) target_structs, + target_struct_allocsize * sizeof (*target_structs)); } target_structs[target_struct_size++] = t; -/* cleanup_target (t);*/ +/* cleanup_target (t); */ if (targetlist == NULL) add_prefix_cmd ("target", class_run, target_command, @@ -169,53 +246,63 @@ information on the arguments for a particular protocol, type\n\ /* Stub functions */ -static void -ignore () +void +target_ignore (void) +{ +} + +void +target_load (char *arg, int from_tty) { + dcache_invalidate (target_dcache); + (*current_target.to_load) (arg, from_tty); } /* ARGSUSED */ static int -nomemory (memaddr, myaddr, len, write, t) - CORE_ADDR memaddr; - char *myaddr; - int len; - int write; - struct target_ops *t; +nomemory (CORE_ADDR memaddr, char *myaddr, int len, int write, + struct target_ops *t) { - errno = EIO; /* Can't read/write this location */ - return 0; /* No bytes handled */ + errno = EIO; /* Can't read/write this location */ + return 0; /* No bytes handled */ } static void -tcomplain () +tcomplain (void) { error ("You can't do that when your target is `%s'", current_target.to_shortname); } void -noprocess () +noprocess (void) { - error ("You can't do that without a process to debug"); + error ("You can't do that without a process to debug."); } /* ARGSUSED */ static int -nosymbol (name, addrp) - char *name; - CORE_ADDR *addrp; +nosymbol (char *name, CORE_ADDR *addrp) +{ + return 1; /* Symbol does not exist in target env */ +} + +/* ARGSUSED */ +static void +nosupport_runtime (void) { - return 1; /* Symbol does not exist in target env */ + if (ptid_equal (inferior_ptid, null_ptid)) + noprocess (); + else + error ("No run-time support for this"); } + /* ARGSUSED */ static void -default_terminal_info (args, from_tty) - char *args; - int from_tty; +default_terminal_info (char *args, int from_tty) { - printf_unfiltered("No saved terminal information.\n"); + printf_unfiltered ("No saved terminal information.\n"); } /* This is the default target_create_inferior and target_attach function. @@ -224,39 +311,36 @@ default_terminal_info (args, from_tty) the target, and the operation should be attempted. */ static void -kill_or_be_killed (from_tty) - int from_tty; +kill_or_be_killed (int from_tty) { if (target_has_execution) { printf_unfiltered ("You are already running a program:\n"); target_files_info (); - if (query ("Kill it? ")) { - target_kill (); - if (target_has_execution) - error ("Killing the program did not help."); - return; - } else { - error ("Program not killed."); - } + if (query ("Kill it? ")) + { + target_kill (); + if (target_has_execution) + error ("Killing the program did not help."); + return; + } + else + { + error ("Program not killed."); + } } - tcomplain(); + tcomplain (); } static void -maybe_kill_then_attach (args, from_tty) - char *args; - int from_tty; +maybe_kill_then_attach (char *args, int from_tty) { kill_or_be_killed (from_tty); target_attach (args, from_tty); } static void -maybe_kill_then_create_inferior (exec, args, env) - char *exec; - char *args; - char **env; +maybe_kill_then_create_inferior (char *exec, char *args, char **env) { kill_or_be_killed (0); target_create_inferior (exec, args, env); @@ -266,41 +350,180 @@ maybe_kill_then_create_inferior (exec, args, env) We default entries, at least to stubs that print error messages. */ static void -cleanup_target (t) - struct target_ops *t; +cleanup_target (struct target_ops *t) { #define de_fault(field, value) \ - if (!t->field) t->field = value - - /* FIELD DEFAULT VALUE */ - - de_fault (to_open, (void (*)())tcomplain); - de_fault (to_close, (void (*)())ignore); - de_fault (to_attach, maybe_kill_then_attach); - de_fault (to_detach, (void (*)())ignore); - de_fault (to_resume, (void (*)())noprocess); - de_fault (to_wait, (int (*)())noprocess); - de_fault (to_fetch_registers, (void (*)())ignore); - de_fault (to_store_registers, (void (*)())noprocess); - de_fault (to_prepare_to_store, (void (*)())noprocess); - de_fault (to_xfer_memory, (int (*)())nomemory); - de_fault (to_files_info, (void (*)())ignore); - de_fault (to_insert_breakpoint, memory_insert_breakpoint); - de_fault (to_remove_breakpoint, memory_remove_breakpoint); - de_fault (to_terminal_init, ignore); - de_fault (to_terminal_inferior, ignore); - de_fault (to_terminal_ours_for_output,ignore); - de_fault (to_terminal_ours, ignore); - de_fault (to_terminal_info, default_terminal_info); - de_fault (to_kill, (void (*)())noprocess); - de_fault (to_load, (void (*)())tcomplain); - de_fault (to_lookup_symbol, nosymbol); - de_fault (to_create_inferior, maybe_kill_then_create_inferior); - de_fault (to_mourn_inferior, (void (*)())noprocess); - de_fault (to_can_run, return_zero); - de_fault (to_notice_signals, (void (*)())ignore); - + if (!t->field) \ + t->field = value + + de_fault (to_open, + (void (*) (char *, int)) + tcomplain); + 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_post_wait, + (void (*) (ptid_t, int)) + target_ignore); + de_fault (to_fetch_registers, + (void (*) (int)) + target_ignore); + de_fault (to_store_registers, + (void (*) (int)) + noprocess); + de_fault (to_prepare_to_store, + (void (*) (void)) + noprocess); + de_fault (to_xfer_memory, + (int (*) (CORE_ADDR, char *, int, int, struct mem_attrib *, struct target_ops *)) + nomemory); + de_fault (to_files_info, + (void (*) (struct target_ops *)) + target_ignore); + de_fault (to_insert_breakpoint, + memory_insert_breakpoint); + de_fault (to_remove_breakpoint, + memory_remove_breakpoint); + de_fault (to_can_use_hw_breakpoint, + (int (*) (int, int, int)) + return_zero); + de_fault (to_insert_hw_breakpoint, + (int (*) (CORE_ADDR, char *)) + return_minus_one); + de_fault (to_remove_hw_breakpoint, + (int (*) (CORE_ADDR, char *)) + return_minus_one); + de_fault (to_insert_watchpoint, + (int (*) (CORE_ADDR, int, int)) + return_minus_one); + de_fault (to_remove_watchpoint, + (int (*) (CORE_ADDR, int, int)) + return_minus_one); + de_fault (to_stopped_by_watchpoint, + (int (*) (void)) + return_zero); + de_fault (to_stopped_data_address, + (CORE_ADDR (*) (void)) + return_zero); + de_fault (to_region_size_ok_for_hw_watchpoint, + default_region_size_ok_for_hw_watchpoint); + de_fault (to_terminal_init, + (void (*) (void)) + target_ignore); + de_fault (to_terminal_inferior, + (void (*) (void)) + target_ignore); + de_fault (to_terminal_ours_for_output, + (void (*) (void)) + target_ignore); + de_fault (to_terminal_ours, + (void (*) (void)) + target_ignore); + de_fault (to_terminal_save_ours, + (void (*) (void)) + 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_acknowledge_created_inferior, + (void (*) (int)) + target_ignore); + de_fault (to_insert_fork_catchpoint, + (int (*) (int)) + tcomplain); + de_fault (to_remove_fork_catchpoint, + (int (*) (int)) + tcomplain); + de_fault (to_insert_vfork_catchpoint, + (int (*) (int)) + tcomplain); + de_fault (to_remove_vfork_catchpoint, + (int (*) (int)) + tcomplain); + de_fault (to_follow_fork, + (int (*) (int)) + target_ignore); + de_fault (to_insert_exec_catchpoint, + (int (*) (int)) + tcomplain); + de_fault (to_remove_exec_catchpoint, + (int (*) (int)) + tcomplain); + de_fault (to_reported_exec_events_per_exec_call, + (int (*) (void)) + return_one); + 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)) + target_ignore); + de_fault (to_rcmd, + (void (*) (char *, struct ui_file *)) + tcomplain); + de_fault (to_enable_exception_callback, + (struct symtab_and_line * (*) (enum exception_event_kind, int)) + nosupport_runtime); + de_fault (to_get_current_exception_event, + (struct exception_event_record * (*) (void)) + nosupport_runtime); + 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); #undef de_fault } @@ -309,7 +532,7 @@ cleanup_target (t) pushed target vectors. */ static void -update_current_target () +update_current_target (void) { struct target_stack_item *item; struct target_ops *t; @@ -331,9 +554,11 @@ update_current_target () INHERIT (to_open, t); INHERIT (to_close, t); INHERIT (to_attach, t); + INHERIT (to_post_attach, t); INHERIT (to_detach, t); INHERIT (to_resume, t); INHERIT (to_wait, t); + INHERIT (to_post_wait, t); INHERIT (to_fetch_registers, t); INHERIT (to_store_registers, t); INHERIT (to_prepare_to_store, t); @@ -341,27 +566,65 @@ update_current_target () INHERIT (to_files_info, t); INHERIT (to_insert_breakpoint, t); INHERIT (to_remove_breakpoint, t); + INHERIT (to_can_use_hw_breakpoint, t); + INHERIT (to_insert_hw_breakpoint, t); + INHERIT (to_remove_hw_breakpoint, 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_continuable_watchpoint, t); + INHERIT (to_region_size_ok_for_hw_watchpoint, t); INHERIT (to_terminal_init, t); INHERIT (to_terminal_inferior, t); INHERIT (to_terminal_ours_for_output, t); INHERIT (to_terminal_ours, t); + INHERIT (to_terminal_save_ours, t); INHERIT (to_terminal_info, t); INHERIT (to_kill, t); INHERIT (to_load, t); INHERIT (to_lookup_symbol, t); INHERIT (to_create_inferior, t); + INHERIT (to_post_startup_inferior, t); + INHERIT (to_acknowledge_created_inferior, t); + INHERIT (to_insert_fork_catchpoint, t); + INHERIT (to_remove_fork_catchpoint, t); + INHERIT (to_insert_vfork_catchpoint, t); + INHERIT (to_remove_vfork_catchpoint, t); + INHERIT (to_follow_fork, t); + INHERIT (to_insert_exec_catchpoint, t); + INHERIT (to_remove_exec_catchpoint, t); + INHERIT (to_reported_exec_events_per_exec_call, t); + INHERIT (to_has_exited, t); INHERIT (to_mourn_inferior, t); 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); + INHERIT (to_extra_thread_info, t); + INHERIT (to_stop, t); + INHERIT (to_query, t); + INHERIT (to_rcmd, t); + INHERIT (to_enable_exception_callback, t); + INHERIT (to_get_current_exception_event, t); + INHERIT (to_pid_to_exec_file, t); INHERIT (to_stratum, t); - INHERIT (DONT_USE, t); INHERIT (to_has_all_memory, t); INHERIT (to_has_memory, t); INHERIT (to_has_stack, t); INHERIT (to_has_registers, t); INHERIT (to_has_execution, t); + INHERIT (to_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_find_memory_regions, t); + INHERIT (to_make_corefile_notes, t); + INHERIT (to_get_thread_local_address, t); INHERIT (to_magic, t); #undef INHERIT @@ -379,8 +642,7 @@ update_current_target () checking them. */ int -push_target (t) - struct target_ops *t; +push_target (struct target_ops *t) { struct target_stack_item *cur, *prev, *tmp; @@ -388,17 +650,17 @@ push_target (t) the struct definition, but not all the places that initialize one. */ if (t->to_magic != OPS_MAGIC) { - fprintf_unfiltered(gdb_stderr, - "Magic number of %s target struct wrong\n", - t->to_shortname); - abort(); + fprintf_unfiltered (gdb_stderr, + "Magic number of %s target struct wrong\n", + t->to_shortname); + internal_error (__FILE__, __LINE__, "failed internal consistency check"); } /* Find the proper stratum to install this target in. */ for (prev = NULL, cur = target_stack; cur; prev = cur, cur = cur->next) { - if ((int)(t->to_stratum) >= (int)(cur->target_ops->to_stratum)) + if ((int) (t->to_stratum) >= (int) (cur->target_ops->to_stratum)) break; } @@ -408,13 +670,14 @@ push_target (t) while (t->to_stratum == cur->target_ops->to_stratum) { /* There's already something on this stratum. Close it off. */ - (cur->target_ops->to_close) (0); + if (cur->target_ops->to_close) + (cur->target_ops->to_close) (0); if (prev) - prev->next = cur->next; /* Unchain old target_ops */ + prev->next = cur->next; /* Unchain old target_ops */ else - target_stack = cur->next; /* Unchain first on list */ + target_stack = cur->next; /* Unchain first on list */ tmp = cur->next; - free (cur); + xfree (cur); cur = tmp; } @@ -432,7 +695,11 @@ push_target (t) update_current_target (); - cleanup_target (¤t_target); /* Fill in the gaps */ + cleanup_target (¤t_target); /* Fill in the gaps */ + + if (targetdebug) + setup_target_debug (); + return prev != 0; } @@ -440,8 +707,7 @@ push_target (t) Return how many times it was removed (0 or 1). */ int -unpush_target (t) - struct target_ops *t; +unpush_target (struct target_ops *t) { struct target_stack_item *cur, *prev; @@ -465,7 +731,7 @@ unpush_target (t) else prev->next = cur->next; - free (cur); /* Release the target_stack_item */ + xfree (cur); /* Release the target_stack_item */ update_current_target (); cleanup_target (¤t_target); @@ -474,16 +740,16 @@ unpush_target (t) } void -pop_target () +pop_target (void) { - (current_target.to_close)(0); /* Let it clean up */ + (current_target.to_close) (0); /* Let it clean up */ if (unpush_target (target_stack->target_ops) == 1) return; - fprintf_unfiltered(gdb_stderr, - "pop_target couldn't find target %s\n", - current_target.to_shortname); - abort(); + fprintf_unfiltered (gdb_stderr, + "pop_target couldn't find target %s\n", + current_target.to_shortname); + internal_error (__FILE__, __LINE__, "failed internal consistency check"); } #undef MIN @@ -496,11 +762,7 @@ pop_target () read. */ int -target_read_string (memaddr, string, len, errnop) - CORE_ADDR memaddr; - char **string; - int len; - int *errnop; +target_read_string (CORE_ADDR memaddr, char **string, int len, int *errnop) { int tlen, origlen, offset, i; char buf[4]; @@ -524,7 +786,16 @@ target_read_string (memaddr, string, len, errnop) errcode = target_xfer_memory (memaddr & ~3, buf, 4, 0); if (errcode != 0) - goto done; + { + /* The transfer request might have crossed the boundary to an + unallocated region of memory. Retry the transfer, requesting + a single byte. */ + tlen = 1; + offset = 0; + errcode = target_xfer_memory (memaddr, buf, 1, 0); + if (errcode != 0) + goto done; + } if (bufptr - buffer + tlen > buffer_allocated) { @@ -549,7 +820,7 @@ target_read_string (memaddr, string, len, errnop) len -= tlen; nbytes_read += tlen; } - done: +done: if (errnop != NULL) *errnop = errcode; if (string != NULL) @@ -568,111 +839,75 @@ target_read_string (memaddr, string, len, errnop) deal with partial reads should call target_read_memory_partial. */ int -target_read_memory (memaddr, myaddr, len) - CORE_ADDR memaddr; - char *myaddr; - int len; +target_read_memory (CORE_ADDR memaddr, char *myaddr, int len) { return target_xfer_memory (memaddr, myaddr, len, 0); } -/* Read LEN bytes of target memory at address MEMADDR, placing the results - in GDB's memory at MYADDR. Returns a count of the bytes actually read, - and optionally an errno value in the location pointed to by ERRNOPTR - if ERRNOPTR is non-null. */ - -int -target_read_memory_partial (memaddr, myaddr, len, errnoptr) - CORE_ADDR memaddr; - char *myaddr; - int len; - int *errnoptr; -{ - int nread; /* Number of bytes actually read. */ - int errcode; /* Error from last read. */ - - /* First try a complete read. */ - errcode = target_xfer_memory (memaddr, myaddr, len, 0); - if (errcode == 0) - { - /* Got it all. */ - nread = len; - } - else - { - /* Loop, reading one byte at a time until we get as much as we can. */ - for (errcode = 0, nread = 0; len > 0 && errcode == 0; nread++, len--) - { - errcode = target_xfer_memory (memaddr++, myaddr++, 1, 0); - } - /* If an error, the last read was unsuccessful, so adjust count. */ - if (errcode != 0) - { - nread--; - } - } - if (errnoptr != NULL) - { - *errnoptr = errcode; - } - return (nread); -} - int -target_write_memory (memaddr, myaddr, len) - CORE_ADDR memaddr; - char *myaddr; - int len; +target_write_memory (CORE_ADDR memaddr, char *myaddr, int len) { return target_xfer_memory (memaddr, myaddr, len, 1); } - -/* Move memory to or from the targets. Iterate until all of it has - been moved, if necessary. The top target gets priority; anything - it doesn't want, is offered to the next one down, etc. Note the - business with curlen: if an early target says "no, but I have a - boundary overlapping this xfer" then we shorten what we offer to - the subsequent targets so the early guy will get a chance at the - tail before the subsequent ones do. - Result is 0 or errno value. */ +static int trust_readonly = 0; + +/* Move memory to or from the targets. The top target gets priority; + if it cannot handle it, it is offered to the next one down, etc. + + Result is -1 on error, or the number of bytes transfered. */ int -target_xfer_memory (memaddr, myaddr, len, write) - CORE_ADDR memaddr; - char *myaddr; - int len; - int write; +do_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, + struct mem_attrib *attrib) { - int curlen; int res; + int done = 0; struct target_ops *t; struct target_stack_item *item; + /* Zero length requests are ok and require no work. */ + if (len == 0) + return 0; + /* to_xfer_memory is not guaranteed to set errno, even when it returns 0. */ errno = 0; - /* The quick case is that the top target does it all. */ - res = current_target.to_xfer_memory - (memaddr, myaddr, len, write, ¤t_target); - if (res == len) - return 0; + if (!write && trust_readonly) + { + /* User-settable option, "trust-readonly-sections". If true, + then memory from any SEC_READONLY bfd section may be read + directly from the bfd file. */ + + struct section_table *secp; + + for (secp = current_target.to_sections; + secp < current_target.to_sections_end; + secp++) + { + if (bfd_get_section_flags (secp->bfd, secp->the_bfd_section) + & SEC_READONLY) + if (memaddr >= secp->addr && memaddr < secp->endaddr) + return xfer_memory (memaddr, myaddr, len, 0, + attrib, ¤t_target); + } + } - if (res > 0) - goto bump; - /* If res <= 0 then we call it again in the loop. Ah well. */ + /* The quick case is that the top target can handle the transfer. */ + res = current_target.to_xfer_memory + (memaddr, myaddr, len, write, attrib, ¤t_target); - for (; len > 0;) + /* If res <= 0 then we call it again in the loop. Ah well. */ + if (res <= 0) { - curlen = len; /* Want to do it all */ for (item = target_stack; item; item = item->next) { t = item->target_ops; if (!t->to_has_memory) continue; - res = t->to_xfer_memory (memaddr, myaddr, curlen, write, t); + res = t->to_xfer_memory (memaddr, myaddr, len, write, attrib, t); if (res > 0) break; /* Handled all or part of xfer */ if (t->to_has_all_memory) @@ -680,35 +915,170 @@ target_xfer_memory (memaddr, myaddr, len, write) } if (res <= 0) + return -1; + } + + return res; +} + + +/* Perform a memory transfer. Iterate until the entire region has + been transfered. + + Result is 0 or errno value. */ + +static int +target_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write) +{ + int res; + int reg_len; + struct mem_region *region; + + /* Zero length requests are ok and require no work. */ + if (len == 0) + { + return 0; + } + + while (len > 0) + { + region = lookup_mem_region(memaddr); + if (memaddr + len < region->hi) + reg_len = len; + else + reg_len = region->hi - memaddr; + + switch (region->attrib.mode) { - /* If this address is for nonexistent memory, - read zeros if reading, or do nothing if writing. Return error. */ + case MEM_RO: + if (write) + return EIO; + break; + + case MEM_WO: if (!write) - memset (myaddr, 0, len); - if (errno == 0) return EIO; + break; + } + + while (reg_len > 0) + { + if (region->attrib.cache) + res = dcache_xfer_memory (target_dcache, memaddr, myaddr, + reg_len, write); else - return errno; + res = do_xfer_memory (memaddr, myaddr, reg_len, write, + ®ion->attrib); + + if (res <= 0) + { + /* If this address is for nonexistent memory, read zeros + if reading, or do nothing if writing. Return + error. */ + if (!write) + memset (myaddr, 0, len); + if (errno == 0) + return EIO; + else + return errno; + } + + memaddr += res; + myaddr += res; + len -= res; + reg_len -= res; } -bump: - memaddr += res; - myaddr += res; - len -= res; } + return 0; /* We managed to cover it all somehow. */ } +/* Perform a partial memory transfer. + + Result is -1 on error, or the number of bytes transfered. */ + +static int +target_xfer_memory_partial (CORE_ADDR memaddr, char *myaddr, int len, + int write_p, int *err) +{ + int res; + int reg_len; + struct mem_region *region; + + /* Zero length requests are ok and require no work. */ + if (len == 0) + { + *err = 0; + return 0; + } + + region = lookup_mem_region(memaddr); + if (memaddr + len < region->hi) + reg_len = len; + else + reg_len = region->hi - memaddr; + + switch (region->attrib.mode) + { + case MEM_RO: + if (write_p) + { + *err = EIO; + return -1; + } + break; + + case MEM_WO: + if (write_p) + { + *err = EIO; + return -1; + } + break; + } + + if (region->attrib.cache) + res = dcache_xfer_memory (target_dcache, memaddr, myaddr, + reg_len, write_p); + else + res = do_xfer_memory (memaddr, myaddr, reg_len, write_p, + ®ion->attrib); + + if (res <= 0) + { + if (errno != 0) + *err = errno; + else + *err = EIO; + + return -1; + } + + *err = 0; + return res; +} + +int +target_read_memory_partial (CORE_ADDR memaddr, char *buf, int len, int *err) +{ + return target_xfer_memory_partial (memaddr, buf, len, 0, err); +} + +int +target_write_memory_partial (CORE_ADDR memaddr, char *buf, int len, int *err) +{ + return target_xfer_memory_partial (memaddr, buf, len, 1, err); +} + /* ARGSUSED */ static void -target_info (args, from_tty) - char *args; - int from_tty; +target_info (char *args, int from_tty) { struct target_ops *t; struct target_stack_item *item; int has_all_mem = 0; - + if (symfile_objfile != NULL) printf_unfiltered ("Symbols from \"%s\".\n", symfile_objfile->name); @@ -724,12 +1094,12 @@ target_info (args, from_tty) if (!t->to_has_memory) continue; - if ((int)(t->to_stratum) <= (int)dummy_stratum) + if ((int) (t->to_stratum) <= (int) dummy_stratum) continue; if (has_all_mem) - printf_unfiltered("\tWhile running this, GDB does not access memory from...\n"); - printf_unfiltered("%s:\n", t->to_longname); - (t->to_files_info)(t); + 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; } } @@ -738,17 +1108,17 @@ target_info (args, from_tty) anything. */ void -target_preopen (from_tty) - int from_tty; +target_preopen (int from_tty) { - dont_repeat(); + dont_repeat (); if (target_has_execution) - { - if (query ("A program is being debugged already. Kill it? ")) - target_kill (); + { + if (!from_tty + || query ("A program is being debugged already. Kill it? ")) + target_kill (); else - error ("Program not killed."); + error ("Program not killed."); } /* Calling target_kill may remove the target from the stack. But if @@ -761,9 +1131,7 @@ target_preopen (from_tty) /* Detach a target after doing deferred register stores. */ void -target_detach (args, from_tty) - char *args; - int from_tty; +target_detach (char *args, int from_tty) { /* Handle any optimized stores to the inferior. */ #ifdef DO_DEFERRED_STORES @@ -773,18 +1141,24 @@ target_detach (args, from_tty) } void -target_link (modname, t_reloc) - char *modname; - CORE_ADDR *t_reloc; +target_link (char *modname, CORE_ADDR *t_reloc) { - if (STREQ(current_target.to_shortname, "rombug")) + if (STREQ (current_target.to_shortname, "rombug")) { (current_target.to_lookup_symbol) (modname, t_reloc); if (*t_reloc == 0) - error("Unable to link to %s and get relocation in rombug", modname); + error ("Unable to link to %s and get relocation in rombug", modname); } else - *t_reloc = (CORE_ADDR)-1; + *t_reloc = (CORE_ADDR) -1; +} + +int +target_async_mask (int mask) +{ + int saved_async_masked_status = target_async_mask_value; + target_async_mask_value = mask; + return saved_async_masked_status; } /* Look through the list of possible targets for a target that can @@ -794,8 +1168,7 @@ target_link (modname, t_reloc) Result is always valid (error() is called for errors). */ static struct target_ops * -find_default_run_target (do_mesg) - char *do_mesg; +find_default_run_target (char *do_mesg) { struct target_ops **t; struct target_ops *runable = NULL; @@ -806,7 +1179,7 @@ find_default_run_target (do_mesg) for (t = target_structs; t < target_structs + target_struct_size; ++t) { - if (target_can_run(*t)) + if ((*t)->to_can_run && target_can_run (*t)) { runable = *t; ++count; @@ -820,492 +1193,237 @@ find_default_run_target (do_mesg) } void -find_default_attach (args, from_tty) - char *args; - int from_tty; +find_default_attach (char *args, int from_tty) { struct target_ops *t; - t = find_default_run_target("attach"); + t = find_default_run_target ("attach"); (t->to_attach) (args, from_tty); return; } void -find_default_create_inferior (exec_file, allargs, env) - char *exec_file; - char *allargs; - char **env; +find_default_create_inferior (char *exec_file, char *allargs, char **env) { struct target_ops *t; - t = find_default_run_target("run"); + t = find_default_run_target ("run"); (t->to_create_inferior) (exec_file, allargs, env); return; } static int -return_zero () +default_region_size_ok_for_hw_watchpoint (int byte_count) +{ + return (byte_count <= DEPRECATED_REGISTER_SIZE); +} + +static int +return_zero (void) { return 0; } -struct target_ops * -find_core_target () +static int +return_one (void) +{ + return 1; +} + +static int +return_minus_one (void) +{ + return -1; +} + +/* + * 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) { struct target_ops **t; - struct target_ops *runable = NULL; - int count; - - count = 0; - - for (t = target_structs; t < target_structs + target_struct_size; - ++t) + struct section_table *old_value; + int old_count; + + old_value = target->to_sections; + + if (target->to_sections) { - if ((*t)->to_stratum == core_stratum) + 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)); + } + 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); + + /* Check to see if anyone else was pointing to this structure. + If old_value was null, then no one was. */ + + if (old_value) + { + for (t = target_structs; t < target_structs + target_struct_size; + ++t) { - runable = *t; - ++count; + if ((*t)->to_sections == old_value) + { + (*t)->to_sections = target->to_sections; + (*t)->to_sections_end = target->to_sections_end; + } } } - return(count == 1 ? runable : NULL); + return old_count; + } - -/* The inferior process has died. Long live the inferior! */ +/* Remove all target sections taken from ABFD. + + 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 -generic_mourn_inferior () +remove_target_sections (bfd *abfd) { - extern int show_breakpoint_hit_counts; + struct target_ops **t; - inferior_pid = 0; - attach_flag = 0; - breakpoint_init_inferior (); - registers_changed (); + 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); + } +} -#ifdef CLEAR_DEFERRED_STORES - /* Delete any pending stores to the inferior... */ - CLEAR_DEFERRED_STORES; -#endif - reopen_exec_file (); - reinit_frame_cache (); - /* It is confusing to the user for ignore counts to stick around - from previous runs of the inferior. So clear them. */ - /* However, it is more confusing for the ignore counts to disappear when - using hit counts. So don't clear them if we're counting hits. */ - if (!show_breakpoint_hit_counts) - breakpoint_clear_ignore_counts (); -} - -/* This table must match in order and size the signals in enum target_signal - in target.h. */ -static struct { - char *name; - char *string; - } signals [] = -{ - {"0", "Signal 0"}, - {"SIGHUP", "Hangup"}, - {"SIGINT", "Interrupt"}, - {"SIGQUIT", "Quit"}, - {"SIGILL", "Illegal instruction"}, - {"SIGTRAP", "Trace/breakpoint trap"}, - {"SIGABRT", "Aborted"}, - {"SIGEMT", "Emulation trap"}, - {"SIGFPE", "Arithmetic exception"}, - {"SIGKILL", "Killed"}, - {"SIGBUS", "Bus error"}, - {"SIGSEGV", "Segmentation fault"}, - {"SIGSYS", "Bad system call"}, - {"SIGPIPE", "Broken pipe"}, - {"SIGALRM", "Alarm clock"}, - {"SIGTERM", "Terminated"}, - {"SIGURG", "Urgent I/O condition"}, - {"SIGSTOP", "Stopped (signal)"}, - {"SIGTSTP", "Stopped (user)"}, - {"SIGCONT", "Continued"}, - {"SIGCHLD", "Child status changed"}, - {"SIGTTIN", "Stopped (tty input)"}, - {"SIGTTOU", "Stopped (tty output)"}, - {"SIGIO", "I/O possible"}, - {"SIGXCPU", "CPU time limit exceeded"}, - {"SIGXFSZ", "File size limit exceeded"}, - {"SIGVTALRM", "Virtual timer expired"}, - {"SIGPROF", "Profiling timer expired"}, - {"SIGWINCH", "Window size changed"}, - {"SIGLOST", "Resource lost"}, - {"SIGUSR1", "User defined signal 1"}, - {"SIGUSR2", "User defined signal 2"}, - {"SIGPWR", "Power fail/restart"}, - {"SIGPOLL", "Pollable event occurred"}, - {"SIGWIND", "SIGWIND"}, - {"SIGPHONE", "SIGPHONE"}, - {"SIGWAITING", "Process's LWPs are blocked"}, - {"SIGLWP", "Signal LWP"}, - {"SIGDANGER", "Swap space dangerously low"}, - {"SIGGRANT", "Monitor mode granted"}, - {"SIGRETRACT", "Need to relinguish monitor mode"}, - {"SIGMSG", "Monitor mode data available"}, - {"SIGSOUND", "Sound completed"}, - {"SIGSAK", "Secure attention"}, - {NULL, "Unknown signal"}, - {NULL, "Internal error: printing TARGET_SIGNAL_DEFAULT"}, - - /* Last entry, used to check whether the table is the right size. */ - {NULL, "TARGET_SIGNAL_MAGIC"} -}; - -/* Return the string for a signal. */ -char * -target_signal_to_string (sig) - enum target_signal sig; + +/* Find a single runnable target in the stack and return it. If for + some reason there is more than one, return NULL. */ + +struct target_ops * +find_run_target (void) { - return signals[sig].string; + 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 ((*t)->to_can_run && target_can_run (*t)) + { + runable = *t; + ++count; + } + } + + return (count == 1 ? runable : NULL); } -/* Return the name for a signal. */ -char * -target_signal_to_name (sig) - enum target_signal sig; +/* Find a single core_stratum target in the list of targets and return it. + If for some reason there is more than one, return NULL. */ + +struct target_ops * +find_core_target (void) { - if (sig == TARGET_SIGNAL_UNKNOWN) - /* I think the code which prints this will always print it along with - the string, so no need to be verbose. */ - return "?"; - return signals[sig].name; + 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 ((*t)->to_stratum == core_stratum) + { + runable = *t; + ++count; + } + } + + return (count == 1 ? runable : NULL); } -/* Given a name, return its signal. */ -enum target_signal -target_signal_from_name (name) - char *name; +/* + * Find the next target down the stack from the specified target. + */ + +struct target_ops * +find_target_beneath (struct target_ops *t) { - enum target_signal sig; + struct target_stack_item *cur; - /* It's possible we also should allow "SIGCLD" as well as "SIGCHLD" - for TARGET_SIGNAL_SIGCHLD. SIGIOT, on the other hand, is more - questionable; seems like by now people should call it SIGABRT - instead. */ + for (cur = target_stack; cur; cur = cur->next) + if (cur->target_ops == t) + break; - /* This ugly cast brought to you by the native VAX compiler. */ - for (sig = TARGET_SIGNAL_HUP; - signals[sig].name != NULL; - sig = (enum target_signal)((int)sig + 1)) - if (STREQ (name, signals[sig].name)) - return sig; - return TARGET_SIGNAL_UNKNOWN; + if (cur == NULL || cur->next == NULL) + return NULL; + else + return cur->next->target_ops; } + -/* The following functions are to help certain targets deal - with the signal/waitstatus stuff. They could just as well be in - a file called native-utils.c or unixwaitstatus-utils.c or whatever. */ +/* The inferior process has died. Long live the inferior! */ -/* Convert host signal to our signals. */ -enum target_signal -target_signal_from_host (hostsig) - int hostsig; +void +generic_mourn_inferior (void) { - /* A switch statement would make sense but would require special kludges - to deal with the cases where more than one signal has the same number. */ + extern int show_breakpoint_hit_counts; - if (hostsig == 0) return TARGET_SIGNAL_0; + inferior_ptid = null_ptid; + attach_flag = 0; + breakpoint_init_inferior (inf_exited); + registers_changed (); -#if defined (SIGHUP) - if (hostsig == SIGHUP) return TARGET_SIGNAL_HUP; -#endif -#if defined (SIGINT) - if (hostsig == SIGINT) return TARGET_SIGNAL_INT; -#endif -#if defined (SIGQUIT) - if (hostsig == SIGQUIT) return TARGET_SIGNAL_QUIT; -#endif -#if defined (SIGILL) - if (hostsig == SIGILL) return TARGET_SIGNAL_ILL; -#endif -#if defined (SIGTRAP) - if (hostsig == SIGTRAP) return TARGET_SIGNAL_TRAP; -#endif -#if defined (SIGABRT) - if (hostsig == SIGABRT) return TARGET_SIGNAL_ABRT; -#endif -#if defined (SIGEMT) - if (hostsig == SIGEMT) return TARGET_SIGNAL_EMT; -#endif -#if defined (SIGFPE) - if (hostsig == SIGFPE) return TARGET_SIGNAL_FPE; -#endif -#if defined (SIGKILL) - if (hostsig == SIGKILL) return TARGET_SIGNAL_KILL; -#endif -#if defined (SIGBUS) - if (hostsig == SIGBUS) return TARGET_SIGNAL_BUS; -#endif -#if defined (SIGSEGV) - if (hostsig == SIGSEGV) return TARGET_SIGNAL_SEGV; -#endif -#if defined (SIGSYS) - if (hostsig == SIGSYS) return TARGET_SIGNAL_SYS; -#endif -#if defined (SIGPIPE) - if (hostsig == SIGPIPE) return TARGET_SIGNAL_PIPE; -#endif -#if defined (SIGALRM) - if (hostsig == SIGALRM) return TARGET_SIGNAL_ALRM; -#endif -#if defined (SIGTERM) - if (hostsig == SIGTERM) return TARGET_SIGNAL_TERM; -#endif -#if defined (SIGUSR1) - if (hostsig == SIGUSR1) return TARGET_SIGNAL_USR1; -#endif -#if defined (SIGUSR2) - if (hostsig == SIGUSR2) return TARGET_SIGNAL_USR2; -#endif -#if defined (SIGCLD) - if (hostsig == SIGCLD) return TARGET_SIGNAL_CHLD; -#endif -#if defined (SIGCHLD) - if (hostsig == SIGCHLD) return TARGET_SIGNAL_CHLD; -#endif -#if defined (SIGPWR) - if (hostsig == SIGPWR) return TARGET_SIGNAL_PWR; -#endif -#if defined (SIGWINCH) - if (hostsig == SIGWINCH) return TARGET_SIGNAL_WINCH; -#endif -#if defined (SIGURG) - if (hostsig == SIGURG) return TARGET_SIGNAL_URG; -#endif -#if defined (SIGIO) - if (hostsig == SIGIO) return TARGET_SIGNAL_IO; -#endif -#if defined (SIGPOLL) - if (hostsig == SIGPOLL) return TARGET_SIGNAL_POLL; -#endif -#if defined (SIGSTOP) - if (hostsig == SIGSTOP) return TARGET_SIGNAL_STOP; -#endif -#if defined (SIGTSTP) - if (hostsig == SIGTSTP) return TARGET_SIGNAL_TSTP; -#endif -#if defined (SIGCONT) - if (hostsig == SIGCONT) return TARGET_SIGNAL_CONT; -#endif -#if defined (SIGTTIN) - if (hostsig == SIGTTIN) return TARGET_SIGNAL_TTIN; -#endif -#if defined (SIGTTOU) - if (hostsig == SIGTTOU) return TARGET_SIGNAL_TTOU; -#endif -#if defined (SIGVTALRM) - if (hostsig == SIGVTALRM) return TARGET_SIGNAL_VTALRM; -#endif -#if defined (SIGPROF) - if (hostsig == SIGPROF) return TARGET_SIGNAL_PROF; -#endif -#if defined (SIGXCPU) - if (hostsig == SIGXCPU) return TARGET_SIGNAL_XCPU; -#endif -#if defined (SIGXFSZ) - if (hostsig == SIGXFSZ) return TARGET_SIGNAL_XFSZ; -#endif -#if defined (SIGWIND) - if (hostsig == SIGWIND) return TARGET_SIGNAL_WIND; -#endif -#if defined (SIGPHONE) - if (hostsig == SIGPHONE) return TARGET_SIGNAL_PHONE; -#endif -#if defined (SIGLOST) - if (hostsig == SIGLOST) return TARGET_SIGNAL_LOST; -#endif -#if defined (SIGWAITING) - if (hostsig == SIGWAITING) return TARGET_SIGNAL_WAITING; -#endif -#if defined (SIGLWP) - if (hostsig == SIGLWP) return TARGET_SIGNAL_LWP; -#endif -#if defined (SIGDANGER) - if (hostsig == SIGDANGER) return TARGET_SIGNAL_DANGER; -#endif -#if defined (SIGGRANT) - if (hostsig == SIGGRANT) return TARGET_SIGNAL_GRANT; -#endif -#if defined (SIGRETRACT) - if (hostsig == SIGRETRACT) return TARGET_SIGNAL_RETRACT; -#endif -#if defined (SIGMSG) - if (hostsig == SIGMSG) return TARGET_SIGNAL_MSG; -#endif -#if defined (SIGSOUND) - if (hostsig == SIGSOUND) return TARGET_SIGNAL_SOUND; -#endif -#if defined (SIGSAK) - if (hostsig == SIGSAK) return TARGET_SIGNAL_SAK; +#ifdef CLEAR_DEFERRED_STORES + /* Delete any pending stores to the inferior... */ + CLEAR_DEFERRED_STORES; #endif - return TARGET_SIGNAL_UNKNOWN; -} -int -target_signal_to_host (oursig) - enum target_signal oursig; -{ - switch (oursig) - { - case TARGET_SIGNAL_0: return 0; + reopen_exec_file (); + reinit_frame_cache (); -#if defined (SIGHUP) - case TARGET_SIGNAL_HUP: return SIGHUP; -#endif -#if defined (SIGINT) - case TARGET_SIGNAL_INT: return SIGINT; -#endif -#if defined (SIGQUIT) - case TARGET_SIGNAL_QUIT: return SIGQUIT; -#endif -#if defined (SIGILL) - case TARGET_SIGNAL_ILL: return SIGILL; -#endif -#if defined (SIGTRAP) - case TARGET_SIGNAL_TRAP: return SIGTRAP; -#endif -#if defined (SIGABRT) - case TARGET_SIGNAL_ABRT: return SIGABRT; -#endif -#if defined (SIGEMT) - case TARGET_SIGNAL_EMT: return SIGEMT; -#endif -#if defined (SIGFPE) - case TARGET_SIGNAL_FPE: return SIGFPE; -#endif -#if defined (SIGKILL) - case TARGET_SIGNAL_KILL: return SIGKILL; -#endif -#if defined (SIGBUS) - case TARGET_SIGNAL_BUS: return SIGBUS; -#endif -#if defined (SIGSEGV) - case TARGET_SIGNAL_SEGV: return SIGSEGV; -#endif -#if defined (SIGSYS) - case TARGET_SIGNAL_SYS: return SIGSYS; -#endif -#if defined (SIGPIPE) - case TARGET_SIGNAL_PIPE: return SIGPIPE; -#endif -#if defined (SIGALRM) - case TARGET_SIGNAL_ALRM: return SIGALRM; -#endif -#if defined (SIGTERM) - case TARGET_SIGNAL_TERM: return SIGTERM; -#endif -#if defined (SIGUSR1) - case TARGET_SIGNAL_USR1: return SIGUSR1; -#endif -#if defined (SIGUSR2) - case TARGET_SIGNAL_USR2: return SIGUSR2; -#endif -#if defined (SIGCHLD) || defined (SIGCLD) - case TARGET_SIGNAL_CHLD: -#if defined (SIGCHLD) - return SIGCHLD; -#else - return SIGCLD; -#endif -#endif /* SIGCLD or SIGCHLD */ -#if defined (SIGPWR) - case TARGET_SIGNAL_PWR: return SIGPWR; -#endif -#if defined (SIGWINCH) - case TARGET_SIGNAL_WINCH: return SIGWINCH; -#endif -#if defined (SIGURG) - case TARGET_SIGNAL_URG: return SIGURG; -#endif -#if defined (SIGIO) - case TARGET_SIGNAL_IO: return SIGIO; -#endif -#if defined (SIGPOLL) - case TARGET_SIGNAL_POLL: return SIGPOLL; -#endif -#if defined (SIGSTOP) - case TARGET_SIGNAL_STOP: return SIGSTOP; -#endif -#if defined (SIGTSTP) - case TARGET_SIGNAL_TSTP: return SIGTSTP; -#endif -#if defined (SIGCONT) - case TARGET_SIGNAL_CONT: return SIGCONT; -#endif -#if defined (SIGTTIN) - case TARGET_SIGNAL_TTIN: return SIGTTIN; -#endif -#if defined (SIGTTOU) - case TARGET_SIGNAL_TTOU: return SIGTTOU; -#endif -#if defined (SIGVTALRM) - case TARGET_SIGNAL_VTALRM: return SIGVTALRM; -#endif -#if defined (SIGPROF) - case TARGET_SIGNAL_PROF: return SIGPROF; -#endif -#if defined (SIGXCPU) - case TARGET_SIGNAL_XCPU: return SIGXCPU; -#endif -#if defined (SIGXFSZ) - case TARGET_SIGNAL_XFSZ: return SIGXFSZ; -#endif -#if defined (SIGWIND) - case TARGET_SIGNAL_WIND: return SIGWIND; -#endif -#if defined (SIGPHONE) - case TARGET_SIGNAL_PHONE: return SIGPHONE; -#endif -#if defined (SIGLOST) - case TARGET_SIGNAL_LOST: return SIGLOST; -#endif -#if defined (SIGWAITING) - case TARGET_SIGNAL_WAITING: return SIGWAITING; -#endif -#if defined (SIGLWP) - case TARGET_SIGNAL_LWP: return SIGLWP; -#endif -#if defined (SIGDANGER) - case TARGET_SIGNAL_DANGER: return SIGDANGER; -#endif -#if defined (SIGGRANT) - case TARGET_SIGNAL_GRANT: return SIGGRANT; -#endif -#if defined (SIGRETRACT) - case TARGET_SIGNAL_RETRACT: return SIGRETRACT; -#endif -#if defined (SIGMSG) - case TARGET_SIGNAL_MSG: return SIGMSG; -#endif -#if defined (SIGSOUND) - case TARGET_SIGNAL_SOUND: return SIGSOUND; -#endif -#if defined (SIGSAK) - case TARGET_SIGNAL_SAK: return SIGSAK; -#endif - default: - /* The user might be trying to do "signal SIGSAK" where this system - doesn't have SIGSAK. */ - warning ("Signal %s does not exist on this system.\n", - target_signal_to_name (oursig)); - return 0; - } -} + /* 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 (detach_hook) + detach_hook (); +} + /* Helper function for child_wait and the Lynx derivatives of child_wait. HOSTSTATUS is the waitstatus from wait() or the equivalent; store our translation of that in OURSTATUS. */ void -store_waitstatus (ourstatus, hoststatus) - struct target_waitstatus *ourstatus; - int hoststatus; +store_waitstatus (struct target_waitstatus *ourstatus, int hoststatus) { #ifdef CHILD_SPECIAL_WAITSTATUS /* CHILD_SPECIAL_WAITSTATUS should return nonzero and set *OURSTATUS @@ -1330,39 +1448,862 @@ store_waitstatus (ourstatus, hoststatus) ourstatus->value.sig = target_signal_from_host (WSTOPSIG (hoststatus)); } } - /* Returns zero to leave the inferior alone, one to interrupt it. */ -int (*target_activity_function) PARAMS ((void)); +int (*target_activity_function) (void); int target_activity_fd; /* Convert a normal process ID to a string. Returns the string in a static buffer. */ char * -normal_pid_to_str (pid) - int pid; +normal_pid_to_str (ptid_t ptid) { static char buf[30]; - sprintf (buf, "process %d", pid); - + sprintf (buf, "process %d", PIDGET (ptid)); return buf; } + +/* Some targets (such as ttrace-based HPUX) don't allow us to request + notification of inferior events such as fork and vork immediately + after the inferior is created. (This because of how gdb gets an + inferior created via invoking a shell to do it. In such a scenario, + if the shell init file has commands in it, the shell will fork and + exec for each of those commands, and we will see each such fork + event. Very bad.) + + This function is used by all targets that allow us to request + notification of forks, etc at inferior creation time; e.g., in + target_acknowledge_forked_child. + */ +static void +normal_target_post_startup_inferior (ptid_t ptid) +{ + /* This space intentionally left blank. */ +} + +/* Error-catcher for target_find_memory_regions */ +/* ARGSUSED */ +static int dummy_find_memory_regions (int (*ignore1) (), void *ignore2) +{ + error ("No target."); + return 0; +} + +/* Error-catcher for target_make_corefile_notes */ +/* ARGSUSED */ +static char * dummy_make_corefile_notes (bfd *ignore1, int *ignore2) +{ + error ("No target."); + return NULL; +} + +/* Set up the handful of non-empty slots needed by the dummy target + vector. */ + +static void +init_dummy_target (void) +{ + dummy_target.to_shortname = "None"; + dummy_target.to_longname = "None"; + dummy_target.to_doc = ""; + dummy_target.to_attach = find_default_attach; + dummy_target.to_create_inferior = find_default_create_inferior; + dummy_target.to_pid_to_str = normal_pid_to_str; + dummy_target.to_stratum = dummy_stratum; + dummy_target.to_find_memory_regions = dummy_find_memory_regions; + dummy_target.to_make_corefile_notes = dummy_make_corefile_notes; + dummy_target.to_magic = OPS_MAGIC; +} -static char targ_desc[] = - "Names of targets and files being debugged.\n\ -Shows the entire 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 struct target_ops debug_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); +} + +static void +debug_to_close (int quitting) +{ + debug_target.to_close (quitting); + + fprintf_unfiltered (gdb_stdlog, "target_close (%d)\n", quitting); +} + +static void +debug_to_attach (char *args, int from_tty) +{ + debug_target.to_attach (args, from_tty); + + fprintf_unfiltered (gdb_stdlog, "target_attach (%s, %d)\n", args, from_tty); +} + + +static void +debug_to_post_attach (int pid) +{ + debug_target.to_post_attach (pid); + + fprintf_unfiltered (gdb_stdlog, "target_post_attach (%d)\n", pid); +} + +static void +debug_to_detach (char *args, int from_tty) +{ + debug_target.to_detach (args, from_tty); + + fprintf_unfiltered (gdb_stdlog, "target_detach (%s, %d)\n", args, from_tty); +} + +static void +debug_to_resume (ptid_t ptid, int step, enum target_signal siggnal) +{ + debug_target.to_resume (ptid, step, siggnal); + + fprintf_unfiltered (gdb_stdlog, "target_resume (%d, %s, %s)\n", PIDGET (ptid), + step ? "step" : "continue", + target_signal_to_name (siggnal)); +} + +static ptid_t +debug_to_wait (ptid_t ptid, struct target_waitstatus *status) +{ + ptid_t retval; + + retval = debug_target.to_wait (ptid, status); + + fprintf_unfiltered (gdb_stdlog, + "target_wait (%d, status) = %d, ", PIDGET (ptid), + PIDGET (retval)); + fprintf_unfiltered (gdb_stdlog, "status->kind = "); + switch (status->kind) + { + case TARGET_WAITKIND_EXITED: + fprintf_unfiltered (gdb_stdlog, "exited, status = %d\n", + status->value.integer); + break; + case TARGET_WAITKIND_STOPPED: + fprintf_unfiltered (gdb_stdlog, "stopped, signal = %s\n", + target_signal_to_name (status->value.sig)); + break; + case TARGET_WAITKIND_SIGNALLED: + fprintf_unfiltered (gdb_stdlog, "signalled, signal = %s\n", + target_signal_to_name (status->value.sig)); + break; + case TARGET_WAITKIND_LOADED: + fprintf_unfiltered (gdb_stdlog, "loaded\n"); + break; + case TARGET_WAITKIND_FORKED: + fprintf_unfiltered (gdb_stdlog, "forked\n"); + break; + case TARGET_WAITKIND_VFORKED: + fprintf_unfiltered (gdb_stdlog, "vforked\n"); + break; + case TARGET_WAITKIND_EXECD: + fprintf_unfiltered (gdb_stdlog, "execd\n"); + break; + case TARGET_WAITKIND_SPURIOUS: + fprintf_unfiltered (gdb_stdlog, "spurious\n"); + break; + default: + fprintf_unfiltered (gdb_stdlog, "unknown???\n"); + break; + } + + return retval; +} + +static void +debug_to_post_wait (ptid_t ptid, int status) +{ + debug_target.to_post_wait (ptid, status); + + fprintf_unfiltered (gdb_stdlog, "target_post_wait (%d, %d)\n", + PIDGET (ptid), status); +} + +static void +debug_print_register (const char * func, int regno) +{ + fprintf_unfiltered (gdb_stdlog, "%s ", func); + if (regno >= 0 && regno < NUM_REGS + NUM_PSEUDO_REGS + && REGISTER_NAME (regno) != NULL && REGISTER_NAME (regno)[0] != '\0') + fprintf_unfiltered (gdb_stdlog, "(%s)", REGISTER_NAME (regno)); + else + fprintf_unfiltered (gdb_stdlog, "(%d)", regno); + if (regno >= 0) + { + int i; + unsigned char buf[MAX_REGISTER_SIZE]; + deprecated_read_register_gen (regno, buf); + fprintf_unfiltered (gdb_stdlog, " = "); + for (i = 0; i < REGISTER_RAW_SIZE (regno); i++) + { + fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]); + } + if (REGISTER_RAW_SIZE (regno) <= sizeof (LONGEST)) + { + fprintf_unfiltered (gdb_stdlog, " 0x%s %s", + paddr_nz (read_register (regno)), + paddr_d (read_register (regno))); + } + } + fprintf_unfiltered (gdb_stdlog, "\n"); +} + +static void +debug_to_fetch_registers (int regno) +{ + debug_target.to_fetch_registers (regno); + debug_print_register ("target_fetch_registers", regno); +} + +static void +debug_to_store_registers (int regno) +{ + debug_target.to_store_registers (regno); + debug_print_register ("target_store_registers", regno); + fprintf_unfiltered (gdb_stdlog, "\n"); +} + +static void +debug_to_prepare_to_store (void) +{ + debug_target.to_prepare_to_store (); + + fprintf_unfiltered (gdb_stdlog, "target_prepare_to_store ()\n"); +} + +static int +debug_to_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, + struct mem_attrib *attrib, + struct target_ops *target) +{ + int retval; + + retval = debug_target.to_xfer_memory (memaddr, myaddr, len, write, + 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); + + + + if (retval > 0) + { + int i; + + fputs_unfiltered (", bytes =", gdb_stdlog); + for (i = 0; i < retval; i++) + { + if ((((long) &(myaddr[i])) & 0xf) == 0) + 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 (CORE_ADDR addr, char *save) +{ + int retval; + + retval = debug_target.to_insert_breakpoint (addr, save); + + fprintf_unfiltered (gdb_stdlog, + "target_insert_breakpoint (0x%lx, xxx) = %ld\n", + (unsigned long) addr, + (unsigned long) retval); + return retval; +} + +static int +debug_to_remove_breakpoint (CORE_ADDR addr, char *save) +{ + int retval; + + retval = debug_target.to_remove_breakpoint (addr, save); + + fprintf_unfiltered (gdb_stdlog, + "target_remove_breakpoint (0x%lx, xxx) = %ld\n", + (unsigned long) addr, + (unsigned long) retval); + return retval; +} + +static int +debug_to_can_use_hw_breakpoint (int type, int cnt, int from_tty) +{ + int retval; + + retval = debug_target.to_can_use_hw_breakpoint (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_size_ok_for_hw_watchpoint (int byte_count) +{ + CORE_ADDR retval; + + retval = debug_target.to_region_size_ok_for_hw_watchpoint (byte_count); + + fprintf_unfiltered (gdb_stdlog, + "TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT (%ld) = 0x%lx\n", + (unsigned long) byte_count, + (unsigned long) retval); + return retval; +} + +static int +debug_to_stopped_by_watchpoint (void) +{ + int retval; + + retval = debug_target.to_stopped_by_watchpoint (); + + fprintf_unfiltered (gdb_stdlog, + "STOPPED_BY_WATCHPOINT () = %ld\n", + (unsigned long) retval); + return retval; +} + +static CORE_ADDR +debug_to_stopped_data_address (void) +{ + CORE_ADDR retval; + + retval = debug_target.to_stopped_data_address (); + + fprintf_unfiltered (gdb_stdlog, + "target_stopped_data_address () = 0x%lx\n", + (unsigned long) retval); + return retval; +} + +static int +debug_to_insert_hw_breakpoint (CORE_ADDR addr, char *save) +{ + int retval; + + retval = debug_target.to_insert_hw_breakpoint (addr, save); + + fprintf_unfiltered (gdb_stdlog, + "target_insert_hw_breakpoint (0x%lx, xxx) = %ld\n", + (unsigned long) addr, + (unsigned long) retval); + return retval; +} + +static int +debug_to_remove_hw_breakpoint (CORE_ADDR addr, char *save) +{ + int retval; + + retval = debug_target.to_remove_hw_breakpoint (addr, save); + + fprintf_unfiltered (gdb_stdlog, + "target_remove_hw_breakpoint (0x%lx, xxx) = %ld\n", + (unsigned long) addr, + (unsigned long) retval); + return retval; +} + +static int +debug_to_insert_watchpoint (CORE_ADDR addr, int len, int type) +{ + int retval; + + retval = debug_target.to_insert_watchpoint (addr, len, type); + + fprintf_unfiltered (gdb_stdlog, + "target_insert_watchpoint (0x%lx, %d, %d) = %ld\n", + (unsigned long) addr, len, type, (unsigned long) retval); + return retval; +} + +static int +debug_to_remove_watchpoint (CORE_ADDR addr, int len, int type) +{ + int retval; + + retval = debug_target.to_insert_watchpoint (addr, len, type); + + fprintf_unfiltered (gdb_stdlog, + "target_insert_watchpoint (0x%lx, %d, %d) = %ld\n", + (unsigned long) addr, len, type, (unsigned long) retval); + return retval; +} + +static void +debug_to_terminal_init (void) +{ + debug_target.to_terminal_init (); + + fprintf_unfiltered (gdb_stdlog, "target_terminal_init ()\n"); +} + +static void +debug_to_terminal_inferior (void) +{ + debug_target.to_terminal_inferior (); + + fprintf_unfiltered (gdb_stdlog, "target_terminal_inferior ()\n"); +} + +static void +debug_to_terminal_ours_for_output (void) +{ + debug_target.to_terminal_ours_for_output (); + + fprintf_unfiltered (gdb_stdlog, "target_terminal_ours_for_output ()\n"); +} + +static void +debug_to_terminal_ours (void) +{ + debug_target.to_terminal_ours (); + + fprintf_unfiltered (gdb_stdlog, "target_terminal_ours ()\n"); +} + +static void +debug_to_terminal_save_ours (void) +{ + debug_target.to_terminal_save_ours (); + + fprintf_unfiltered (gdb_stdlog, "target_terminal_save_ours ()\n"); +} + +static void +debug_to_terminal_info (char *arg, int from_tty) +{ + debug_target.to_terminal_info (arg, from_tty); + + fprintf_unfiltered (gdb_stdlog, "target_terminal_info (%s, %d)\n", arg, + from_tty); +} + +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); + + fprintf_unfiltered (gdb_stdlog, "target_load (%s, %d)\n", args, from_tty); +} + +static int +debug_to_lookup_symbol (char *name, CORE_ADDR *addrp) +{ + int retval; + + retval = debug_target.to_lookup_symbol (name, addrp); + + fprintf_unfiltered (gdb_stdlog, "target_lookup_symbol (%s, xxx)\n", name); + + return retval; +} + +static void +debug_to_create_inferior (char *exec_file, char *args, char **env) +{ + debug_target.to_create_inferior (exec_file, args, env); + + fprintf_unfiltered (gdb_stdlog, "target_create_inferior (%s, %s, xxx)\n", + exec_file, args); +} + +static void +debug_to_post_startup_inferior (ptid_t ptid) +{ + debug_target.to_post_startup_inferior (ptid); + + fprintf_unfiltered (gdb_stdlog, "target_post_startup_inferior (%d)\n", + PIDGET (ptid)); +} + +static void +debug_to_acknowledge_created_inferior (int pid) +{ + debug_target.to_acknowledge_created_inferior (pid); + + fprintf_unfiltered (gdb_stdlog, "target_acknowledge_created_inferior (%d)\n", + pid); +} + +static int +debug_to_insert_fork_catchpoint (int pid) +{ + int retval; + + retval = debug_target.to_insert_fork_catchpoint (pid); + + fprintf_unfiltered (gdb_stdlog, "target_insert_fork_catchpoint (%d) = %d\n", + pid, retval); + + return retval; +} + +static int +debug_to_remove_fork_catchpoint (int pid) +{ + int retval; + + retval = debug_target.to_remove_fork_catchpoint (pid); + + fprintf_unfiltered (gdb_stdlog, "target_remove_fork_catchpoint (%d) = %d\n", + pid, retval); + + return retval; +} + +static int +debug_to_insert_vfork_catchpoint (int pid) +{ + int retval; + + retval = debug_target.to_insert_vfork_catchpoint (pid); + + fprintf_unfiltered (gdb_stdlog, "target_insert_vfork_catchpoint (%d)= %d\n", + pid, retval); + + return retval; +} + +static int +debug_to_remove_vfork_catchpoint (int pid) +{ + int retval; + + retval = debug_target.to_remove_vfork_catchpoint (pid); + + fprintf_unfiltered (gdb_stdlog, "target_remove_vfork_catchpoint (%d) = %d\n", + pid, retval); + + return retval; +} + +static int +debug_to_follow_fork (int follow_child) +{ + int retval = debug_target.to_follow_fork (follow_child); + + fprintf_unfiltered (gdb_stdlog, "target_follow_fork (%d) = %d\n", + follow_child, retval); + + return retval; +} + +static int +debug_to_insert_exec_catchpoint (int pid) +{ + int retval; + + retval = debug_target.to_insert_exec_catchpoint (pid); + + fprintf_unfiltered (gdb_stdlog, "target_insert_exec_catchpoint (%d) = %d\n", + pid, retval); + + return retval; +} + +static int +debug_to_remove_exec_catchpoint (int pid) +{ + int retval; + + retval = debug_target.to_remove_exec_catchpoint (pid); + + fprintf_unfiltered (gdb_stdlog, "target_remove_exec_catchpoint (%d) = %d\n", + pid, retval); + + return retval; +} + +static int +debug_to_reported_exec_events_per_exec_call (void) +{ + int reported_exec_events; + + reported_exec_events = debug_target.to_reported_exec_events_per_exec_call (); + + fprintf_unfiltered (gdb_stdlog, + "target_reported_exec_events_per_exec_call () = %d\n", + reported_exec_events); + + return reported_exec_events; +} + +static int +debug_to_has_exited (int pid, int wait_status, int *exit_status) +{ + int has_exited; + + has_exited = debug_target.to_has_exited (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 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) +{ + int retval; + + retval = debug_target.to_can_run (); + + fprintf_unfiltered (gdb_stdlog, "target_can_run () = %d\n", retval); + + return retval; +} + +static void +debug_to_notice_signals (ptid_t ptid) +{ + debug_target.to_notice_signals (ptid); + + fprintf_unfiltered (gdb_stdlog, "target_notice_signals (%d)\n", + PIDGET (ptid)); +} + +static int +debug_to_thread_alive (ptid_t ptid) +{ + int retval; + + retval = debug_target.to_thread_alive (ptid); + + fprintf_unfiltered (gdb_stdlog, "target_thread_alive (%d) = %d\n", + PIDGET (ptid), retval); + + 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_target.to_stop (); + + fprintf_unfiltered (gdb_stdlog, "target_stop ()\n"); +} + +static int +debug_to_query (int type, char *req, char *resp, int *siz) +{ + int retval; + + retval = debug_target.to_query (type, req, resp, siz); + + fprintf_unfiltered (gdb_stdlog, "target_query (%c, %s, %s, %d) = %d\n", type, req, resp, *siz, retval); + + return retval; +} + +static void +debug_to_rcmd (char *command, + struct ui_file *outbuf) +{ + debug_target.to_rcmd (command, outbuf); + fprintf_unfiltered (gdb_stdlog, "target_rcmd (%s, ...)\n", command); +} + +static struct symtab_and_line * +debug_to_enable_exception_callback (enum exception_event_kind kind, int enable) +{ + struct symtab_and_line *result; + result = debug_target.to_enable_exception_callback (kind, enable); + fprintf_unfiltered (gdb_stdlog, + "target get_exception_callback_sal (%d, %d)\n", + kind, enable); + return result; +} + +static struct exception_event_record * +debug_to_get_current_exception_event (void) +{ + struct exception_event_record *result; + result = debug_target.to_get_current_exception_event (); + fprintf_unfiltered (gdb_stdlog, "target get_current_exception_event ()\n"); + return result; +} + +static char * +debug_to_pid_to_exec_file (int pid) +{ + char *exec_file; + + exec_file = debug_target.to_pid_to_exec_file (pid); + + fprintf_unfiltered (gdb_stdlog, "target_pid_to_exec_file (%d) = %s\n", + pid, exec_file); + + return exec_file; +} + +static void +setup_target_debug (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_post_wait = debug_to_post_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.to_xfer_memory = debug_to_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_region_size_ok_for_hw_watchpoint = debug_to_region_size_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_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_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_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_follow_fork = debug_to_follow_fork; + 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_reported_exec_events_per_exec_call = debug_to_reported_exec_events_per_exec_call; + 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_query = debug_to_query; + current_target.to_rcmd = debug_to_rcmd; + current_target.to_enable_exception_callback = debug_to_enable_exception_callback; + current_target.to_get_current_exception_event = debug_to_get_current_exception_event; + current_target.to_pid_to_exec_file = debug_to_pid_to_exec_file; + +} + + +static char targ_desc[] = +"Names of targets and files being debugged.\n\ +Shows the entire 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 +do_monitor_command (char *cmd, + int from_tty) +{ + if ((current_target.to_rcmd + == (void (*) (char *, struct ui_file *)) tcomplain) + || (current_target.to_rcmd == debug_to_rcmd + && (debug_target.to_rcmd + == (void (*) (char *, struct ui_file *)) tcomplain))) + { + error ("\"monitor\" command not supported by this target.\n"); + } + target_rcmd (cmd, gdb_stdtarg); +} void -initialize_targets () +initialize_targets (void) { + init_dummy_target (); push_target (&dummy_target); add_info ("target", target_info, targ_desc); add_info ("files", target_info, targ_desc); - if (!STREQ (signals[TARGET_SIGNAL_LAST].string, "TARGET_SIGNAL_MAGIC")) - abort (); + add_show_from_set + (add_set_cmd ("target", class_maintenance, var_zinteger, + (char *) &targetdebug, + "Set target debugging.\n\ +When non-zero, target debugging is enabled.", &setdebuglist), + &showdebuglist); + + add_setshow_boolean_cmd ("trust-readonly-sections", class_support, + &trust_readonly, "\ +Set mode for reading from readonly sections.\n\ +When this mode is on, memory reads from readonly sections (such as .text)\n\ +will be read from the object file instead of from the target. This will\n\ +result in significant performance improvement for remote targets.", "\ +Show mode for reading from readonly sections.\n", + NULL, NULL, + &setlist, &showlist); + + add_com ("monitor", class_obscure, do_monitor_command, + "Send a command to the remote monitor (remote targets only)."); + + target_dcache = dcache_init (); }