/* Memory attributes support, for GDB.
- Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "command.h"
-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;
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 = 1;
+
+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. */
redefined to describe the minimal region containing ADDR. LO
and HI are used in the case where no memory region is defined
that contains ADDR. If a memory region is disabled, it is
- treated as if it does not exist. */
+ treated as if it does not exist. The initial values for LO
+ and HI represent the bottom and top of memory. */
- lo = (CORE_ADDR) 0;
- hi = (CORE_ADDR) ~ 0;
+ 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;
+ /* This (correctly) won't match if m->hi == 0, representing
+ the top of the address space, because CORE_ADDR is unsigned;
+ no value of LO is less than zero. */
if (addr >= m->hi && lo < m->hi)
lo = m->hi;
- if (addr <= m->lo && hi > m->lo)
+ /* This will never set HI to zero; if we're here and ADDR
+ is at or below M, and the region starts at zero, then ADDR
+ would have been in the region. */
+ if (addr <= m->lo && (hi == 0 || hi > m->lo))
hi = m->lo;
}
}
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;
}
void
invalidate_target_mem_regions (void)
{
- struct mem_region *m;
- int ix;
-
if (!target_mem_regions_valid)
return;
printf_filtered ("Num ");
printf_filtered ("Enb ");
printf_filtered ("Low Addr ");
- if (TARGET_ADDR_BIT > 32)
+ if (gdbarch_addr_bit (target_gdbarch) > 32)
printf_filtered (" ");
printf_filtered ("High Addr ");
- if (TARGET_ADDR_BIT > 32)
+ if (gdbarch_addr_bit (target_gdbarch) > 32)
printf_filtered (" ");
printf_filtered ("Attrs ");
printf_filtered ("\n");
for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++)
{
char *tmp;
+
printf_filtered ("%-3d %-3c\t",
m->number,
m->enabled_p ? 'y' : 'n');
- if (TARGET_ADDR_BIT <= 32)
+ if (gdbarch_addr_bit (target_gdbarch) <= 32)
tmp = hex_string_custom ((unsigned long) m->lo, 8);
else
tmp = hex_string_custom ((unsigned long) m->lo, 16);
printf_filtered ("%s ", tmp);
- if (TARGET_ADDR_BIT <= 32)
+ if (gdbarch_addr_bit (target_gdbarch) <= 32)
{
- if (m->hi == 0)
- tmp = "0x100000000";
- else
- tmp = hex_string_custom ((unsigned long) m->hi, 8);
+ if (m->hi == 0)
+ tmp = "0x100000000";
+ else
+ tmp = hex_string_custom ((unsigned long) m->hi, 8);
}
else
{
- if (m->hi == 0)
- tmp = "0x10000000000000000";
- else
- tmp = hex_string_custom ((unsigned long) m->hi, 16);
+ if (m->hi == 0)
+ tmp = "0x10000000000000000";
+ else
+ tmp = hex_string_custom ((unsigned long) m->hi, 16);
}
printf_filtered ("%s ", tmp);
require_user_regions (from_tty);
- dcache_invalidate (target_dcache);
+ target_dcache_invalidate ();
if (p == 0)
{
require_user_regions (from_tty);
- dcache_invalidate (target_dcache);
+ target_dcache_invalidate ();
if (p == 0)
{
static void
mem_delete (int num)
{
- struct mem_region *m1, *m;
+ struct mem_region *m;
int ix;
if (!mem_region_list)
require_user_regions (from_tty);
- dcache_invalidate (target_dcache);
+ target_dcache_invalidate ();
if (p == 0)
{
- if (query ("Delete all memory regions? "))
+ if (query (_("Delete all memory regions? ")))
mem_clear ();
dont_repeat ();
return;
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)
{
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);
}