include/opcode/
[deliverable/binutils-gdb.git] / gdb / target.c
index 944d601659f9860dece77ea34a104d5e900613d8..6b009a8e76cfb1322a9a0c28b44d2aee394dbfb7 100644 (file)
@@ -40,6 +40,7 @@
 #include "exceptions.h"
 #include "target-descriptions.h"
 #include "gdb_stdint.h"
+#include "gdbthread.h"
 
 static void target_info (char *, int);
 
@@ -49,6 +50,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 *);
@@ -131,6 +135,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);
@@ -416,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);
@@ -469,6 +477,7 @@ update_current_target (void)
       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.  */
@@ -544,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,
@@ -1705,6 +1716,14 @@ target_disconnect (char *args, int from_tty)
   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_running (ptid, 1);
+
+}
 /* Look through the list of possible targets for a target that can
    follow forks.  */
 
@@ -1751,6 +1770,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.  */
@@ -1880,6 +2050,14 @@ 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)
 {
@@ -2447,6 +2625,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)
 {
@@ -2790,6 +2985,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;
This page took 0.029558 seconds and 4 git commands to generate.