* configure: Regenerate to track ../common/common.m4 changes.
[deliverable/binutils-gdb.git] / gdb / target.c
index ceb71b36cde459d360e811b88e00dd34cb9f1d7f..461cfe390c22362cc5adf3701ef2453d76f7d47c 100644 (file)
@@ -39,6 +39,7 @@
 #include "gdbcore.h"
 #include "exceptions.h"
 #include "target-descriptions.h"
+#include "gdbthread.h"
 
 static void target_info (char *, int);
 
@@ -48,6 +49,9 @@ static void kill_or_be_killed (int);
 
 static void default_terminal_info (char *, int);
 
+static int default_watchpoint_addr_within_range (struct target_ops *,
+                                                CORE_ADDR, CORE_ADDR, int);
+
 static int default_region_ok_for_hw_watchpoint (CORE_ADDR, int);
 
 static int nosymbol (char *, CORE_ADDR *);
@@ -130,6 +134,9 @@ static int debug_to_stopped_by_watchpoint (void);
 
 static int debug_to_stopped_data_address (struct target_ops *, CORE_ADDR *);
 
+static int debug_to_watchpoint_addr_within_range (struct target_ops *,
+                                                 CORE_ADDR, CORE_ADDR, int);
+
 static int debug_to_region_ok_for_hw_watchpoint (CORE_ADDR, int);
 
 static void debug_to_terminal_init (void);
@@ -158,7 +165,7 @@ static void debug_to_notice_signals (ptid_t);
 
 static int debug_to_thread_alive (ptid_t);
 
-static void debug_to_stop (void);
+static void debug_to_stop (ptid_t);
 
 /* NOTE: cagney/2004-09-29: Many targets reference this variable in
    wierd and mysterious ways.  Putting the variable here lets those
@@ -203,6 +210,11 @@ int attach_flag;
 
 static int trust_readonly = 0;
 
+/* Nonzero if we should show true memory content including
+   memory breakpoint inserted by gdb.  */
+
+static int show_memory_breakpoints = 0;
+
 /* Non-zero if we want to see trace of target level stuff.  */
 
 static int targetdebug = 0;
@@ -393,6 +405,7 @@ update_current_target (void)
       INHERIT (to_close, t);
       INHERIT (to_attach, t);
       INHERIT (to_post_attach, t);
+      INHERIT (to_attach_no_wait, t);
       INHERIT (to_detach, t);
       /* Do not inherit to_disconnect.  */
       INHERIT (to_resume, t);
@@ -410,9 +423,10 @@ update_current_target (void)
       INHERIT (to_insert_watchpoint, t);
       INHERIT (to_remove_watchpoint, t);
       INHERIT (to_stopped_data_address, t);
-      INHERIT (to_stopped_by_watchpoint, t);
       INHERIT (to_have_steppable_watchpoint, t);
       INHERIT (to_have_continuable_watchpoint, t);
+      INHERIT (to_stopped_by_watchpoint, t);
+      INHERIT (to_watchpoint_addr_within_range, t);
       INHERIT (to_region_ok_for_hw_watchpoint, t);
       INHERIT (to_terminal_init, t);
       INHERIT (to_terminal_inferior, t);
@@ -433,7 +447,6 @@ update_current_target (void)
       /* Do not inherit to_follow_fork.  */
       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);
@@ -459,11 +472,12 @@ update_current_target (void)
       INHERIT (to_can_async_p, t);
       INHERIT (to_is_async_p, t);
       INHERIT (to_async, t);
-      INHERIT (to_async_mask_value, t);
+      INHERIT (to_async_mask, t);
       INHERIT (to_find_memory_regions, t);
       INHERIT (to_make_corefile_notes, t);
       INHERIT (to_get_thread_local_address, t);
       /* Do not inherit to_read_description.  */
+      /* Do not inherit to_search_memory.  */
       INHERIT (to_magic, t);
       /* Do not inherit to_memory_map.  */
       /* Do not inherit to_flash_erase.  */
