mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-24 00:44:14 +08:00
gdb/
* 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:
parent
bce613b9bf
commit
4b5752d02f
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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 ®ion;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user