/* Select target systems and architectures at runtime for GDB.
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Cygnus Support.
#include "gdbcore.h"
#include "exceptions.h"
#include "target-descriptions.h"
-#include "gdb_stdint.h"
+#include "gdbthread.h"
+#include "solib.h"
static void target_info (char *, int);
-static void maybe_kill_then_attach (char *, int);
-
static void kill_or_be_killed (int);
static void default_terminal_info (char *, int);
static void debug_to_close (int);
-static void debug_to_attach (char *, int);
+static void debug_to_attach (struct target_ops *ops, char *, int);
-static void debug_to_detach (char *, int);
+static void debug_to_detach (struct target_ops *ops, char *, int);
static void debug_to_resume (ptid_t, int, enum target_signal);
static int debug_to_lookup_symbol (char *, CORE_ADDR *);
-static void debug_to_mourn_inferior (void);
+static void debug_to_mourn_inferior (struct target_ops *);
static int debug_to_can_run (void);
static int debug_to_thread_alive (ptid_t);
-static void debug_to_stop (void);
+static void debug_to_stop (ptid_t);
/* NOTE: cagney/2004-09-29: Many targets reference this variable in
wierd and mysterious ways. Putting the variable here lets those
static struct cmd_list_element *targetlist = NULL;
-/* Nonzero if we are debugging an attached outside process
- rather than an inferior. */
-
-int attach_flag;
-
/* Nonzero if we should trust readonly sections from the
executable when reading memory. */
(*current_target.to_load) (arg, from_tty);
}
+void target_create_inferior (char *exec_file, char *args,
+ char **env, int from_tty)
+{
+ struct target_ops *t;
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_create_inferior != NULL)
+ {
+ t->to_create_inferior (t, exec_file, args, env, from_tty);
+ return;
+ }
+ }
+
+ internal_error (__FILE__, __LINE__,
+ "could not find a target to create inferior");
+}
+
+
static int
nomemory (CORE_ADDR memaddr, char *myaddr, int len, int write,
struct target_ops *t)
tcomplain ();
}
-static void
-maybe_kill_then_attach (char *args, int from_tty)
-{
- kill_or_be_killed (from_tty);
- target_attach (args, from_tty);
-}
+/* A default implementation for the to_get_ada_task_ptid target method.
-static void
-maybe_kill_then_create_inferior (char *exec, char *args, char **env,
- int from_tty)
+ This function builds the PTID by using both LWP and TID as part of
+ the PTID lwp and tid elements. The pid used is the pid of the
+ inferior_ptid. */
+
+ptid_t
+default_get_ada_task_ptid (long lwp, long tid)
{
- kill_or_be_killed (0);
- target_create_inferior (exec, args, env, from_tty);
+ return ptid_build (ptid_get_pid (inferior_ptid), lwp, tid);
}
/* Go through the target stack from top to bottom, copying over zero
INHERIT (to_shortname, t);
INHERIT (to_longname, t);
INHERIT (to_doc, t);
- INHERIT (to_open, t);
- INHERIT (to_close, t);
- INHERIT (to_attach, t);
+ /* Do not inherit to_open. */
+ /* Do not inherit to_close. */
+ /* Do not inherit to_attach. */
INHERIT (to_post_attach, t);
- INHERIT (to_detach, t);
+ INHERIT (to_attach_no_wait, t);
+ /* Do not inherit to_detach. */
/* Do not inherit to_disconnect. */
INHERIT (to_resume, t);
INHERIT (to_wait, t);
INHERIT (to_kill, t);
INHERIT (to_load, t);
INHERIT (to_lookup_symbol, t);
- INHERIT (to_create_inferior, t);
+ /* Do no inherit to_create_inferior. */
INHERIT (to_post_startup_inferior, t);
INHERIT (to_acknowledge_created_inferior, t);
INHERIT (to_insert_fork_catchpoint, t);
INHERIT (to_insert_exec_catchpoint, t);
INHERIT (to_remove_exec_catchpoint, t);
INHERIT (to_has_exited, t);
- INHERIT (to_mourn_inferior, t);
+ /* Do no inherit to_mourn_inferiour. */
INHERIT (to_can_run, t);
INHERIT (to_notice_signals, t);
INHERIT (to_thread_alive, t);
INHERIT (to_find_memory_regions, t);
INHERIT (to_make_corefile_notes, t);
INHERIT (to_get_thread_local_address, t);
+ INHERIT (to_can_execute_reverse, t);
/* Do not inherit to_read_description. */
+ INHERIT (to_get_ada_task_ptid, t);
+ /* Do not inherit to_search_memory. */
+ INHERIT (to_supports_multi_process, t);
INHERIT (to_magic, t);
/* Do not inherit to_memory_map. */
/* Do not inherit to_flash_erase. */
de_fault (to_close,
(void (*) (int))
target_ignore);
- de_fault (to_attach,
- maybe_kill_then_attach);
de_fault (to_post_attach,
(void (*) (int))
target_ignore);
- de_fault (to_detach,
- (void (*) (char *, int))
- target_ignore);
de_fault (to_resume,
(void (*) (ptid_t, int, enum target_signal))
noprocess);
de_fault (to_lookup_symbol,
(int (*) (char *, CORE_ADDR *))
nosymbol);
- de_fault (to_create_inferior,
- maybe_kill_then_create_inferior);
de_fault (to_post_startup_inferior,
(void (*) (ptid_t))
target_ignore);
de_fault (to_has_exited,
(int (*) (int, int, int *))
return_zero);
- de_fault (to_mourn_inferior,
- (void (*) (void))
- noprocess);
de_fault (to_can_run,
return_zero);
de_fault (to_notice_signals,
(char *(*) (struct thread_info *))
return_zero);
de_fault (to_stop,
- (void (*) (void))
+ (void (*) (ptid_t))
target_ignore);
current_target.to_xfer_partial = current_xfer_partial;
de_fault (to_rcmd,
de_fault (to_pid_to_exec_file,
(char *(*) (int))
return_zero);
- de_fault (to_can_async_p,
- (int (*) (void))
- return_zero);
- de_fault (to_is_async_p,
- (int (*) (void))
- return_zero);
de_fault (to_async,
(void (*) (void (*) (enum inferior_event_type, void*), void*))
tcomplain);
(int (*) (int))
return_one);
current_target.to_read_description = NULL;
+ de_fault (to_get_ada_task_ptid,
+ (ptid_t (*) (long, long))
+ default_get_ada_task_ptid);
+ de_fault (to_supports_multi_process,
+ (int (*) (void))
+ return_zero);
#undef de_fault
/* Finally, position the target-stack beneath the squashed
struct target_ops **cur;
struct target_ops *tmp;
+ if (t->to_stratum == dummy_stratum)
+ internal_error (__FILE__, __LINE__,
+ "Attempt to unpush the dummy target");
+
/* Look for the specified target. Note that we assume that a target
can only occur once in the target stack. */
void
pop_target (void)
{
- target_close (¤t_target, 0); /* Let it clean up */
+ target_close (target_stack, 0); /* Let it clean up */
if (unpush_target (target_stack) == 1)
return;
internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
}
+void
+pop_all_targets_above (enum strata above_stratum, int quitting)
+{
+ while ((int) (current_target.to_stratum) > (int) above_stratum)
+ {
+ target_close (target_stack, quitting);
+ if (!unpush_target (target_stack))
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "pop_all_targets couldn't find target %s\n",
+ target_stack->to_shortname);
+ internal_error (__FILE__, __LINE__,
+ _("failed internal consistency check"));
+ break;
+ }
+ }
+}
+
+void
+pop_all_targets (int quitting)
+{
+ pop_all_targets_above (dummy_stratum, quitting);
+}
+
/* Using the objfile specified in OBJFILE, find the address for the
current thread's thread-local storage with offset OFFSET. */
CORE_ADDR
volatile CORE_ADDR addr = 0;
if (target_get_thread_local_address_p ()
- && gdbarch_fetch_tls_load_module_address_p (current_gdbarch))
+ && gdbarch_fetch_tls_load_module_address_p (target_gdbarch))
{
ptid_t ptid = inferior_ptid;
volatile struct gdb_exception ex;
CORE_ADDR lm_addr;
/* Fetch the load module address for this objfile. */
- lm_addr = gdbarch_fetch_tls_load_module_address (current_gdbarch,
+ lm_addr = gdbarch_fetch_tls_load_module_address (target_gdbarch,
objfile);
/* If it's 0, throw the appropriate exception. */
if (lm_addr == 0)
/* Likewise for accesses to unmapped overlay sections. */
if (readbuf != NULL && overlay_debugging)
{
- asection *section = find_pc_overlay (memaddr);
+ struct obj_section *section = find_pc_overlay (memaddr);
if (pc_in_unmapped_range (memaddr, section))
return xfer_memory (memaddr, readbuf, len, 0, NULL, ops);
}
const unsigned char *myaddr = NULL;
fprintf_unfiltered (gdb_stdlog,
- "%s:target_xfer_partial (%d, %s, 0x%lx, 0x%lx, 0x%s, %s) = %s",
+ "%s:target_xfer_partial (%d, %s, %s, %s, %s, %s) = %s",
ops->to_shortname,
(int) object,
(annex ? annex : "(null)"),
- (long) readbuf, (long) writebuf,
- paddr_nz (offset), paddr_d (len), paddr_d (retval));
+ host_address_to_string (readbuf),
+ host_address_to_string (writebuf),
+ core_addr_to_string_nz (offset),
+ plongest (len), plongest (retval));
if (readbuf)
myaddr = readbuf;
fputs_unfiltered (", bytes =", gdb_stdlog);
for (i = 0; i < retval; i++)
{
- if ((((long) &(myaddr[i])) & 0xf) == 0)
+ if ((((intptr_t) &(myaddr[i])) & 0xf) == 0)
{
if (targetdebug < 2 && i > 0)
{
return len;
}
+LONGEST
+target_read_until_error (struct target_ops *ops,
+ enum target_object object,
+ const char *annex, gdb_byte *buf,
+ ULONGEST offset, LONGEST len)
+{
+ LONGEST xfered = 0;
+ while (xfered < len)
+ {
+ LONGEST xfer = target_read_partial (ops, object, annex,
+ (gdb_byte *) buf + xfered,
+ offset + xfered, len - xfered);
+ /* Call an observer, notifying them of the xfer progress? */
+ if (xfer == 0)
+ return xfered;
+ if (xfer < 0)
+ {
+ /* We've got an error. Try to read in smaller blocks. */
+ ULONGEST start = offset + xfered;
+ ULONGEST remaining = len - xfered;
+ ULONGEST half;
+
+ /* If an attempt was made to read a random memory address,
+ it's likely that the very first byte is not accessible.
+ Try reading the first byte, to avoid doing log N tries
+ below. */
+ xfer = target_read_partial (ops, object, annex,
+ (gdb_byte *) buf + xfered, start, 1);
+ if (xfer <= 0)
+ return xfered;
+ start += 1;
+ remaining -= 1;
+ half = remaining/2;
+
+ while (half > 0)
+ {
+ xfer = target_read_partial (ops, object, annex,
+ (gdb_byte *) buf + xfered,
+ start, half);
+ if (xfer == 0)
+ return xfered;
+ if (xfer < 0)
+ {
+ remaining = half;
+ }
+ else
+ {
+ /* We have successfully read the first half. So, the
+ error must be in the second half. Adjust start and
+ remaining to point at the second half. */
+ xfered += xfer;
+ start += xfer;
+ remaining -= xfer;
+ }
+ half = remaining/2;
+ }
+
+ return xfered;
+ }
+ xfered += xfer;
+ QUIT;
+ }
+ return len;
+}
+
+
/* An alternative to target_write with progress callbacks. */
LONGEST
void
target_pre_inferior (int from_tty)
{
- invalidate_target_mem_regions ();
+ /* Clear out solib state. Otherwise the solib state of the previous
+ inferior might have survived and is entirely wrong for the new
+ target. This has been observed on GNU/Linux using glibc 2.3. How
+ to reproduce:
+
+ bash$ ./foo&
+ [1] 4711
+ bash$ ./foo&
+ [1] 4712
+ bash$ gdb ./foo
+ [...]
+ (gdb) attach 4711
+ (gdb) detach
+ (gdb) attach 4712
+ Cannot access memory at address 0xdeadbeef
+ */
+
+ /* In some OSs, the shared library list is the same/global/shared
+ across inferiors. If code is shared between processes, so are
+ memory regions and features. */
+ if (!gdbarch_has_global_solist (target_gdbarch))
+ {
+ no_shared_libraries (NULL, from_tty);
- target_clear_description ();
+ invalidate_target_mem_regions ();
+
+ target_clear_description ();
+ }
}
/* This is to be called by the open routine before it does
/* Calling target_kill may remove the target from the stack. But if
it doesn't (which seems like a win for UDI), remove it now. */
-
- if (target_has_execution)
- pop_target ();
+ /* Leave the exec target, though. The user may be switching from a
+ live process to a core of the same program. */
+ pop_all_targets_above (file_stratum, 0);
target_pre_inferior (from_tty);
}
void
target_detach (char *args, int from_tty)
{
- /* If we're in breakpoints-always-inserted mode, have to
- remove them before detaching. */
- remove_breakpoints ();
+ struct target_ops* t;
+
+ if (gdbarch_has_global_solist (target_gdbarch))
+ /* Don't remove global breakpoints here. They're removed on
+ disconnection from the target. */
+ ;
+ else
+ /* If we're in breakpoints-always-inserted mode, have to remove
+ them before detaching. */
+ remove_breakpoints ();
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_detach != NULL)
+ {
+ t->to_detach (t, args, from_tty);
+ return;
+ }
+ }
- (current_target.to_detach) (args, from_tty);
+ internal_error (__FILE__, __LINE__, "could not find a target to detach");
}
void
{
struct target_ops *t;
- /* If we're in breakpoints-always-inserted mode, have to
- remove them before disconnecting. */
+ /* If we're in breakpoints-always-inserted mode or if breakpoints
+ are global across processes, we have to remove them before
+ disconnecting. */
remove_breakpoints ();
for (t = current_target.beneath; t != NULL; t = t->beneath)
tcomplain ();
}
+void
+target_resume (ptid_t ptid, int step, enum target_signal signal)
+{
+ dcache_invalidate (target_dcache);
+ (*current_target.to_resume) (ptid, step, signal);
+ set_executing (ptid, 1);
+ set_running (ptid, 1);
+}
/* Look through the list of possible targets for a target that can
follow forks. */
"could not find a target to follow fork");
}
+void
+target_mourn_inferior (void)
+{
+ struct target_ops *t;
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_mourn_inferior != NULL)
+ {
+ t->to_mourn_inferior (t);
+ 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. */
return NULL;
}
+/* The default implementation of to_search_memory.
+ This implements a basic search of memory, reading target memory and
+ performing the search here (as opposed to performing the search in on the
+ target side with, for example, gdbserver). */
+
+int
+simple_search_memory (struct target_ops *ops,
+ CORE_ADDR start_addr, ULONGEST search_space_len,
+ const gdb_byte *pattern, ULONGEST pattern_len,
+ CORE_ADDR *found_addrp)
+{
+ /* NOTE: also defined in find.c testcase. */
+#define SEARCH_CHUNK_SIZE 16000
+ const unsigned chunk_size = SEARCH_CHUNK_SIZE;
+ /* Buffer to hold memory contents for searching. */
+ gdb_byte *search_buf;
+ unsigned search_buf_size;
+ struct cleanup *old_cleanups;
+
+ search_buf_size = chunk_size + pattern_len - 1;
+
+ /* No point in trying to allocate a buffer larger than the search space. */
+ if (search_space_len < search_buf_size)
+ search_buf_size = search_space_len;
+
+ search_buf = malloc (search_buf_size);
+ if (search_buf == NULL)
+ error (_("Unable to allocate memory to perform the search."));
+ old_cleanups = make_cleanup (free_current_contents, &search_buf);
+
+ /* Prime the search buffer. */
+
+ if (target_read (ops, TARGET_OBJECT_MEMORY, NULL,
+ search_buf, start_addr, search_buf_size) != search_buf_size)
+ {
+ warning (_("Unable to access target memory at %s, halting search."),
+ hex_string (start_addr));
+ do_cleanups (old_cleanups);
+ return -1;
+ }
+
+ /* Perform the search.
+
+ The loop is kept simple by allocating [N + pattern-length - 1] bytes.
+ When we've scanned N bytes we copy the trailing bytes to the start and
+ read in another N bytes. */
+
+ while (search_space_len >= pattern_len)
+ {
+ gdb_byte *found_ptr;
+ unsigned nr_search_bytes = min (search_space_len, search_buf_size);
+
+ found_ptr = memmem (search_buf, nr_search_bytes,
+ pattern, pattern_len);
+
+ if (found_ptr != NULL)
+ {
+ CORE_ADDR found_addr = start_addr + (found_ptr - search_buf);
+ *found_addrp = found_addr;
+ do_cleanups (old_cleanups);
+ return 1;
+ }
+
+ /* Not found in this chunk, skip to next chunk. */
+
+ /* Don't let search_space_len wrap here, it's unsigned. */
+ if (search_space_len >= chunk_size)
+ search_space_len -= chunk_size;
+ else
+ search_space_len = 0;
+
+ if (search_space_len >= pattern_len)
+ {
+ unsigned keep_len = search_buf_size - chunk_size;
+ CORE_ADDR read_addr = start_addr + keep_len;
+ int nr_to_read;
+
+ /* Copy the trailing part of the previous iteration to the front
+ of the buffer for the next iteration. */
+ gdb_assert (keep_len == pattern_len - 1);
+ memcpy (search_buf, search_buf + chunk_size, keep_len);
+
+ nr_to_read = min (search_space_len - keep_len, chunk_size);
+
+ if (target_read (ops, TARGET_OBJECT_MEMORY, NULL,
+ search_buf + keep_len, read_addr,
+ nr_to_read) != nr_to_read)
+ {
+ warning (_("Unable to access target memory at %s, halting search."),
+ hex_string (read_addr));
+ do_cleanups (old_cleanups);
+ return -1;
+ }
+
+ start_addr += chunk_size;
+ }
+ }
+
+ /* Not found. */
+
+ do_cleanups (old_cleanups);
+ return 0;
+}
+
+/* Search SEARCH_SPACE_LEN bytes beginning at START_ADDR for the
+ sequence of bytes in PATTERN with length PATTERN_LEN.
+
+ The result is 1 if found, 0 if not found, and -1 if there was an error
+ requiring halting of the search (e.g. memory read error).
+ If the pattern is found the address is recorded in FOUND_ADDRP. */
+
+int
+target_search_memory (CORE_ADDR start_addr, ULONGEST search_space_len,
+ const gdb_byte *pattern, ULONGEST pattern_len,
+ CORE_ADDR *found_addrp)
+{
+ struct target_ops *t;
+ int found;
+
+ /* We don't use INHERIT to set current_target.to_search_memory,
+ so we have to scan the target stack and handle targetdebug
+ ourselves. */
+
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog, "target_search_memory (%s, ...)\n",
+ hex_string (start_addr));
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ if (t->to_search_memory != NULL)
+ break;
+
+ if (t != NULL)
+ {
+ found = t->to_search_memory (t, start_addr, search_space_len,
+ pattern, pattern_len, found_addrp);
+ }
+ else
+ {
+ /* If a special version of to_search_memory isn't available, use the
+ simple version. */
+ found = simple_search_memory (¤t_target,
+ start_addr, search_space_len,
+ pattern, pattern_len, found_addrp);
+ }
+
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog, " = %d\n", found);
+
+ return found;
+}
+
/* Look through the currently pushed targets. If none of them will
be able to restart the currently running process, issue an error
message. */
}
void
-find_default_attach (char *args, int from_tty)
+find_default_attach (struct target_ops *ops, char *args, int from_tty)
{
struct target_ops *t;
t = find_default_run_target ("attach");
- (t->to_attach) (args, from_tty);
+ (t->to_attach) (t, args, from_tty);
return;
}
void
-find_default_create_inferior (char *exec_file, char *allargs, char **env,
+find_default_create_inferior (struct target_ops *ops,
+ char *exec_file, char *allargs, char **env,
int from_tty)
{
struct target_ops *t;
t = find_default_run_target ("run");
- (t->to_create_inferior) (exec_file, allargs, env, from_tty);
+ (t->to_create_inferior) (t, exec_file, allargs, env, from_tty);
return;
}
return 0;
}
+int
+find_default_supports_non_stop (void)
+{
+ struct target_ops *t;
+
+ t = find_default_run_target (NULL);
+ if (t && t->to_supports_non_stop)
+ return (t->to_supports_non_stop) ();
+ return 0;
+}
+
+int
+target_supports_non_stop ()
+{
+ struct target_ops *t;
+ for (t = ¤t_target; t != NULL; t = t->beneath)
+ if (t->to_supports_non_stop)
+ return t->to_supports_non_stop ();
+
+ return 0;
+}
+
+
+char *
+target_get_osdata (const char *type)
+{
+ char *document;
+ struct target_ops *t;
+
+ if (target_can_run (¤t_target))
+ t = ¤t_target;
+ else
+ t = find_default_run_target ("get OS data");
+
+ if (!t)
+ return NULL;
+
+ document = target_read_stralloc (t,
+ TARGET_OBJECT_OSDATA,
+ type);
+ return document;
+}
+
static int
default_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
{
- return (len <= TYPE_LENGTH (builtin_type_void_data_ptr));
+ return (len <= gdbarch_ptr_bit (target_gdbarch) / TARGET_CHAR_BIT);
}
static int
void
generic_mourn_inferior (void)
{
- extern int show_breakpoint_hit_counts;
+ ptid_t ptid;
+ ptid = inferior_ptid;
inferior_ptid = null_ptid;
- attach_flag = 0;
+
+ if (!ptid_equal (ptid, null_ptid))
+ {
+ int pid = ptid_get_pid (ptid);
+ delete_inferior (pid);
+ }
+
breakpoint_init_inferior (inf_exited);
registers_changed ();
reopen_exec_file ();
reinit_frame_cache ();
- /* It is confusing to the user for ignore counts to stick around
- from previous runs of the inferior. So clear them. */
- /* However, it is more confusing for the ignore counts to disappear when
- using hit counts. So don't clear them if we're counting hits. */
- if (!show_breakpoint_hit_counts)
- breakpoint_clear_ignore_counts ();
-
if (deprecated_detach_hook)
deprecated_detach_hook ();
}
}
}
\f
-/* Returns zero to leave the inferior alone, one to interrupt it. */
-int (*target_activity_function) (void);
-int target_activity_fd;
-\f
/* Convert a normal process ID to a string. Returns the string in a
static buffer. */
dummy_target.to_longname = "None";
dummy_target.to_doc = "";
dummy_target.to_attach = find_default_attach;
+ dummy_target.to_detach =
+ (void (*)(struct target_ops *, char *, int))target_ignore;
dummy_target.to_create_inferior = find_default_create_inferior;
dummy_target.to_can_async_p = find_default_can_async_p;
dummy_target.to_is_async_p = find_default_is_async_p;
+ dummy_target.to_supports_non_stop = find_default_supports_non_stop;
dummy_target.to_pid_to_str = normal_pid_to_str;
dummy_target.to_stratum = dummy_stratum;
dummy_target.to_find_memory_regions = dummy_find_memory_regions;
targ->to_close (quitting);
}
+void
+target_attach (char *args, int from_tty)
+{
+ struct target_ops *t;
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_attach != NULL)
+ {
+ t->to_attach (t, args, from_tty);
+ return;
+ }
+ }
+
+ internal_error (__FILE__, __LINE__,
+ "could not find a target to attach");
+}
+
+
static void
-debug_to_attach (char *args, int from_tty)
+debug_to_attach (struct target_ops *ops, char *args, int from_tty)
{
- debug_target.to_attach (args, from_tty);
+ debug_target.to_attach (&debug_target, args, from_tty);
fprintf_unfiltered (gdb_stdlog, "target_attach (%s, %d)\n", args, from_tty);
}
}
static void
-debug_to_detach (char *args, int from_tty)
+debug_to_detach (struct target_ops *ops, char *args, int from_tty)
{
- debug_target.to_detach (args, from_tty);
+ debug_target.to_detach (&debug_target, args, from_tty);
fprintf_unfiltered (gdb_stdlog, "target_detach (%s, %d)\n", args, from_tty);
}
struct gdbarch *gdbarch = get_regcache_arch (regcache);
fprintf_unfiltered (gdb_stdlog, "%s ", func);
if (regno >= 0 && regno < gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch)
&& gdbarch_register_name (gdbarch, regno) != NULL
&& gdbarch_register_name (gdbarch, regno)[0] != '\0')
fprintf_unfiltered (gdb_stdlog, "(%s)",
gdbarch_register_name (gdbarch, regno));
else
fprintf_unfiltered (gdb_stdlog, "(%d)", regno);
- if (regno >= 0)
+ if (regno >= 0 && regno < gdbarch_num_regs (gdbarch))
{
int i, size = register_size (gdbarch, regno);
unsigned char buf[MAX_REGISTER_SIZE];
- regcache_cooked_read (regcache, regno, buf);
+ regcache_raw_collect (regcache, regno, buf);
fprintf_unfiltered (gdb_stdlog, " = ");
for (i = 0; i < size; i++)
{
if (size <= sizeof (LONGEST))
{
ULONGEST val = extract_unsigned_integer (buf, size);
- fprintf_unfiltered (gdb_stdlog, " 0x%s %s",
- paddr_nz (val), paddr_d (val));
+ fprintf_unfiltered (gdb_stdlog, " %s %s",
+ core_addr_to_string_nz (val), plongest (val));
}
}
fprintf_unfiltered (gdb_stdlog, "\n");
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)
{
fputs_unfiltered (", bytes =", gdb_stdlog);
for (i = 0; i < retval; i++)
{
- if ((((long) &(myaddr[i])) & 0xf) == 0)
+ if ((((intptr_t) &(myaddr[i])) & 0xf) == 0)
{
if (targetdebug < 2 && i > 0)
{
}
static void
-debug_to_create_inferior (char *exec_file, char *args, char **env,
+debug_to_create_inferior (struct target_ops *ops,
+ char *exec_file, char *args, char **env,
int from_tty)
{
- debug_target.to_create_inferior (exec_file, args, env, from_tty);
+ debug_target.to_create_inferior (ops, exec_file, args, env, from_tty);
fprintf_unfiltered (gdb_stdlog, "target_create_inferior (%s, %s, xxx, %d)\n",
exec_file, args, from_tty);
}
static void
-debug_to_mourn_inferior (void)
+debug_to_mourn_inferior (struct target_ops *ops)
{
- debug_target.to_mourn_inferior ();
+ debug_target.to_mourn_inferior (&debug_target);
fprintf_unfiltered (gdb_stdlog, "target_mourn_inferior ()\n");
}
}
static void
-debug_to_stop (void)
+debug_to_stop (ptid_t ptid)
{
- debug_target.to_stop ();
+ debug_target.to_stop (ptid);
- fprintf_unfiltered (gdb_stdlog, "target_stop ()\n");
+ fprintf_unfiltered (gdb_stdlog, "target_stop (%s)\n",
+ target_pid_to_str (ptid));
}
static void
}
}
+/* Controls if async mode is permitted. */
+int target_async_permitted = 0;
+
+/* The set command writes to this variable. If the inferior is
+ executing, linux_nat_async_permitted is *not* updated. */
+static int target_async_permitted_1 = 0;
+
+static void
+set_maintenance_target_async_permitted (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ if (target_has_execution)
+ {
+ target_async_permitted_1 = target_async_permitted;
+ error (_("Cannot change this setting while the inferior is running."));
+ }
+
+ target_async_permitted = target_async_permitted_1;
+}
+
+static void
+show_maintenance_target_async_permitted (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+ fprintf_filtered (file, _("\
+Controlling the inferior in asynchronous mode is %s.\n"), value);
+}
+
void
initialize_targets (void)
{
_("Print the name of each layer of the internal target stack."),
&maintenanceprintlist);
+ add_setshow_boolean_cmd ("target-async", no_class,
+ &target_async_permitted_1, _("\
+Set whether gdb controls the inferior in asynchronous mode."), _("\
+Show whether gdb controls the inferior in asynchronous mode."), _("\
+Tells gdb whether to control the inferior in asynchronous mode."),
+ set_maintenance_target_async_permitted,
+ show_maintenance_target_async_permitted,
+ &setlist,
+ &showlist);
+
target_dcache = dcache_init ();
}