gdb/
authorVladimir Prus <vladimir@codesourcery.com>
Tue, 21 Nov 2006 16:50:16 +0000 (16:50 +0000)
committerVladimir Prus <vladimir@codesourcery.com>
Tue, 21 Nov 2006 16:50:16 +0000 (16:50 +0000)
        * memattr.h (enum mem_access_mode): New value
        MEM_NONE.
        * memattr.c (unknown_mem_attrib): New.
        (inaccessible_by_default): New.
        (show_inaccessible_by_default): New.
        (lookup_mem_region): Check inaccessible_by_default.
        (dummy_cmd): New.
        (mem_set_cmdlist, mem_show_cmdlist): New.
        (_initialize_mem): Register new "set" and "show"
        commands.
        * target.c (memory_xfer_partial): If memory type
        is MEM_NONE, return an error.
        Clip to region size when calling to_xfer_partial.
        If upper limit of memory range is 0, don't clip
        anything.

        gdb/doc/
        * gdb.texinfo (Memory Access Checking): New.

gdb/ChangeLog
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/memattr.c
gdb/memattr.h
gdb/target.c

index 4726e265f82a86eaf34da08984c3cb22777bed40..2f6ef8d0cd0d5a0d864e3b2553eab1d90ac8d9b8 100644 (file)
@@ -1,3 +1,21 @@
+2006-11-21  Vladimir Prus  <vladimir@codesourcery.com>
+
+       * memattr.h (enum mem_access_mode): New value
+       MEM_NONE.
+       * memattr.c (unknown_mem_attrib): New.
+       (inaccessible_by_default): New.
+       (show_inaccessible_by_default): New.
+       (lookup_mem_region): Check inaccessible_by_default.
+       (dummy_cmd): New.
+       (mem_set_cmdlist, mem_show_cmdlist): New.
+       (_initialize_mem): Register new "set" and "show"
+       commands.
+       * target.c (memory_xfer_partial): If memory type
+       is MEM_NONE, return an error.
+       Clip to region size when calling to_xfer_partial.
+       If upper limit of memory range is 0, don't clip
+       anything.
+
 2006-11-20  Joel Brobecker  <brobecker@adacore.com>
 
        * README: Remove obsolete information.
index ecf7a8ccc109614892ad0e9a8456635f7f3847f1..71f30c1e730da0e6859db97d293c2223dda3710b 100644 (file)
@@ -1,3 +1,7 @@
+2006-11-21  Vladimir Prus  <vladimir@codesourcery.com>
+
+       * gdb.texinfo (Memory Access Checking): New.
+
 2006-11-16  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * gdb.texinfo (Remote configuration): Mention
index f0b5f87e1065572a60e64ee59af91bff6e749bec..f89cc09781682007bc6d3716d347d70627fb7a80 100644 (file)
@@ -6894,6 +6894,27 @@ Enable @value{GDBN} to cache target memory.
 Disable @value{GDBN} from caching target memory.  This is the default.
 @end table
 
+@subsection Memory Access Checking
+@value{GDBN} can be instructed to refuse accesses to memory that is
+not explicitly described.  This can be useful if accessing such
+regions has undesired effects for a specific target, or to provide
+better error checking.  The following commands control this behaviour.
+
+@table @code
+@kindex set mem inaccessible-by-default
+@item set mem inaccessible-by-default [on|off]
+If @code{on} is specified, make  @value{GDBN} treat memory not
+explicitly described by the memory ranges as non-existent and refuse accesses
+to such memory.  The checks are only performed if there's at least one
+memory range defined.  If @code{off} is specified, make @value{GDBN}
+treat the memory not explicitly described by the memory ranges as RAM.
+The default value is @code{off}.
+@kindex show mem inaccessible-by-default
+@item show mem inaccessible-by-default
+Show the current handling of accesses to unknown memory.
+@end table
+
+
 @c @subsubsection Memory Write Verification
 @c The memory write verification attributes set whether @value{GDBN}
 @c will re-reads data after each write to verify the write was successful.
index 889d03ac8f400f8a1685f79ee03c37fbc011b536..a114dc1ff82934b3f3c9ab46fae7a79524dbf116 100644 (file)
@@ -40,6 +40,17 @@ const struct mem_attrib default_mem_attrib =
   -1 /* Flash blocksize not specified.  */
 };
 
+const struct mem_attrib unknown_mem_attrib =
+{
+  MEM_NONE,                    /* mode */
+  MEM_WIDTH_UNSPECIFIED,
+  0,                           /* hwbreak */
+  0,                           /* cache */
+  0,                           /* verify */
+  -1 /* Flash blocksize not specified.  */
+};
+
+
 VEC(mem_region_s) *mem_region_list, *target_mem_region_list;
 static int mem_number = 0;
 
@@ -53,6 +64,25 @@ static int mem_use_target = 1;
    empty, then the target can't supply memory regions.  */
 static int target_mem_regions_valid;
 
