* 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.
This commit is contained in:
Vladimir Prus 2006-11-21 16:50:16 +00:00
parent bce613b9bf
commit 4b5752d02f
6 changed files with 126 additions and 4 deletions

View 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.

View 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

View 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.

View 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)
{
}
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);
}

View 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. */

View 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;