@@ -539,6 +553,8 @@ update_current_target (void)
   de_fault (to_stopped_data_address,
            (int (*) (struct target_ops *, CORE_ADDR *))
            return_zero);
+  de_fault (to_watchpoint_addr_within_range,
+           default_watchpoint_addr_within_range);
   de_fault (to_region_ok_for_hw_watchpoint,
            default_region_ok_for_hw_watchpoint);
   de_fault (to_terminal_init,
@@ -593,9 +609,6 @@ update_current_target (void)
   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);
@@ -617,7 +630,7 @@ update_current_target (void)
            (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,
@@ -635,6 +648,9 @@ update_current_target (void)
   de_fault (to_async,
            (void (*) (void (*) (enum inferior_event_type, void*), void*))
            tcomplain);
+  de_fault (to_async_mask,
+           (int (*) (int))
+           return_one);
   current_target.to_read_description = NULL;
 #undef de_fault
 
@@ -1064,7 +1080,11 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
       if (res <= 0)
        return -1;
       else
-       return res;
+       {
+         if (readbuf && !show_memory_breakpoints)
+           breakpoint_restore_shadows (readbuf, memaddr, reg_len);
+         return res;
+       }
     }
 
   /* If none of those methods found the memory we wanted, fall back
@@ -1082,22 +1102,41 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
       res = ops->to_xfer_partial (ops, TARGET_OBJECT_MEMORY, NULL,
                                  readbuf, writebuf, memaddr, reg_len);
       if (res > 0)
-       return res;
+       break;
 
       /* We want to continue past core files to executables, but not
         past a running target's memory.  */
       if (ops->to_has_all_memory)
-       return res;
+       break;
 
       ops = ops->beneath;
     }
   while (ops != NULL);
 
+  if (readbuf && !show_memory_breakpoints)
+    breakpoint_restore_shadows (readbuf, memaddr, reg_len);
+
   /* If we still haven't got anything, return the last error.  We
      give up.  */
   return res;
 }
 