+/* If this flag is set, gdb will assume that memory ranges not
+   specified by the memory map have type MEM_NONE, and will
+   emit errors on all accesses to that memory.  */
+static int inaccessible_by_default = 0;
+
+static void
+show_inaccessible_by_default (struct ui_file *file, int from_tty,
+                             struct cmd_list_element *c,
+                             const char *value)
+{
+  if (inaccessible_by_default)
+    fprintf_filtered (file, _("\
+Unknown memory addresses will be treated as inaccessible.\n"));
+  else
+    fprintf_filtered (file, _("\
+Unknown memory addresses will be treated as RAM.\n"));          
+}
+
+
 /* Predicate function which returns true if LHS should sort before RHS
    in a list of memory regions, useful for VEC_lower_bound.  */
 
@@ -215,13 +245,17 @@ lookup_mem_region (CORE_ADDR addr)
   lo = 0;
   hi = 0;
 
-  /* If we ever want to support a huge list of memory regions, this
+  /* Either find memory range containing ADDRESS, or set LO and HI
+     to the nearest boundaries of an existing memory range.
+     
+     If we ever want to support a huge list of memory regions, this
      check should be replaced with a binary search (probably using
      VEC_lower_bound).  */
   for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++)
     {
       if (m->enabled_p == 1)
        {
+         /* If the address is in the memory region, return that memory range.  */
          if (addr >= m->lo && (addr < m->hi || m->hi == 0))
            return m;
 
@@ -243,7 +277,15 @@ lookup_mem_region (CORE_ADDR addr)
      was learned above.  */
   region.lo = lo;
   region.hi = hi;
-  region.attrib = default_mem_attrib;
+
+  /* When no memory map is defined at all, we always return 
+     'default_mem_attrib', so that we do not make all memory 
+     inaccessible for targets that don't provide a memory map.  */
+  if (inaccessible_by_default && !VEC_empty (mem_region_s, mem_region_list))
+    region.attrib = unknown_mem_attrib;
+  else
+    region.attrib = default_mem_attrib;
+
   return &region;
 }
 
@@ -674,9 +716,17 @@ mem_delete_command (char *args, int from_tty)
 
   dont_repeat ();
 }
+
+static void
+dummy_cmd (char *args, int from_tty)
+{
+}
 \f
 extern initialize_file_ftype _initialize_mem; /* -Wmissing-prototype */
 
+static struct cmd_list_element *mem_set_cmdlist;
+static struct cmd_list_element *mem_show_cmdlist;
+
 void
 _initialize_mem (void)
 {
@@ -709,4 +759,25 @@ Do \"info mem\" to see current list of code numbers."), &deletelist);
 
   add_info ("mem", mem_info_command,
            _("Memory region attributes"));
+
+  add_prefix_cmd ("mem", class_vars, dummy_cmd, _("\
+Memory regions settings"),
+                 &mem_set_cmdlist, "set mem ",
+                 0/* allow-unknown */, &setlist);
+  add_prefix_cmd ("mem", class_vars, dummy_cmd, _("\
+Memory regions settings"),
+                 &mem_show_cmdlist, "show mem  ",
+                 0/* allow-unknown */, &showlist);
+
+  add_setshow_boolean_cmd ("inaccessible-by-default", no_class,
+                                 &inaccessible_by_default, _("\
+Set handling of unknown memory regions."), _("\
+Show handling of unknown memory regions."), _("\
+If on, and some memory map is defined, debugger will emit errors on\n\
+accesses to memory not defined in the memory map. If off, accesses to all\n\
+memory addresses will be allowed."),
+                               NULL,
+                               show_inaccessible_by_default,
+                               &mem_set_cmdlist,
+                               &mem_show_cmdlist);
 }
index 046af689635a445307ae06d027142bc5e8300390..077ccee86c523bbf6f785ba870eacf41428f2736 100644 (file)
@@ -26,6 +26,7 @@
 
 enum mem_access_mode
 {
+  MEM_NONE,                     /* Memory that is not physically present. */
   MEM_RW,                      /* read/write */
   MEM_RO,                      /* read only */
   MEM_WO,                      /* write only */
@@ -76,7 +77,10 @@ struct mem_attrib
 
 struct mem_region 
 {
+  /* Lowest address in the region.  */
   CORE_ADDR lo;
+  /* Address past the highest address of the region. 
+     If 0, upper bound is "infinity".  */
   CORE_ADDR hi;
 
   /* Item number of this memory region. */
index 2ff882cf912e40d4776ea47eed8df4da4ee6c5f7..2062733037ec8252f3e4da76b9eb943490c98897 100644 (file)
@@ -1015,7 +1015,8 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
 
   /* Try GDB's internal data cache.  */
   region = lookup_mem_region (memaddr);
-  if (memaddr + len < region->hi)
+  /* region->hi == 0 means there's no upper bound.  */
+  if (memaddr + len < region->hi || region->hi == 0)
     reg_len = len;
   else
     reg_len = region->hi - memaddr;
@@ -1037,6 +1038,9 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
       if (writebuf != NULL)
        error (_("Writing to flash memory forbidden in this context"));
       break;
+
+    case MEM_NONE:
+      return -1;
     }
 
   if (region->attrib.cache)
@@ -1072,7 +1076,7 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
   do
     {
       res = ops->to_xfer_partial (ops, TARGET_OBJECT_MEMORY, NULL,
-                                 readbuf, writebuf, memaddr, len);
+                                 readbuf, writebuf, memaddr, reg_len);
       if (res > 0)
        return res;