X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Ftarget.c;h=86cdb71b78901292c9ba37b397b7deaa43106ed9;hb=2bd7c093f663139ad9e57ddc748ade12f6bfbe01;hp=681043eb76a17f33df4023822d11336caf95cc96;hpb=87ab71f0a047c034c71d26d7c4ff4fa2b35b22cd;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/target.c b/gdb/target.c index 681043eb76..86cdb71b78 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1,7 +1,7 @@ /* Select target systems and architectures at runtime for GDB. Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by Cygnus Support. @@ -44,8 +44,6 @@ static void target_info (char *, int); -static void maybe_kill_then_attach (char *, int); - static void kill_or_be_killed (int); static void default_terminal_info (char *, int); @@ -99,20 +97,6 @@ static struct target_ops debug_target; static void debug_to_open (char *, int); -static void debug_to_close (int); - -static void debug_to_attach (char *, int); - -static void debug_to_detach (char *, int); - -static void debug_to_resume (ptid_t, int, enum target_signal); - -static ptid_t debug_to_wait (ptid_t, struct target_waitstatus *); - -static void debug_to_fetch_registers (struct regcache *, int); - -static void debug_to_store_registers (struct regcache *, int); - static void debug_to_prepare_to_store (struct regcache *); static void debug_to_files_info (struct target_ops *); @@ -152,20 +136,14 @@ 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_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 (ptid_t); /* NOTE: cagney/2004-09-29: Many targets reference this variable in @@ -201,11 +179,6 @@ struct target_ops current_target; static struct cmd_list_element *targetlist = NULL; -/* Nonzero if we are debugging an attached outside process - rather than an inferior. */ - -int attach_flag; - /* Nonzero if we should trust readonly sections from the executable when reading memory. */ @@ -281,6 +254,24 @@ 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 (); +} + void target_load (char *arg, int from_tty) { @@ -288,6 +279,29 @@ target_load (char *arg, int from_tty) (*current_target.to_load) (arg, from_tty); } +void +target_create_inferior (char *exec_file, char *args, + char **env, int from_tty) +{ + struct target_ops *t; + for (t = current_target.beneath; t != NULL; t = t->beneath) + { + if (t->to_create_inferior != NULL) + { + t->to_create_inferior (t, exec_file, args, env, from_tty); + if (targetdebug) + fprintf_unfiltered (gdb_stdlog, + "target_create_inferior (%s, %s, xxx, %d)\n", + exec_file, args, from_tty); + return; + } + } + + internal_error (__FILE__, __LINE__, + "could not find a target to create inferior"); +} + + static int nomemory (CORE_ADDR memaddr, char *myaddr, int len, int write, struct target_ops *t) @@ -343,7 +357,7 @@ kill_or_be_killed (int from_tty) { printf_unfiltered (_("You are already running a program:\n")); target_files_info (); - if (query ("Kill it? ")) + if (query (_("Kill it? "))) { target_kill (); if (target_has_execution) @@ -358,19 +372,16 @@ kill_or_be_killed (int from_tty) tcomplain (); } -static void -maybe_kill_then_attach (char *args, int from_tty) -{ - kill_or_be_killed (from_tty); - target_attach (args, from_tty); -} +/* A default implementation for the to_get_ada_task_ptid target method. -static void -maybe_kill_then_create_inferior (char *exec, char *args, char **env, - int from_tty) + This function builds the PTID by using both LWP and TID as part of + the PTID lwp and tid elements. The pid used is the pid of the + inferior_ptid. */ + +static ptid_t +default_get_ada_task_ptid (long lwp, long tid) { - kill_or_be_killed (0); - target_create_inferior (exec, args, env, from_tty); + return ptid_build (ptid_get_pid (inferior_ptid), lwp, tid); } /* Go through the target stack from top to bottom, copying over zero @@ -402,17 +413,17 @@ update_current_target (void) INHERIT (to_shortname, t); INHERIT (to_longname, t); INHERIT (to_doc, t); - INHERIT (to_open, t); - INHERIT (to_close, t); - INHERIT (to_attach, t); + /* Do not inherit to_open. */ + /* Do not inherit to_close. */ + /* Do not inherit to_attach. */ INHERIT (to_post_attach, t); INHERIT (to_attach_no_wait, t); - INHERIT (to_detach, t); + /* Do not inherit to_detach. */ /* Do not inherit to_disconnect. */ - INHERIT (to_resume, t); - INHERIT (to_wait, t); - INHERIT (to_fetch_registers, t); - INHERIT (to_store_registers, t); + /* Do not inherit to_resume. */ + /* Do not inherit to_wait. */ + /* Do not inherit to_fetch_registers. */ + /* Do not inherit to_store_registers. */ INHERIT (to_prepare_to_store, t); INHERIT (deprecated_xfer_memory, t); INHERIT (to_files_info, t); @@ -435,10 +446,10 @@ update_current_target (void) INHERIT (to_terminal_ours, t); INHERIT (to_terminal_save_ours, t); INHERIT (to_terminal_info, t); - INHERIT (to_kill, t); + /* Do not inherit to_kill. */ INHERIT (to_load, t); INHERIT (to_lookup_symbol, t); - INHERIT (to_create_inferior, t); + /* Do no inherit to_create_inferior. */ INHERIT (to_post_startup_inferior, t); INHERIT (to_acknowledge_created_inferior, t); INHERIT (to_insert_fork_catchpoint, t); @@ -449,12 +460,12 @@ update_current_target (void) INHERIT (to_insert_exec_catchpoint, t); INHERIT (to_remove_exec_catchpoint, t); INHERIT (to_has_exited, t); - INHERIT (to_mourn_inferior, t); + /* Do not inherit to_mourn_inferiour. */ INHERIT (to_can_run, t); INHERIT (to_notice_signals, t); - INHERIT (to_thread_alive, t); - INHERIT (to_find_new_threads, t); - INHERIT (to_pid_to_str, t); + /* Do not inherit to_thread_alive. */ + /* Do not inherit to_find_new_threads. */ + /* Do not inherit to_pid_to_str. */ INHERIT (to_extra_thread_info, t); INHERIT (to_stop, t); /* Do not inherit to_xfer_partial. */ @@ -476,9 +487,12 @@ update_current_target (void) INHERIT (to_async_mask, t); INHERIT (to_find_memory_regions, t); INHERIT (to_make_corefile_notes, t); - INHERIT (to_get_thread_local_address, t); + /* Do not inherit to_get_thread_local_address. */ + INHERIT (to_can_execute_reverse, t); /* Do not inherit to_read_description. */ + INHERIT (to_get_ada_task_ptid, t); /* Do not inherit to_search_memory. */ + INHERIT (to_supports_multi_process, t); INHERIT (to_magic, t); /* Do not inherit to_memory_map. */ /* Do not inherit to_flash_erase. */ @@ -500,26 +514,9 @@ update_current_target (void) de_fault (to_close, (void (*) (int)) target_ignore); - de_fault (to_attach, - maybe_kill_then_attach); de_fault (to_post_attach, (void (*) (int)) target_ignore); - de_fault (to_detach, - (void (*) (char *, int)) - target_ignore); - de_fault (to_resume, - (void (*) (ptid_t, int, enum target_signal)) - noprocess); - de_fault (to_wait, - (ptid_t (*) (ptid_t, struct target_waitstatus *)) - noprocess); - de_fault (to_fetch_registers, - (void (*) (struct regcache *, int)) - target_ignore); - de_fault (to_store_registers, - (void (*) (struct regcache *, int)) - noprocess); de_fault (to_prepare_to_store, (void (*) (struct regcache *)) noprocess); @@ -575,17 +572,12 @@ update_current_target (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); @@ -613,20 +605,11 @@ update_current_target (void) 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); @@ -640,12 +623,6 @@ update_current_target (void) 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); @@ -653,6 +630,12 @@ update_current_target (void) (int (*) (int)) return_one); current_target.to_read_description = NULL; + de_fault (to_get_ada_task_ptid, + (ptid_t (*) (long, long)) + default_get_ada_task_ptid); + de_fault (to_supports_multi_process, + (int (*) (void)) + return_zero); #undef de_fault /* Finally, position the target-stack beneath the squashed @@ -778,6 +761,10 @@ unpush_target (struct target_ops *t) struct target_ops **cur; struct target_ops *tmp; + if (t->to_stratum == dummy_stratum) + internal_error (__FILE__, __LINE__, + "Attempt to unpush the dummy target"); + /* Look for the specified target. Note that we assume that a target can only occur once in the target stack. */ @@ -811,7 +798,7 @@ unpush_target (struct target_ops *t) void pop_target (void) { - target_close (¤t_target, 0); /* Let it clean up */ + target_close (target_stack, 0); /* Let it clean up */ if (unpush_target (target_stack) == 1) return; @@ -826,12 +813,12 @@ pop_all_targets_above (enum strata above_stratum, int quitting) { while ((int) (current_target.to_stratum) > (int) above_stratum) { - target_close (¤t_target, quitting); + target_close (target_stack, quitting); if (!unpush_target (target_stack)) { fprintf_unfiltered (gdb_stderr, "pop_all_targets couldn't find target %s\n", - current_target.to_shortname); + target_stack->to_shortname); internal_error (__FILE__, __LINE__, _("failed internal consistency check")); break; @@ -851,9 +838,18 @@ CORE_ADDR target_translate_tls_address (struct objfile *objfile, CORE_ADDR offset) { volatile CORE_ADDR addr = 0; + struct target_ops *target; + + for (target = current_target.beneath; + target != NULL; + target = target->beneath) + { + if (target->to_get_thread_local_address != NULL) + break; + } - if (target_get_thread_local_address_p () - && gdbarch_fetch_tls_load_module_address_p (current_gdbarch)) + if (target != NULL + && gdbarch_fetch_tls_load_module_address_p (target_gdbarch)) { ptid_t ptid = inferior_ptid; volatile struct gdb_exception ex; @@ -863,14 +859,14 @@ target_translate_tls_address (struct objfile *objfile, CORE_ADDR offset) CORE_ADDR lm_addr; /* Fetch the load module address for this objfile. */ - lm_addr = gdbarch_fetch_tls_load_module_address (current_gdbarch, + lm_addr = gdbarch_fetch_tls_load_module_address (target_gdbarch, objfile); /* If it's 0, throw the appropriate exception. */ if (lm_addr == 0) throw_error (TLS_LOAD_MODULE_NOT_FOUND_ERROR, _("TLS load module not found")); - addr = target_get_thread_local_address (ptid, lm_addr, offset); + addr = target->to_get_thread_local_address (target, ptid, lm_addr, offset); } /* If an error occurred, print TLS related messages here. Otherwise, throw the error to some higher catcher. */ @@ -1053,7 +1049,7 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf /* Likewise for accesses to unmapped overlay sections. */ if (readbuf != NULL && overlay_debugging) { - asection *section = find_pc_overlay (memaddr); + struct obj_section *section = find_pc_overlay (memaddr); if (pc_in_unmapped_range (memaddr, section)) return xfer_memory (memaddr, readbuf, len, 0, NULL, ops); } @@ -1195,12 +1191,14 @@ target_xfer_partial (struct target_ops *ops, const unsigned char *myaddr = NULL; fprintf_unfiltered (gdb_stdlog, - "%s:target_xfer_partial (%d, %s, 0x%lx, 0x%lx, 0x%s, %s) = %s", + "%s:target_xfer_partial (%d, %s, %s, %s, %s, %s) = %s", ops->to_shortname, (int) object, (annex ? annex : "(null)"), - (long) readbuf, (long) writebuf, - paddr_nz (offset), paddr_d (len), paddr_d (retval)); + host_address_to_string (readbuf), + host_address_to_string (writebuf), + core_addr_to_string_nz (offset), + plongest (len), plongest (retval)); if (readbuf) myaddr = readbuf; @@ -1213,7 +1211,7 @@ target_xfer_partial (struct target_ops *ops, fputs_unfiltered (", bytes =", gdb_stdlog); for (i = 0; i < retval; i++) { - if ((((long) &(myaddr[i])) & 0xf) == 0) + if ((((intptr_t) &(myaddr[i])) & 0xf) == 0) { if (targetdebug < 2 && i > 0) { @@ -1346,21 +1344,6 @@ target_flash_done (void) tcomplain (); } -#ifndef target_stopped_data_address_p -int -target_stopped_data_address_p (struct target_ops *target) -{ - if (target->to_stopped_data_address - == (int (*) (struct target_ops *, CORE_ADDR *)) return_zero) - return 0; - if (target->to_stopped_data_address == debug_to_stopped_data_address - && (debug_target.to_stopped_data_address - == (int (*) (struct target_ops *, CORE_ADDR *)) return_zero)) - return 0; - return 1; -} -#endif - static void show_trust_readonly (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) @@ -1758,11 +1741,18 @@ target_pre_inferior (int from_tty) (gdb) attach 4712 Cannot access memory at address 0xdeadbeef */ - no_shared_libraries (NULL, from_tty); - invalidate_target_mem_regions (); + /* In some OSs, the shared library list is the same/global/shared + across inferiors. If code is shared between processes, so are + memory regions and features. */ + if (!gdbarch_has_global_solist (target_gdbarch)) + { + no_shared_libraries (NULL, from_tty); + + invalidate_target_mem_regions (); - target_clear_description (); + target_clear_description (); + } } /* This is to be called by the open routine before it does @@ -1796,11 +1786,30 @@ target_preopen (int from_tty) void target_detach (char *args, int from_tty) { - /* If we're in breakpoints-always-inserted mode, have to - remove them before detaching. */ - remove_breakpoints (); + struct target_ops* t; + + if (gdbarch_has_global_solist (target_gdbarch)) + /* Don't remove global breakpoints here. They're removed on + disconnection from the target. */ + ; + else + /* If we're in breakpoints-always-inserted mode, have to remove + them before detaching. */ + remove_breakpoints (); + + for (t = current_target.beneath; t != NULL; t = t->beneath) + { + if (t->to_detach != NULL) + { + t->to_detach (t, args, from_tty); + if (targetdebug) + fprintf_unfiltered (gdb_stdlog, "target_detach (%s, %d)\n", + args, from_tty); + return; + } + } - (current_target.to_detach) (args, from_tty); + internal_error (__FILE__, __LINE__, "could not find a target to detach"); } void @@ -1808,8 +1817,9 @@ target_disconnect (char *args, int from_tty) { struct target_ops *t; - /* If we're in breakpoints-always-inserted mode, have to - remove them before disconnecting. */ + /* If we're in breakpoints-always-inserted mode or if breakpoints + are global across processes, we have to remove them before + disconnecting. */ remove_breakpoints (); for (t = current_target.beneath; t != NULL; t = t->beneath) @@ -1825,13 +1835,75 @@ target_disconnect (char *args, int from_tty) tcomplain (); } +ptid_t +target_wait (ptid_t ptid, struct target_waitstatus *status) +{ + struct target_ops *t; + + for (t = current_target.beneath; t != NULL; t = t->beneath) + { + if (t->to_wait != NULL) + { + ptid_t retval = (*t->to_wait) (t, ptid, status); + + if (targetdebug) + { + char *status_string; + + status_string = target_waitstatus_to_string (status); + fprintf_unfiltered (gdb_stdlog, + "target_wait (%d, status) = %d, %s\n", + PIDGET (ptid), PIDGET (retval), + status_string); + xfree (status_string); + } + + return retval; + } + } + + noprocess (); +} + +char * +target_pid_to_str (ptid_t ptid) +{ + struct target_ops *t; + + for (t = current_target.beneath; t != NULL; t = t->beneath) + { + if (t->to_pid_to_str != NULL) + return (*t->to_pid_to_str) (t, ptid); + } + + return normal_pid_to_str (ptid); +} + void target_resume (ptid_t ptid, int step, enum target_signal signal) { + struct target_ops *t; + dcache_invalidate (target_dcache); - (*current_target.to_resume) (ptid, step, signal); - set_executing (ptid, 1); - set_running (ptid, 1); + + for (t = current_target.beneath; t != NULL; t = t->beneath) + { + if (t->to_resume != NULL) + { + t->to_resume (t, ptid, step, signal); + if (targetdebug) + fprintf_unfiltered (gdb_stdlog, "target_resume (%d, %s, %s)\n", + PIDGET (ptid), + step ? "step" : "continue", + target_signal_to_name (signal)); + + set_executing (ptid, 1); + set_running (ptid, 1); + return; + } + } + + noprocess (); } /* Look through the list of possible targets for a target that can follow forks. */ @@ -1858,6 +1930,25 @@ target_follow_fork (int follow_child) "could not find a target to follow fork"); } +void +target_mourn_inferior (void) +{ + struct target_ops *t; + for (t = current_target.beneath; t != NULL; t = t->beneath) + { + if (t->to_mourn_inferior != NULL) + { + t->to_mourn_inferior (t); + if (targetdebug) + fprintf_unfiltered (gdb_stdlog, "target_mourn_inferior ()\n"); + return; + } + } + + internal_error (__FILE__, __LINE__, + "could not find a target to follow mourn inferiour"); +} + /* Look for a target which can describe architectural features, starting from TARGET. If we find one, return its description. */ @@ -2103,27 +2194,28 @@ find_default_run_target (char *do_mesg) } void -find_default_attach (char *args, int from_tty) +find_default_attach (struct target_ops *ops, char *args, int from_tty) { struct target_ops *t; t = find_default_run_target ("attach"); - (t->to_attach) (args, from_tty); + (t->to_attach) (t, args, from_tty); return; } void -find_default_create_inferior (char *exec_file, char *allargs, char **env, +find_default_create_inferior (struct target_ops *ops, + char *exec_file, char *allargs, char **env, int from_tty) { struct target_ops *t; t = find_default_run_target ("run"); - (t->to_create_inferior) (exec_file, allargs, env, from_tty); + (t->to_create_inferior) (t, exec_file, allargs, env, from_tty); return; } -int +static int find_default_can_async_p (void) { struct target_ops *t; @@ -2138,7 +2230,7 @@ find_default_can_async_p (void) return 0; } -int +static int find_default_is_async_p (void) { struct target_ops *t; @@ -2153,10 +2245,53 @@ find_default_is_async_p (void) return 0; } +static int +find_default_supports_non_stop (void) +{ + struct target_ops *t; + + t = find_default_run_target (NULL); + if (t && t->to_supports_non_stop) + return (t->to_supports_non_stop) (); + return 0; +} + +int +target_supports_non_stop (void) +{ + struct target_ops *t; + for (t = ¤t_target; t != NULL; t = t->beneath) + if (t->to_supports_non_stop) + return t->to_supports_non_stop (); + + return 0; +} + + +char * +target_get_osdata (const char *type) +{ + char *document; + struct target_ops *t; + + /* If we're already connected to something that can get us OS + related data, use it. Otherwise, try using the native + target. */ + if (current_target.to_stratum >= process_stratum) + t = current_target.beneath; + else + t = find_default_run_target ("get OS data"); + + if (!t) + return NULL; + + return target_read_stralloc (t, TARGET_OBJECT_OSDATA, type); +} + static int default_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len) { - return (len <= TYPE_LENGTH (builtin_type_void_data_ptr)); + return (len <= gdbarch_ptr_bit (target_gdbarch) / TARGET_CHAR_BIT); } static int @@ -2340,23 +2475,23 @@ find_target_beneath (struct target_ops *t) void generic_mourn_inferior (void) { - extern int show_breakpoint_hit_counts; + ptid_t ptid; + ptid = inferior_ptid; inferior_ptid = null_ptid; - attach_flag = 0; + + if (!ptid_equal (ptid, null_ptid)) + { + int pid = ptid_get_pid (ptid); + delete_inferior (pid); + } + breakpoint_init_inferior (inf_exited); registers_changed (); reopen_exec_file (); reinit_frame_cache (); - /* It is confusing to the user for ignore counts to stick around - from previous runs of the inferior. So clear them. */ - /* However, it is more confusing for the ignore counts to disappear when - using hit counts. So don't clear them if we're counting hits. */ - if (!show_breakpoint_hit_counts) - breakpoint_clear_ignore_counts (); - if (deprecated_detach_hook) deprecated_detach_hook (); } @@ -2384,10 +2519,6 @@ store_waitstatus (struct target_waitstatus *ourstatus, int hoststatus) } } -/* Returns zero to leave the inferior alone, one to interrupt it. */ -int (*target_activity_function) (void); -int target_activity_fd; - /* Convert a normal process ID to a string. Returns the string in a static buffer. */ @@ -2400,6 +2531,12 @@ normal_pid_to_str (ptid_t ptid) return buf; } +static char * +dummy_pid_to_str (struct target_ops *ops, ptid_t ptid) +{ + return normal_pid_to_str (ptid); +} + /* Error-catcher for target_find_memory_regions */ static int dummy_find_memory_regions (int (*ignore1) (), void *ignore2) { @@ -2424,10 +2561,13 @@ init_dummy_target (void) dummy_target.to_longname = "None"; dummy_target.to_doc = ""; dummy_target.to_attach = find_default_attach; + dummy_target.to_detach = + (void (*)(struct target_ops *, char *, int))target_ignore; dummy_target.to_create_inferior = find_default_create_inferior; dummy_target.to_can_async_p = find_default_can_async_p; dummy_target.to_is_async_p = find_default_is_async_p; - dummy_target.to_pid_to_str = normal_pid_to_str; + dummy_target.to_supports_non_stop = find_default_supports_non_stop; + dummy_target.to_pid_to_str = dummy_pid_to_str; dummy_target.to_stratum = dummy_stratum; dummy_target.to_find_memory_regions = dummy_find_memory_regions; dummy_target.to_make_corefile_notes = dummy_make_corefile_notes; @@ -2443,13 +2583,6 @@ debug_to_open (char *args, int from_tty) fprintf_unfiltered (gdb_stdlog, "target_open (%s, %d)\n", args, from_tty); } -static void -debug_to_close (int quitting) -{ - target_close (&debug_target, quitting); - fprintf_unfiltered (gdb_stdlog, "target_close (%d)\n", quitting); -} - void target_close (struct target_ops *targ, int quitting) { @@ -2457,89 +2590,118 @@ target_close (struct target_ops *targ, int quitting) targ->to_xclose (targ, quitting); else if (targ->to_close != NULL) targ->to_close (quitting); + + if (targetdebug) + fprintf_unfiltered (gdb_stdlog, "target_close (%d)\n", quitting); } -static void -debug_to_attach (char *args, int from_tty) +void +target_attach (char *args, int from_tty) { - debug_target.to_attach (args, from_tty); + struct target_ops *t; + for (t = current_target.beneath; t != NULL; t = t->beneath) + { + if (t->to_attach != NULL) + { + t->to_attach (t, args, from_tty); + if (targetdebug) + fprintf_unfiltered (gdb_stdlog, "target_attach (%s, %d)\n", + args, from_tty); + return; + } + } - fprintf_unfiltered (gdb_stdlog, "target_attach (%s, %d)\n", args, from_tty); + internal_error (__FILE__, __LINE__, + "could not find a target to attach"); } - -static void -debug_to_post_attach (int pid) +int +target_thread_alive (ptid_t ptid) { - debug_target.to_post_attach (pid); + struct target_ops *t; + for (t = current_target.beneath; t != NULL; t = t->beneath) + { + if (t->to_thread_alive != NULL) + { + int retval; - fprintf_unfiltered (gdb_stdlog, "target_post_attach (%d)\n", pid); + retval = t->to_thread_alive (t, ptid); + if (targetdebug) + fprintf_unfiltered (gdb_stdlog, "target_thread_alive (%d) = %d\n", + PIDGET (ptid), retval); + + return retval; + } + } + + return 0; } -static void -debug_to_detach (char *args, int from_tty) +void +target_find_new_threads (void) { - debug_target.to_detach (args, from_tty); + struct target_ops *t; + for (t = current_target.beneath; t != NULL; t = t->beneath) + { + if (t->to_find_new_threads != NULL) + { + t->to_find_new_threads (t); + if (targetdebug) + fprintf_unfiltered (gdb_stdlog, "target_find_new_threads ()\n"); - fprintf_unfiltered (gdb_stdlog, "target_detach (%s, %d)\n", args, from_tty); + return; + } + } } static void -debug_to_resume (ptid_t ptid, int step, enum target_signal siggnal) +debug_to_post_attach (int pid) { - debug_target.to_resume (ptid, step, siggnal); + debug_target.to_post_attach (pid); - fprintf_unfiltered (gdb_stdlog, "target_resume (%d, %s, %s)\n", PIDGET (ptid), - step ? "step" : "continue", - target_signal_to_name (siggnal)); + fprintf_unfiltered (gdb_stdlog, "target_post_attach (%d)\n", pid); } -static ptid_t -debug_to_wait (ptid_t ptid, struct target_waitstatus *status) -{ - ptid_t retval; +/* Return a pretty printed form of target_waitstatus. + Space for the result is malloc'd, caller must free. */ - retval = debug_target.to_wait (ptid, status); +char * +target_waitstatus_to_string (const struct target_waitstatus *ws) +{ + const char *kind_str = "status->kind = "; - fprintf_unfiltered (gdb_stdlog, - "target_wait (%d, status) = %d, ", PIDGET (ptid), - PIDGET (retval)); - fprintf_unfiltered (gdb_stdlog, "status->kind = "); - switch (status->kind) + switch (ws->kind) { case TARGET_WAITKIND_EXITED: - fprintf_unfiltered (gdb_stdlog, "exited, status = %d\n", - status->value.integer); - break; + return xstrprintf ("%sexited, status = %d", + kind_str, ws->value.integer); case TARGET_WAITKIND_STOPPED: - fprintf_unfiltered (gdb_stdlog, "stopped, signal = %s\n", - target_signal_to_name (status->value.sig)); - break; + return xstrprintf ("%sstopped, signal = %s", + kind_str, target_signal_to_name (ws->value.sig)); case TARGET_WAITKIND_SIGNALLED: - fprintf_unfiltered (gdb_stdlog, "signalled, signal = %s\n", - target_signal_to_name (status->value.sig)); - break; + return xstrprintf ("%ssignalled, signal = %s", + kind_str, target_signal_to_name (ws->value.sig)); case TARGET_WAITKIND_LOADED: - fprintf_unfiltered (gdb_stdlog, "loaded\n"); - break; + return xstrprintf ("%sloaded", kind_str); case TARGET_WAITKIND_FORKED: - fprintf_unfiltered (gdb_stdlog, "forked\n"); - break; + return xstrprintf ("%sforked", kind_str); case TARGET_WAITKIND_VFORKED: - fprintf_unfiltered (gdb_stdlog, "vforked\n"); - break; + return xstrprintf ("%svforked", kind_str); case TARGET_WAITKIND_EXECD: - fprintf_unfiltered (gdb_stdlog, "execd\n"); - break; + return xstrprintf ("%sexecd", kind_str); + case TARGET_WAITKIND_SYSCALL_ENTRY: + return xstrprintf ("%ssyscall-entry", kind_str); + case TARGET_WAITKIND_SYSCALL_RETURN: + return xstrprintf ("%ssyscall-return", kind_str); case TARGET_WAITKIND_SPURIOUS: - fprintf_unfiltered (gdb_stdlog, "spurious\n"); - break; + return xstrprintf ("%sspurious", kind_str); + case TARGET_WAITKIND_IGNORE: + return xstrprintf ("%signore", kind_str); + case TARGET_WAITKIND_NO_HISTORY: + return xstrprintf ("%sno-history", kind_str); default: - fprintf_unfiltered (gdb_stdlog, "unknown???\n"); - break; + return xstrprintf ("%sunknown???", kind_str); } - - return retval; } static void @@ -2549,18 +2711,17 @@ debug_print_register (const char * func, struct gdbarch *gdbarch = get_regcache_arch (regcache); fprintf_unfiltered (gdb_stdlog, "%s ", func); if (regno >= 0 && regno < gdbarch_num_regs (gdbarch) - + gdbarch_num_pseudo_regs (gdbarch) && gdbarch_register_name (gdbarch, regno) != NULL && gdbarch_register_name (gdbarch, regno)[0] != '\0') fprintf_unfiltered (gdb_stdlog, "(%s)", gdbarch_register_name (gdbarch, regno)); else fprintf_unfiltered (gdb_stdlog, "(%d)", regno); - if (regno >= 0) + if (regno >= 0 && regno < gdbarch_num_regs (gdbarch)) { int i, size = register_size (gdbarch, regno); unsigned char buf[MAX_REGISTER_SIZE]; - regcache_cooked_read (regcache, regno, buf); + regcache_raw_collect (regcache, regno, buf); fprintf_unfiltered (gdb_stdlog, " = "); for (i = 0; i < size; i++) { @@ -2569,26 +2730,48 @@ debug_print_register (const char * func, if (size <= sizeof (LONGEST)) { ULONGEST val = extract_unsigned_integer (buf, size); - fprintf_unfiltered (gdb_stdlog, " 0x%s %s", - paddr_nz (val), paddr_d (val)); + fprintf_unfiltered (gdb_stdlog, " %s %s", + core_addr_to_string_nz (val), plongest (val)); } } fprintf_unfiltered (gdb_stdlog, "\n"); } -static void -debug_to_fetch_registers (struct regcache *regcache, int regno) +void +target_fetch_registers (struct regcache *regcache, int regno) { - debug_target.to_fetch_registers (regcache, regno); - debug_print_register ("target_fetch_registers", regcache, regno); + struct target_ops *t; + for (t = current_target.beneath; t != NULL; t = t->beneath) + { + if (t->to_fetch_registers != NULL) + { + t->to_fetch_registers (t, regcache, regno); + if (targetdebug) + debug_print_register ("target_fetch_registers", regcache, regno); + return; + } + } } -static void -debug_to_store_registers (struct regcache *regcache, int regno) +void +target_store_registers (struct regcache *regcache, int regno) { - debug_target.to_store_registers (regcache, regno); - debug_print_register ("target_store_registers", regcache, regno); - fprintf_unfiltered (gdb_stdlog, "\n"); + + struct target_ops *t; + for (t = current_target.beneath; t != NULL; t = t->beneath) + { + if (t->to_store_registers != NULL) + { + t->to_store_registers (t, regcache, regno); + if (targetdebug) + { + debug_print_register ("target_store_registers", regcache, regno); + } + return; + } + } + + noprocess (); } static void @@ -2610,9 +2793,9 @@ deprecated_debug_xfer_memory (CORE_ADDR memaddr, bfd_byte *myaddr, int len, attrib, target); fprintf_unfiltered (gdb_stdlog, - "target_xfer_memory (0x%x, xxx, %d, %s, xxx) = %d", - (unsigned int) memaddr, /* possable truncate long long */ - len, write ? "write" : "read", retval); + "target_xfer_memory (%s, xxx, %d, %s, xxx) = %d", + paddress (memaddr), len, write ? "write" : "read", + retval); if (retval > 0) { @@ -2621,7 +2804,7 @@ deprecated_debug_xfer_memory (CORE_ADDR memaddr, bfd_byte *myaddr, int len, fputs_unfiltered (", bytes =", gdb_stdlog); for (i = 0; i < retval; i++) { - if ((((long) &(myaddr[i])) & 0xf) == 0) + if ((((intptr_t) &(myaddr[i])) & 0xf) == 0) { if (targetdebug < 2 && i > 0) { @@ -2854,14 +3037,6 @@ debug_to_terminal_info (char *arg, int from_tty) 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) { @@ -2882,16 +3057,6 @@ debug_to_lookup_symbol (char *name, CORE_ADDR *addrp) return retval; } -static void -debug_to_create_inferior (char *exec_file, char *args, char **env, - int from_tty) -{ - debug_target.to_create_inferior (exec_file, args, env, from_tty); - - fprintf_unfiltered (gdb_stdlog, "target_create_inferior (%s, %s, xxx, %d)\n", - exec_file, args, from_tty); -} - static void debug_to_post_startup_inferior (ptid_t ptid) { @@ -2989,14 +3154,6 @@ debug_to_has_exited (int pid, int wait_status, int *exit_status) 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) { @@ -3018,27 +3175,6 @@ debug_to_notice_signals (ptid_t ptid) 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 (ptid_t ptid) { @@ -3075,14 +3211,7 @@ 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_fetch_registers = debug_to_fetch_registers; - current_target.to_store_registers = debug_to_store_registers; current_target.to_prepare_to_store = debug_to_prepare_to_store; current_target.deprecated_xfer_memory = deprecated_debug_xfer_memory; current_target.to_files_info = debug_to_files_info; @@ -3103,10 +3232,8 @@ setup_target_debug (void) 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; @@ -3116,11 +3243,8 @@ setup_target_debug (void) current_target.to_insert_exec_catchpoint = debug_to_insert_exec_catchpoint; current_target.to_remove_exec_catchpoint = debug_to_remove_exec_catchpoint; current_target.to_has_exited = debug_to_has_exited; - current_target.to_mourn_inferior = debug_to_mourn_inferior; current_target.to_can_run = debug_to_can_run; current_target.to_notice_signals = debug_to_notice_signals; - current_target.to_thread_alive = debug_to_thread_alive; - current_target.to_find_new_threads = debug_to_find_new_threads; current_target.to_stop = debug_to_stop; current_target.to_rcmd = debug_to_rcmd; current_target.to_pid_to_exec_file = debug_to_pid_to_exec_file; @@ -3160,6 +3284,35 @@ maintenance_print_target_stack (char *cmd, int from_tty) } } +/* Controls if async mode is permitted. */ +int target_async_permitted = 0; + +/* The set command writes to this variable. If the inferior is + executing, linux_nat_async_permitted is *not* updated. */ +static int target_async_permitted_1 = 0; + +static void +set_maintenance_target_async_permitted (char *args, int from_tty, + struct cmd_list_element *c) +{ + if (target_has_execution) + { + target_async_permitted_1 = target_async_permitted; + error (_("Cannot change this setting while the inferior is running.")); + } + + target_async_permitted = target_async_permitted_1; +} + +static void +show_maintenance_target_async_permitted (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *value) +{ + fprintf_filtered (file, _("\ +Controlling the inferior in asynchronous mode is %s.\n"), value); +} + void initialize_targets (void) { @@ -3197,5 +3350,15 @@ result in significant performance improvement for remote targets."), _("Print the name of each layer of the internal target stack."), &maintenanceprintlist); + add_setshow_boolean_cmd ("target-async", no_class, + &target_async_permitted_1, _("\ +Set whether gdb controls the inferior in asynchronous mode."), _("\ +Show whether gdb controls the inferior in asynchronous mode."), _("\ +Tells gdb whether to control the inferior in asynchronous mode."), + set_maintenance_target_async_permitted, + show_maintenance_target_async_permitted, + &setlist, + &showlist); + target_dcache = dcache_init (); }