+static void
+restore_show_memory_breakpoints (void *arg)
+{
+  show_memory_breakpoints = (uintptr_t) arg;
+}
+
+struct cleanup *
+make_show_memory_breakpoints_cleanup (int show)
+{
+  int current = show_memory_breakpoints;
+  show_memory_breakpoints = show;
+
+  return make_cleanup (restore_show_memory_breakpoints,
+                      (void *) (uintptr_t) current);
+}
+
 static LONGEST
 target_xfer_partial (struct target_ops *ops,
                     enum target_object object, const char *annex,
@@ -1412,6 +1451,72 @@ target_read (struct target_ops *ops,
   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
@@ -1648,6 +1753,10 @@ 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 ();
+
   (current_target.to_detach) (args, from_tty);
 }
 
@@ -1656,6 +1765,10 @@ 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.  */  
+  remove_breakpoints ();
+
   for (t = current_target.beneath; t != NULL; t = t->beneath)
     if (t->to_disconnect != NULL)
        {
@@ -1669,14 +1782,14 @@ target_disconnect (char *args, int from_tty)
   tcomplain ();
 }
 
-int
-target_async_mask (int mask)
+void
+target_resume (ptid_t ptid, int step, enum target_signal signal)
 {
-  int saved_async_masked_status = target_async_mask_value;
-  target_async_mask_value = mask;
-  return saved_async_masked_status;
+  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.  */
 
@@ -1723,6 +1836,157 @@ target_read_description (struct target_ops *target)
   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 (&current_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.  */
@@ -1762,7 +2026,8 @@ The \"%s\" target does not support \"run\".  Try \"help target\" or \"continue\"
    execute a run or attach command without any other data.  This is
    used to locate the default process stratum.
 
-   Result is always valid (error() is called for errors).  */
+   If DO_MESG is not NULL, the result is always valid (error() is
+   called for errors); else, return NULL on error.  */
 
 static struct target_ops *
 find_default_run_target (char *do_mesg)
@@ -1784,7 +2049,12 @@ find_default_run_target (char *do_mesg)
     }
 
   if (count != 1)
-    error (_("Don't know how to %s.  Try \"help target\"."), do_mesg);
+    {
+      if (do_mesg)
+       error (_("Don't know how to %s.  Try \"help target\"."), do_mesg);
+      else
+       return NULL;
+    }
 
   return runable;
 }
@@ -1810,12 +2080,50 @@ find_default_create_inferior (char *exec_file, char *allargs, char **env,
   return;
 }
 
+int
+find_default_can_async_p (void)
+{
+  struct target_ops *t;
+
+  /* This may be called before the target is pushed on the stack;
+     look for the default process stratum.  If there's none, gdb isn't
+     configured with a native debugger, and target remote isn't
+     connected yet.  */
+  t = find_default_run_target (NULL);
+  if (t && t->to_can_async_p)
+    return (t->to_can_async_p) ();
+  return 0;
+}
+
+int
+find_default_is_async_p (void)
+{
+  struct target_ops *t;
+
+  /* This may be called before the target is pushed on the stack;
+     look for the default process stratum.  If there's none, gdb isn't
+     configured with a native debugger, and target remote isn't
+     connected yet.  */
+  t = find_default_run_target (NULL);
+  if (t && t->to_is_async_p)
+    return (t->to_is_async_p) ();
+  return 0;
+}
+
 static int
 default_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
 {
   return (len <= TYPE_LENGTH (builtin_type_void_data_ptr));
 }
 
+static int
+default_watchpoint_addr_within_range (struct target_ops *target,
+                                     CORE_ADDR addr,
+                                     CORE_ADDR start, int length)
+{
+  return addr >= start && addr < start + length;
+}
+
 static int
 return_zero (void)
 {
@@ -2074,6 +2382,8 @@ init_dummy_target (void)
   dummy_target.to_doc = "";
   dummy_target.to_attach = find_default_attach;
   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_stratum = dummy_stratum;
   dummy_target.to_find_memory_regions = dummy_find_memory_regions;
@@ -2381,6 +2691,23 @@ debug_to_stopped_data_address (struct target_ops *target, CORE_ADDR *addr)
   return retval;
 }
 
+static int
+debug_to_watchpoint_addr_within_range (struct target_ops *target,
+                                      CORE_ADDR addr,
+                                      CORE_ADDR start, int length)
+{
+  int retval;
+
+  retval = debug_target.to_watchpoint_addr_within_range (target, addr,
+                                                        start, length);
+
+  fprintf_filtered (gdb_stdlog,
+                   "target_watchpoint_addr_within_range (0x%lx, 0x%lx, %d) = %d\n",
+                   (unsigned long) addr, (unsigned long) start, length,
+                   retval);
+  return retval;
+}
+
 static int
 debug_to_insert_hw_breakpoint (struct bp_target_info *bp_tgt)
 {
@@ -2606,20 +2933,6 @@ debug_to_remove_exec_catchpoint (int pid)
   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)
 {
@@ -2684,11 +2997,12 @@ debug_to_find_new_threads (void)
 }
 
 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
@@ -2738,6 +3052,7 @@ setup_target_debug (void)
   current_target.to_remove_watchpoint = debug_to_remove_watchpoint;
   current_target.to_stopped_by_watchpoint = debug_to_stopped_by_watchpoint;
   current_target.to_stopped_data_address = debug_to_stopped_data_address;
+  current_target.to_watchpoint_addr_within_range = debug_to_watchpoint_addr_within_range;
   current_target.to_region_ok_for_hw_watchpoint = debug_to_region_ok_for_hw_watchpoint;
   current_target.to_terminal_init = debug_to_terminal_init;
   current_target.to_terminal_inferior = debug_to_terminal_inferior;
@@ -2757,7 +3072,6 @@ setup_target_debug (void)
   current_target.to_remove_vfork_catchpoint = debug_to_remove_vfork_catchpoint;
   current_target.to_insert_exec_catchpoint = debug_to_insert_exec_catchpoint;
   current_target.to_remove_exec_catchpoint = debug_to_remove_exec_catchpoint;
-  current_target.to_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;
This page took 0.030366 seconds and 4 git commands to generate.