15796c8dcSSimon Schubert /* Memory attributes support, for GDB.
25796c8dcSSimon Schubert
3*ef5ccd6cSJohn Marino Copyright (C) 2001-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert
55796c8dcSSimon Schubert This file is part of GDB.
65796c8dcSSimon Schubert
75796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify
85796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by
95796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or
105796c8dcSSimon Schubert (at your option) any later version.
115796c8dcSSimon Schubert
125796c8dcSSimon Schubert This program is distributed in the hope that it will be useful,
135796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
145796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
155796c8dcSSimon Schubert GNU General Public License for more details.
165796c8dcSSimon Schubert
175796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
185796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */
195796c8dcSSimon Schubert
205796c8dcSSimon Schubert #include "defs.h"
215796c8dcSSimon Schubert #include "command.h"
225796c8dcSSimon Schubert #include "gdbcmd.h"
235796c8dcSSimon Schubert #include "memattr.h"
245796c8dcSSimon Schubert #include "target.h"
255796c8dcSSimon Schubert #include "value.h"
265796c8dcSSimon Schubert #include "language.h"
275796c8dcSSimon Schubert #include "vec.h"
285796c8dcSSimon Schubert #include "gdb_string.h"
29c50c785cSJohn Marino #include "breakpoint.h"
30c50c785cSJohn Marino #include "cli/cli-utils.h"
315796c8dcSSimon Schubert
325796c8dcSSimon Schubert const struct mem_attrib default_mem_attrib =
335796c8dcSSimon Schubert {
345796c8dcSSimon Schubert MEM_RW, /* mode */
355796c8dcSSimon Schubert MEM_WIDTH_UNSPECIFIED,
365796c8dcSSimon Schubert 0, /* hwbreak */
375796c8dcSSimon Schubert 0, /* cache */
385796c8dcSSimon Schubert 0, /* verify */
395796c8dcSSimon Schubert -1 /* Flash blocksize not specified. */
405796c8dcSSimon Schubert };
415796c8dcSSimon Schubert
425796c8dcSSimon Schubert const struct mem_attrib unknown_mem_attrib =
435796c8dcSSimon Schubert {
445796c8dcSSimon Schubert MEM_NONE, /* mode */
455796c8dcSSimon Schubert MEM_WIDTH_UNSPECIFIED,
465796c8dcSSimon Schubert 0, /* hwbreak */
475796c8dcSSimon Schubert 0, /* cache */
485796c8dcSSimon Schubert 0, /* verify */
495796c8dcSSimon Schubert -1 /* Flash blocksize not specified. */
505796c8dcSSimon Schubert };
515796c8dcSSimon Schubert
525796c8dcSSimon Schubert
535796c8dcSSimon Schubert VEC(mem_region_s) *mem_region_list, *target_mem_region_list;
545796c8dcSSimon Schubert static int mem_number = 0;
555796c8dcSSimon Schubert
565796c8dcSSimon Schubert /* If this flag is set, the memory region list should be automatically
575796c8dcSSimon Schubert updated from the target. If it is clear, the list is user-controlled
585796c8dcSSimon Schubert and should be left alone. */
595796c8dcSSimon Schubert static int mem_use_target = 1;
605796c8dcSSimon Schubert
615796c8dcSSimon Schubert /* If this flag is set, we have tried to fetch the target memory regions
625796c8dcSSimon Schubert since the last time it was invalidated. If that list is still
635796c8dcSSimon Schubert empty, then the target can't supply memory regions. */
645796c8dcSSimon Schubert static int target_mem_regions_valid;
655796c8dcSSimon Schubert
665796c8dcSSimon Schubert /* If this flag is set, gdb will assume that memory ranges not
675796c8dcSSimon Schubert specified by the memory map have type MEM_NONE, and will
685796c8dcSSimon Schubert emit errors on all accesses to that memory. */
695796c8dcSSimon Schubert static int inaccessible_by_default = 1;
705796c8dcSSimon Schubert
715796c8dcSSimon Schubert static void
show_inaccessible_by_default(struct ui_file * file,int from_tty,struct cmd_list_element * c,const char * value)725796c8dcSSimon Schubert show_inaccessible_by_default (struct ui_file *file, int from_tty,
735796c8dcSSimon Schubert struct cmd_list_element *c,
745796c8dcSSimon Schubert const char *value)
755796c8dcSSimon Schubert {
765796c8dcSSimon Schubert if (inaccessible_by_default)
77c50c785cSJohn Marino fprintf_filtered (file, _("Unknown memory addresses will "
78c50c785cSJohn Marino "be treated as inaccessible.\n"));
795796c8dcSSimon Schubert else
80c50c785cSJohn Marino fprintf_filtered (file, _("Unknown memory addresses "
81c50c785cSJohn Marino "will be treated as RAM.\n"));
825796c8dcSSimon Schubert }
835796c8dcSSimon Schubert
845796c8dcSSimon Schubert
855796c8dcSSimon Schubert /* Predicate function which returns true if LHS should sort before RHS
865796c8dcSSimon Schubert in a list of memory regions, useful for VEC_lower_bound. */
875796c8dcSSimon Schubert
885796c8dcSSimon Schubert static int
mem_region_lessthan(const struct mem_region * lhs,const struct mem_region * rhs)895796c8dcSSimon Schubert mem_region_lessthan (const struct mem_region *lhs,
905796c8dcSSimon Schubert const struct mem_region *rhs)
915796c8dcSSimon Schubert {
925796c8dcSSimon Schubert return lhs->lo < rhs->lo;
935796c8dcSSimon Schubert }
945796c8dcSSimon Schubert
955796c8dcSSimon Schubert /* A helper function suitable for qsort, used to sort a
965796c8dcSSimon Schubert VEC(mem_region_s) by starting address. */
975796c8dcSSimon Schubert
985796c8dcSSimon Schubert int
mem_region_cmp(const void * untyped_lhs,const void * untyped_rhs)995796c8dcSSimon Schubert mem_region_cmp (const void *untyped_lhs, const void *untyped_rhs)
1005796c8dcSSimon Schubert {
1015796c8dcSSimon Schubert const struct mem_region *lhs = untyped_lhs;
1025796c8dcSSimon Schubert const struct mem_region *rhs = untyped_rhs;
1035796c8dcSSimon Schubert
1045796c8dcSSimon Schubert if (lhs->lo < rhs->lo)
1055796c8dcSSimon Schubert return -1;
1065796c8dcSSimon Schubert else if (lhs->lo == rhs->lo)
1075796c8dcSSimon Schubert return 0;
1085796c8dcSSimon Schubert else
1095796c8dcSSimon Schubert return 1;
1105796c8dcSSimon Schubert }
1115796c8dcSSimon Schubert
1125796c8dcSSimon Schubert /* Allocate a new memory region, with default settings. */
1135796c8dcSSimon Schubert
1145796c8dcSSimon Schubert void
mem_region_init(struct mem_region * new)1155796c8dcSSimon Schubert mem_region_init (struct mem_region *new)
1165796c8dcSSimon Schubert {
1175796c8dcSSimon Schubert memset (new, 0, sizeof (struct mem_region));
1185796c8dcSSimon Schubert new->enabled_p = 1;
1195796c8dcSSimon Schubert new->attrib = default_mem_attrib;
1205796c8dcSSimon Schubert }
1215796c8dcSSimon Schubert
1225796c8dcSSimon Schubert /* This function should be called before any command which would
1235796c8dcSSimon Schubert modify the memory region list. It will handle switching from
1245796c8dcSSimon Schubert a target-provided list to a local list, if necessary. */
1255796c8dcSSimon Schubert
1265796c8dcSSimon Schubert static void
require_user_regions(int from_tty)1275796c8dcSSimon Schubert require_user_regions (int from_tty)
1285796c8dcSSimon Schubert {
1295796c8dcSSimon Schubert struct mem_region *m;
1305796c8dcSSimon Schubert int ix, length;
1315796c8dcSSimon Schubert
1325796c8dcSSimon Schubert /* If we're already using a user-provided list, nothing to do. */
1335796c8dcSSimon Schubert if (!mem_use_target)
1345796c8dcSSimon Schubert return;
1355796c8dcSSimon Schubert
1365796c8dcSSimon Schubert /* Switch to a user-provided list (possibly a copy of the current
1375796c8dcSSimon Schubert one). */
1385796c8dcSSimon Schubert mem_use_target = 0;
1395796c8dcSSimon Schubert
1405796c8dcSSimon Schubert /* If we don't have a target-provided region list yet, then
1415796c8dcSSimon Schubert no need to warn. */
1425796c8dcSSimon Schubert if (mem_region_list == NULL)
1435796c8dcSSimon Schubert return;
1445796c8dcSSimon Schubert
1455796c8dcSSimon Schubert /* Otherwise, let the user know how to get back. */
1465796c8dcSSimon Schubert if (from_tty)
1475796c8dcSSimon Schubert warning (_("Switching to manual control of memory regions; use "
1485796c8dcSSimon Schubert "\"mem auto\" to fetch regions from the target again."));
1495796c8dcSSimon Schubert
1505796c8dcSSimon Schubert /* And create a new list for the user to modify. */
1515796c8dcSSimon Schubert length = VEC_length (mem_region_s, target_mem_region_list);
1525796c8dcSSimon Schubert mem_region_list = VEC_alloc (mem_region_s, length);
1535796c8dcSSimon Schubert for (ix = 0; VEC_iterate (mem_region_s, target_mem_region_list, ix, m); ix++)
1545796c8dcSSimon Schubert VEC_quick_push (mem_region_s, mem_region_list, m);
1555796c8dcSSimon Schubert }
1565796c8dcSSimon Schubert
1575796c8dcSSimon Schubert /* This function should be called before any command which would
1585796c8dcSSimon Schubert read the memory region list, other than those which call
1595796c8dcSSimon Schubert require_user_regions. It will handle fetching the
1605796c8dcSSimon Schubert target-provided list, if necessary. */
1615796c8dcSSimon Schubert
1625796c8dcSSimon Schubert static void
require_target_regions(void)1635796c8dcSSimon Schubert require_target_regions (void)
1645796c8dcSSimon Schubert {
1655796c8dcSSimon Schubert if (mem_use_target && !target_mem_regions_valid)
1665796c8dcSSimon Schubert {
1675796c8dcSSimon Schubert target_mem_regions_valid = 1;
1685796c8dcSSimon Schubert target_mem_region_list = target_memory_map ();
1695796c8dcSSimon Schubert mem_region_list = target_mem_region_list;
1705796c8dcSSimon Schubert }
1715796c8dcSSimon Schubert }
1725796c8dcSSimon Schubert
1735796c8dcSSimon Schubert static void
create_mem_region(CORE_ADDR lo,CORE_ADDR hi,const struct mem_attrib * attrib)1745796c8dcSSimon Schubert create_mem_region (CORE_ADDR lo, CORE_ADDR hi,
1755796c8dcSSimon Schubert const struct mem_attrib *attrib)
1765796c8dcSSimon Schubert {
1775796c8dcSSimon Schubert struct mem_region new;
1785796c8dcSSimon Schubert int i, ix;
1795796c8dcSSimon Schubert
180c50c785cSJohn Marino /* lo == hi is a useless empty region. */
1815796c8dcSSimon Schubert if (lo >= hi && hi != 0)
1825796c8dcSSimon Schubert {
1835796c8dcSSimon Schubert printf_unfiltered (_("invalid memory region: low >= high\n"));
1845796c8dcSSimon Schubert return;
1855796c8dcSSimon Schubert }
1865796c8dcSSimon Schubert
1875796c8dcSSimon Schubert mem_region_init (&new);
1885796c8dcSSimon Schubert new.lo = lo;
1895796c8dcSSimon Schubert new.hi = hi;
1905796c8dcSSimon Schubert
1915796c8dcSSimon Schubert ix = VEC_lower_bound (mem_region_s, mem_region_list, &new,
1925796c8dcSSimon Schubert mem_region_lessthan);
1935796c8dcSSimon Schubert
1945796c8dcSSimon Schubert /* Check for an overlapping memory region. We only need to check
1955796c8dcSSimon Schubert in the vicinity - at most one before and one after the
1965796c8dcSSimon Schubert insertion point. */
1975796c8dcSSimon Schubert for (i = ix - 1; i < ix + 1; i++)
1985796c8dcSSimon Schubert {
1995796c8dcSSimon Schubert struct mem_region *n;
2005796c8dcSSimon Schubert
2015796c8dcSSimon Schubert if (i < 0)
2025796c8dcSSimon Schubert continue;
2035796c8dcSSimon Schubert if (i >= VEC_length (mem_region_s, mem_region_list))
2045796c8dcSSimon Schubert continue;
2055796c8dcSSimon Schubert
2065796c8dcSSimon Schubert n = VEC_index (mem_region_s, mem_region_list, i);
2075796c8dcSSimon Schubert
2085796c8dcSSimon Schubert if ((lo >= n->lo && (lo < n->hi || n->hi == 0))
2095796c8dcSSimon Schubert || (hi > n->lo && (hi <= n->hi || n->hi == 0))
210*ef5ccd6cSJohn Marino || (lo <= n->lo && ((hi >= n->hi && n->hi != 0) || hi == 0)))
2115796c8dcSSimon Schubert {
2125796c8dcSSimon Schubert printf_unfiltered (_("overlapping memory region\n"));
2135796c8dcSSimon Schubert return;
2145796c8dcSSimon Schubert }
2155796c8dcSSimon Schubert }
2165796c8dcSSimon Schubert
2175796c8dcSSimon Schubert new.number = ++mem_number;
2185796c8dcSSimon Schubert new.attrib = *attrib;
2195796c8dcSSimon Schubert VEC_safe_insert (mem_region_s, mem_region_list, ix, &new);
2205796c8dcSSimon Schubert }
2215796c8dcSSimon Schubert
2225796c8dcSSimon Schubert /*
2235796c8dcSSimon Schubert * Look up the memory region cooresponding to ADDR.
2245796c8dcSSimon Schubert */
2255796c8dcSSimon Schubert struct mem_region *
lookup_mem_region(CORE_ADDR addr)2265796c8dcSSimon Schubert lookup_mem_region (CORE_ADDR addr)
2275796c8dcSSimon Schubert {
2285796c8dcSSimon Schubert static struct mem_region region;
2295796c8dcSSimon Schubert struct mem_region *m;
2305796c8dcSSimon Schubert CORE_ADDR lo;
2315796c8dcSSimon Schubert CORE_ADDR hi;
2325796c8dcSSimon Schubert int ix;
2335796c8dcSSimon Schubert
2345796c8dcSSimon Schubert require_target_regions ();
2355796c8dcSSimon Schubert
2365796c8dcSSimon Schubert /* First we initialize LO and HI so that they describe the entire
2375796c8dcSSimon Schubert memory space. As we process the memory region chain, they are
2385796c8dcSSimon Schubert redefined to describe the minimal region containing ADDR. LO
2395796c8dcSSimon Schubert and HI are used in the case where no memory region is defined
2405796c8dcSSimon Schubert that contains ADDR. If a memory region is disabled, it is
2415796c8dcSSimon Schubert treated as if it does not exist. The initial values for LO
2425796c8dcSSimon Schubert and HI represent the bottom and top of memory. */
2435796c8dcSSimon Schubert
2445796c8dcSSimon Schubert lo = 0;
2455796c8dcSSimon Schubert hi = 0;
2465796c8dcSSimon Schubert
2475796c8dcSSimon Schubert /* Either find memory range containing ADDRESS, or set LO and HI
2485796c8dcSSimon Schubert to the nearest boundaries of an existing memory range.
2495796c8dcSSimon Schubert
2505796c8dcSSimon Schubert If we ever want to support a huge list of memory regions, this
2515796c8dcSSimon Schubert check should be replaced with a binary search (probably using
2525796c8dcSSimon Schubert VEC_lower_bound). */
2535796c8dcSSimon Schubert for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++)
2545796c8dcSSimon Schubert {
2555796c8dcSSimon Schubert if (m->enabled_p == 1)
2565796c8dcSSimon Schubert {
257c50c785cSJohn Marino /* If the address is in the memory region, return that
258c50c785cSJohn Marino memory range. */
2595796c8dcSSimon Schubert if (addr >= m->lo && (addr < m->hi || m->hi == 0))
2605796c8dcSSimon Schubert return m;
2615796c8dcSSimon Schubert
2625796c8dcSSimon Schubert /* This (correctly) won't match if m->hi == 0, representing
2635796c8dcSSimon Schubert the top of the address space, because CORE_ADDR is unsigned;
2645796c8dcSSimon Schubert no value of LO is less than zero. */
2655796c8dcSSimon Schubert if (addr >= m->hi && lo < m->hi)
2665796c8dcSSimon Schubert lo = m->hi;
2675796c8dcSSimon Schubert
2685796c8dcSSimon Schubert /* This will never set HI to zero; if we're here and ADDR
2695796c8dcSSimon Schubert is at or below M, and the region starts at zero, then ADDR
2705796c8dcSSimon Schubert would have been in the region. */
2715796c8dcSSimon Schubert if (addr <= m->lo && (hi == 0 || hi > m->lo))
2725796c8dcSSimon Schubert hi = m->lo;
2735796c8dcSSimon Schubert }
2745796c8dcSSimon Schubert }
2755796c8dcSSimon Schubert
2765796c8dcSSimon Schubert /* Because no region was found, we must cons up one based on what
2775796c8dcSSimon Schubert was learned above. */
2785796c8dcSSimon Schubert region.lo = lo;
2795796c8dcSSimon Schubert region.hi = hi;
2805796c8dcSSimon Schubert
2815796c8dcSSimon Schubert /* When no memory map is defined at all, we always return
2825796c8dcSSimon Schubert 'default_mem_attrib', so that we do not make all memory
2835796c8dcSSimon Schubert inaccessible for targets that don't provide a memory map. */
2845796c8dcSSimon Schubert if (inaccessible_by_default && !VEC_empty (mem_region_s, mem_region_list))
2855796c8dcSSimon Schubert region.attrib = unknown_mem_attrib;
2865796c8dcSSimon Schubert else
2875796c8dcSSimon Schubert region.attrib = default_mem_attrib;
2885796c8dcSSimon Schubert
2895796c8dcSSimon Schubert return ®ion;
2905796c8dcSSimon Schubert }
2915796c8dcSSimon Schubert
2925796c8dcSSimon Schubert /* Invalidate any memory regions fetched from the target. */
2935796c8dcSSimon Schubert
2945796c8dcSSimon Schubert void
invalidate_target_mem_regions(void)2955796c8dcSSimon Schubert invalidate_target_mem_regions (void)
2965796c8dcSSimon Schubert {
2975796c8dcSSimon Schubert if (!target_mem_regions_valid)
2985796c8dcSSimon Schubert return;
2995796c8dcSSimon Schubert
3005796c8dcSSimon Schubert target_mem_regions_valid = 0;
3015796c8dcSSimon Schubert VEC_free (mem_region_s, target_mem_region_list);
3025796c8dcSSimon Schubert if (mem_use_target)
3035796c8dcSSimon Schubert mem_region_list = NULL;
3045796c8dcSSimon Schubert }
3055796c8dcSSimon Schubert
306c50c785cSJohn Marino /* Clear memory region list. */
3075796c8dcSSimon Schubert
3085796c8dcSSimon Schubert static void
mem_clear(void)3095796c8dcSSimon Schubert mem_clear (void)
3105796c8dcSSimon Schubert {
3115796c8dcSSimon Schubert VEC_free (mem_region_s, mem_region_list);
3125796c8dcSSimon Schubert }
3135796c8dcSSimon Schubert
3145796c8dcSSimon Schubert
3155796c8dcSSimon Schubert static void
mem_command(char * args,int from_tty)3165796c8dcSSimon Schubert mem_command (char *args, int from_tty)
3175796c8dcSSimon Schubert {
3185796c8dcSSimon Schubert CORE_ADDR lo, hi;
3195796c8dcSSimon Schubert char *tok;
3205796c8dcSSimon Schubert struct mem_attrib attrib;
3215796c8dcSSimon Schubert
3225796c8dcSSimon Schubert if (!args)
3235796c8dcSSimon Schubert error_no_arg (_("No mem"));
3245796c8dcSSimon Schubert
3255796c8dcSSimon Schubert /* For "mem auto", switch back to using a target provided list. */
3265796c8dcSSimon Schubert if (strcmp (args, "auto") == 0)
3275796c8dcSSimon Schubert {
3285796c8dcSSimon Schubert if (mem_use_target)
3295796c8dcSSimon Schubert return;
3305796c8dcSSimon Schubert
3315796c8dcSSimon Schubert if (mem_region_list != target_mem_region_list)
3325796c8dcSSimon Schubert {
3335796c8dcSSimon Schubert mem_clear ();
3345796c8dcSSimon Schubert mem_region_list = target_mem_region_list;
3355796c8dcSSimon Schubert }
3365796c8dcSSimon Schubert
3375796c8dcSSimon Schubert mem_use_target = 1;
3385796c8dcSSimon Schubert return;
3395796c8dcSSimon Schubert }
3405796c8dcSSimon Schubert
3415796c8dcSSimon Schubert require_user_regions (from_tty);
3425796c8dcSSimon Schubert
3435796c8dcSSimon Schubert tok = strtok (args, " \t");
3445796c8dcSSimon Schubert if (!tok)
3455796c8dcSSimon Schubert error (_("no lo address"));
3465796c8dcSSimon Schubert lo = parse_and_eval_address (tok);
3475796c8dcSSimon Schubert
3485796c8dcSSimon Schubert tok = strtok (NULL, " \t");
3495796c8dcSSimon Schubert if (!tok)
3505796c8dcSSimon Schubert error (_("no hi address"));
3515796c8dcSSimon Schubert hi = parse_and_eval_address (tok);
3525796c8dcSSimon Schubert
3535796c8dcSSimon Schubert attrib = default_mem_attrib;
3545796c8dcSSimon Schubert while ((tok = strtok (NULL, " \t")) != NULL)
3555796c8dcSSimon Schubert {
3565796c8dcSSimon Schubert if (strcmp (tok, "rw") == 0)
3575796c8dcSSimon Schubert attrib.mode = MEM_RW;
3585796c8dcSSimon Schubert else if (strcmp (tok, "ro") == 0)
3595796c8dcSSimon Schubert attrib.mode = MEM_RO;
3605796c8dcSSimon Schubert else if (strcmp (tok, "wo") == 0)
3615796c8dcSSimon Schubert attrib.mode = MEM_WO;
3625796c8dcSSimon Schubert
3635796c8dcSSimon Schubert else if (strcmp (tok, "8") == 0)
3645796c8dcSSimon Schubert attrib.width = MEM_WIDTH_8;
3655796c8dcSSimon Schubert else if (strcmp (tok, "16") == 0)
3665796c8dcSSimon Schubert {
3675796c8dcSSimon Schubert if ((lo % 2 != 0) || (hi % 2 != 0))
3685796c8dcSSimon Schubert error (_("region bounds not 16 bit aligned"));
3695796c8dcSSimon Schubert attrib.width = MEM_WIDTH_16;
3705796c8dcSSimon Schubert }
3715796c8dcSSimon Schubert else if (strcmp (tok, "32") == 0)
3725796c8dcSSimon Schubert {
3735796c8dcSSimon Schubert if ((lo % 4 != 0) || (hi % 4 != 0))
3745796c8dcSSimon Schubert error (_("region bounds not 32 bit aligned"));
3755796c8dcSSimon Schubert attrib.width = MEM_WIDTH_32;
3765796c8dcSSimon Schubert }
3775796c8dcSSimon Schubert else if (strcmp (tok, "64") == 0)
3785796c8dcSSimon Schubert {
3795796c8dcSSimon Schubert if ((lo % 8 != 0) || (hi % 8 != 0))
3805796c8dcSSimon Schubert error (_("region bounds not 64 bit aligned"));
3815796c8dcSSimon Schubert attrib.width = MEM_WIDTH_64;
3825796c8dcSSimon Schubert }
3835796c8dcSSimon Schubert
3845796c8dcSSimon Schubert #if 0
3855796c8dcSSimon Schubert else if (strcmp (tok, "hwbreak") == 0)
3865796c8dcSSimon Schubert attrib.hwbreak = 1;
3875796c8dcSSimon Schubert else if (strcmp (tok, "swbreak") == 0)
3885796c8dcSSimon Schubert attrib.hwbreak = 0;
3895796c8dcSSimon Schubert #endif
3905796c8dcSSimon Schubert
3915796c8dcSSimon Schubert else if (strcmp (tok, "cache") == 0)
3925796c8dcSSimon Schubert attrib.cache = 1;
3935796c8dcSSimon Schubert else if (strcmp (tok, "nocache") == 0)
3945796c8dcSSimon Schubert attrib.cache = 0;
3955796c8dcSSimon Schubert
3965796c8dcSSimon Schubert #if 0
3975796c8dcSSimon Schubert else if (strcmp (tok, "verify") == 0)
3985796c8dcSSimon Schubert attrib.verify = 1;
3995796c8dcSSimon Schubert else if (strcmp (tok, "noverify") == 0)
4005796c8dcSSimon Schubert attrib.verify = 0;
4015796c8dcSSimon Schubert #endif
4025796c8dcSSimon Schubert
4035796c8dcSSimon Schubert else
4045796c8dcSSimon Schubert error (_("unknown attribute: %s"), tok);
4055796c8dcSSimon Schubert }
4065796c8dcSSimon Schubert
4075796c8dcSSimon Schubert create_mem_region (lo, hi, &attrib);
4085796c8dcSSimon Schubert }
4095796c8dcSSimon Schubert
4105796c8dcSSimon Schubert
4115796c8dcSSimon Schubert static void
mem_info_command(char * args,int from_tty)4125796c8dcSSimon Schubert mem_info_command (char *args, int from_tty)
4135796c8dcSSimon Schubert {
4145796c8dcSSimon Schubert struct mem_region *m;
4155796c8dcSSimon Schubert struct mem_attrib *attrib;
4165796c8dcSSimon Schubert int ix;
4175796c8dcSSimon Schubert
4185796c8dcSSimon Schubert if (mem_use_target)
4195796c8dcSSimon Schubert printf_filtered (_("Using memory regions provided by the target.\n"));
4205796c8dcSSimon Schubert else
4215796c8dcSSimon Schubert printf_filtered (_("Using user-defined memory regions.\n"));
4225796c8dcSSimon Schubert
4235796c8dcSSimon Schubert require_target_regions ();
4245796c8dcSSimon Schubert
4255796c8dcSSimon Schubert if (!mem_region_list)
4265796c8dcSSimon Schubert {
4275796c8dcSSimon Schubert printf_unfiltered (_("There are no memory regions defined.\n"));
4285796c8dcSSimon Schubert return;
4295796c8dcSSimon Schubert }
4305796c8dcSSimon Schubert
4315796c8dcSSimon Schubert printf_filtered ("Num ");
4325796c8dcSSimon Schubert printf_filtered ("Enb ");
4335796c8dcSSimon Schubert printf_filtered ("Low Addr ");
434*ef5ccd6cSJohn Marino if (gdbarch_addr_bit (target_gdbarch ()) > 32)
4355796c8dcSSimon Schubert printf_filtered (" ");
4365796c8dcSSimon Schubert printf_filtered ("High Addr ");
437*ef5ccd6cSJohn Marino if (gdbarch_addr_bit (target_gdbarch ()) > 32)
4385796c8dcSSimon Schubert printf_filtered (" ");
4395796c8dcSSimon Schubert printf_filtered ("Attrs ");
4405796c8dcSSimon Schubert printf_filtered ("\n");
4415796c8dcSSimon Schubert
4425796c8dcSSimon Schubert for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++)
4435796c8dcSSimon Schubert {
4445796c8dcSSimon Schubert char *tmp;
445cf7f2e2dSJohn Marino
4465796c8dcSSimon Schubert printf_filtered ("%-3d %-3c\t",
4475796c8dcSSimon Schubert m->number,
4485796c8dcSSimon Schubert m->enabled_p ? 'y' : 'n');
449*ef5ccd6cSJohn Marino if (gdbarch_addr_bit (target_gdbarch ()) <= 32)
4505796c8dcSSimon Schubert tmp = hex_string_custom ((unsigned long) m->lo, 8);
4515796c8dcSSimon Schubert else
4525796c8dcSSimon Schubert tmp = hex_string_custom ((unsigned long) m->lo, 16);
4535796c8dcSSimon Schubert
4545796c8dcSSimon Schubert printf_filtered ("%s ", tmp);
4555796c8dcSSimon Schubert
456*ef5ccd6cSJohn Marino if (gdbarch_addr_bit (target_gdbarch ()) <= 32)
4575796c8dcSSimon Schubert {
4585796c8dcSSimon Schubert if (m->hi == 0)
4595796c8dcSSimon Schubert tmp = "0x100000000";
4605796c8dcSSimon Schubert else
4615796c8dcSSimon Schubert tmp = hex_string_custom ((unsigned long) m->hi, 8);
4625796c8dcSSimon Schubert }
4635796c8dcSSimon Schubert else
4645796c8dcSSimon Schubert {
4655796c8dcSSimon Schubert if (m->hi == 0)
4665796c8dcSSimon Schubert tmp = "0x10000000000000000";
4675796c8dcSSimon Schubert else
4685796c8dcSSimon Schubert tmp = hex_string_custom ((unsigned long) m->hi, 16);
4695796c8dcSSimon Schubert }
4705796c8dcSSimon Schubert
4715796c8dcSSimon Schubert printf_filtered ("%s ", tmp);
4725796c8dcSSimon Schubert
4735796c8dcSSimon Schubert /* Print a token for each attribute.
4745796c8dcSSimon Schubert
4755796c8dcSSimon Schubert * FIXME: Should we output a comma after each token? It may
4765796c8dcSSimon Schubert * make it easier for users to read, but we'd lose the ability
4775796c8dcSSimon Schubert * to cut-and-paste the list of attributes when defining a new
4785796c8dcSSimon Schubert * region. Perhaps that is not important.
4795796c8dcSSimon Schubert *
4805796c8dcSSimon Schubert * FIXME: If more attributes are added to GDB, the output may
4815796c8dcSSimon Schubert * become cluttered and difficult for users to read. At that
4825796c8dcSSimon Schubert * time, we may want to consider printing tokens only if they
4835796c8dcSSimon Schubert * are different from the default attribute. */
4845796c8dcSSimon Schubert
4855796c8dcSSimon Schubert attrib = &m->attrib;
4865796c8dcSSimon Schubert switch (attrib->mode)
4875796c8dcSSimon Schubert {
4885796c8dcSSimon Schubert case MEM_RW:
4895796c8dcSSimon Schubert printf_filtered ("rw ");
4905796c8dcSSimon Schubert break;
4915796c8dcSSimon Schubert case MEM_RO:
4925796c8dcSSimon Schubert printf_filtered ("ro ");
4935796c8dcSSimon Schubert break;
4945796c8dcSSimon Schubert case MEM_WO:
4955796c8dcSSimon Schubert printf_filtered ("wo ");
4965796c8dcSSimon Schubert break;
4975796c8dcSSimon Schubert case MEM_FLASH:
4985796c8dcSSimon Schubert printf_filtered ("flash blocksize 0x%x ", attrib->blocksize);
4995796c8dcSSimon Schubert break;
5005796c8dcSSimon Schubert }
5015796c8dcSSimon Schubert
5025796c8dcSSimon Schubert switch (attrib->width)
5035796c8dcSSimon Schubert {
5045796c8dcSSimon Schubert case MEM_WIDTH_8:
5055796c8dcSSimon Schubert printf_filtered ("8 ");
5065796c8dcSSimon Schubert break;
5075796c8dcSSimon Schubert case MEM_WIDTH_16:
5085796c8dcSSimon Schubert printf_filtered ("16 ");
5095796c8dcSSimon Schubert break;
5105796c8dcSSimon Schubert case MEM_WIDTH_32:
5115796c8dcSSimon Schubert printf_filtered ("32 ");
5125796c8dcSSimon Schubert break;
5135796c8dcSSimon Schubert case MEM_WIDTH_64:
5145796c8dcSSimon Schubert printf_filtered ("64 ");
5155796c8dcSSimon Schubert break;
5165796c8dcSSimon Schubert case MEM_WIDTH_UNSPECIFIED:
5175796c8dcSSimon Schubert break;
5185796c8dcSSimon Schubert }
5195796c8dcSSimon Schubert
5205796c8dcSSimon Schubert #if 0
5215796c8dcSSimon Schubert if (attrib->hwbreak)
5225796c8dcSSimon Schubert printf_filtered ("hwbreak");
5235796c8dcSSimon Schubert else
5245796c8dcSSimon Schubert printf_filtered ("swbreak");
5255796c8dcSSimon Schubert #endif
5265796c8dcSSimon Schubert
5275796c8dcSSimon Schubert if (attrib->cache)
5285796c8dcSSimon Schubert printf_filtered ("cache ");
5295796c8dcSSimon Schubert else
5305796c8dcSSimon Schubert printf_filtered ("nocache ");
5315796c8dcSSimon Schubert
5325796c8dcSSimon Schubert #if 0
5335796c8dcSSimon Schubert if (attrib->verify)
5345796c8dcSSimon Schubert printf_filtered ("verify ");
5355796c8dcSSimon Schubert else
5365796c8dcSSimon Schubert printf_filtered ("noverify ");
5375796c8dcSSimon Schubert #endif
5385796c8dcSSimon Schubert
5395796c8dcSSimon Schubert printf_filtered ("\n");
5405796c8dcSSimon Schubert
5415796c8dcSSimon Schubert gdb_flush (gdb_stdout);
5425796c8dcSSimon Schubert }
5435796c8dcSSimon Schubert }
5445796c8dcSSimon Schubert
5455796c8dcSSimon Schubert
5465796c8dcSSimon Schubert /* Enable the memory region number NUM. */
5475796c8dcSSimon Schubert
5485796c8dcSSimon Schubert static void
mem_enable(int num)5495796c8dcSSimon Schubert mem_enable (int num)
5505796c8dcSSimon Schubert {
5515796c8dcSSimon Schubert struct mem_region *m;
5525796c8dcSSimon Schubert int ix;
5535796c8dcSSimon Schubert
5545796c8dcSSimon Schubert for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++)
5555796c8dcSSimon Schubert if (m->number == num)
5565796c8dcSSimon Schubert {
5575796c8dcSSimon Schubert m->enabled_p = 1;
5585796c8dcSSimon Schubert return;
5595796c8dcSSimon Schubert }
5605796c8dcSSimon Schubert printf_unfiltered (_("No memory region number %d.\n"), num);
5615796c8dcSSimon Schubert }
5625796c8dcSSimon Schubert
5635796c8dcSSimon Schubert static void
mem_enable_command(char * args,int from_tty)5645796c8dcSSimon Schubert mem_enable_command (char *args, int from_tty)
5655796c8dcSSimon Schubert {
5665796c8dcSSimon Schubert int num;
5675796c8dcSSimon Schubert struct mem_region *m;
5685796c8dcSSimon Schubert int ix;
5695796c8dcSSimon Schubert
5705796c8dcSSimon Schubert require_user_regions (from_tty);
5715796c8dcSSimon Schubert
5725796c8dcSSimon Schubert target_dcache_invalidate ();
5735796c8dcSSimon Schubert
574c50c785cSJohn Marino if (args == NULL || *args == '\0')
575c50c785cSJohn Marino { /* Enable all mem regions. */
5765796c8dcSSimon Schubert for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++)
5775796c8dcSSimon Schubert m->enabled_p = 1;
5785796c8dcSSimon Schubert }
5795796c8dcSSimon Schubert else
5805796c8dcSSimon Schubert {
581c50c785cSJohn Marino struct get_number_or_range_state state;
5825796c8dcSSimon Schubert
583c50c785cSJohn Marino init_number_or_range (&state, args);
584c50c785cSJohn Marino while (!state.finished)
585c50c785cSJohn Marino {
586c50c785cSJohn Marino num = get_number_or_range (&state);
5875796c8dcSSimon Schubert mem_enable (num);
588c50c785cSJohn Marino }
5895796c8dcSSimon Schubert }
5905796c8dcSSimon Schubert }
5915796c8dcSSimon Schubert
5925796c8dcSSimon Schubert
5935796c8dcSSimon Schubert /* Disable the memory region number NUM. */
5945796c8dcSSimon Schubert
5955796c8dcSSimon Schubert static void
mem_disable(int num)5965796c8dcSSimon Schubert mem_disable (int num)
5975796c8dcSSimon Schubert {
5985796c8dcSSimon Schubert struct mem_region *m;
5995796c8dcSSimon Schubert int ix;
6005796c8dcSSimon Schubert
6015796c8dcSSimon Schubert for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++)
6025796c8dcSSimon Schubert if (m->number == num)
6035796c8dcSSimon Schubert {
6045796c8dcSSimon Schubert m->enabled_p = 0;
6055796c8dcSSimon Schubert return;
6065796c8dcSSimon Schubert }
6075796c8dcSSimon Schubert printf_unfiltered (_("No memory region number %d.\n"), num);
6085796c8dcSSimon Schubert }
6095796c8dcSSimon Schubert
6105796c8dcSSimon Schubert static void
mem_disable_command(char * args,int from_tty)6115796c8dcSSimon Schubert mem_disable_command (char *args, int from_tty)
6125796c8dcSSimon Schubert {
6135796c8dcSSimon Schubert int num;
6145796c8dcSSimon Schubert struct mem_region *m;
6155796c8dcSSimon Schubert int ix;
6165796c8dcSSimon Schubert
6175796c8dcSSimon Schubert require_user_regions (from_tty);
6185796c8dcSSimon Schubert
6195796c8dcSSimon Schubert target_dcache_invalidate ();
6205796c8dcSSimon Schubert
621c50c785cSJohn Marino if (args == NULL || *args == '\0')
6225796c8dcSSimon Schubert {
6235796c8dcSSimon Schubert for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++)
6245796c8dcSSimon Schubert m->enabled_p = 0;
6255796c8dcSSimon Schubert }
6265796c8dcSSimon Schubert else
6275796c8dcSSimon Schubert {
628c50c785cSJohn Marino struct get_number_or_range_state state;
6295796c8dcSSimon Schubert
630c50c785cSJohn Marino init_number_or_range (&state, args);
631c50c785cSJohn Marino while (!state.finished)
632c50c785cSJohn Marino {
633c50c785cSJohn Marino num = get_number_or_range (&state);
6345796c8dcSSimon Schubert mem_disable (num);
635c50c785cSJohn Marino }
6365796c8dcSSimon Schubert }
6375796c8dcSSimon Schubert }
6385796c8dcSSimon Schubert
6395796c8dcSSimon Schubert /* Delete the memory region number NUM. */
6405796c8dcSSimon Schubert
6415796c8dcSSimon Schubert static void
mem_delete(int num)6425796c8dcSSimon Schubert mem_delete (int num)
6435796c8dcSSimon Schubert {
644cf7f2e2dSJohn Marino struct mem_region *m;
6455796c8dcSSimon Schubert int ix;
6465796c8dcSSimon Schubert
6475796c8dcSSimon Schubert if (!mem_region_list)
6485796c8dcSSimon Schubert {
6495796c8dcSSimon Schubert printf_unfiltered (_("No memory region number %d.\n"), num);
6505796c8dcSSimon Schubert return;
6515796c8dcSSimon Schubert }
6525796c8dcSSimon Schubert
6535796c8dcSSimon Schubert for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++)
6545796c8dcSSimon Schubert if (m->number == num)
6555796c8dcSSimon Schubert break;
6565796c8dcSSimon Schubert
6575796c8dcSSimon Schubert if (m == NULL)
6585796c8dcSSimon Schubert {
6595796c8dcSSimon Schubert printf_unfiltered (_("No memory region number %d.\n"), num);
6605796c8dcSSimon Schubert return;
6615796c8dcSSimon Schubert }
6625796c8dcSSimon Schubert
6635796c8dcSSimon Schubert VEC_ordered_remove (mem_region_s, mem_region_list, ix);
6645796c8dcSSimon Schubert }
6655796c8dcSSimon Schubert
6665796c8dcSSimon Schubert static void
mem_delete_command(char * args,int from_tty)6675796c8dcSSimon Schubert mem_delete_command (char *args, int from_tty)
6685796c8dcSSimon Schubert {
6695796c8dcSSimon Schubert int num;
670c50c785cSJohn Marino struct get_number_or_range_state state;
6715796c8dcSSimon Schubert
6725796c8dcSSimon Schubert require_user_regions (from_tty);
6735796c8dcSSimon Schubert
6745796c8dcSSimon Schubert target_dcache_invalidate ();
6755796c8dcSSimon Schubert
676c50c785cSJohn Marino if (args == NULL || *args == '\0')
6775796c8dcSSimon Schubert {
6785796c8dcSSimon Schubert if (query (_("Delete all memory regions? ")))
6795796c8dcSSimon Schubert mem_clear ();
6805796c8dcSSimon Schubert dont_repeat ();
6815796c8dcSSimon Schubert return;
6825796c8dcSSimon Schubert }
6835796c8dcSSimon Schubert
684c50c785cSJohn Marino init_number_or_range (&state, args);
685c50c785cSJohn Marino while (!state.finished)
6865796c8dcSSimon Schubert {
687c50c785cSJohn Marino num = get_number_or_range (&state);
6885796c8dcSSimon Schubert mem_delete (num);
6895796c8dcSSimon Schubert }
6905796c8dcSSimon Schubert
6915796c8dcSSimon Schubert dont_repeat ();
6925796c8dcSSimon Schubert }
6935796c8dcSSimon Schubert
6945796c8dcSSimon Schubert static void
dummy_cmd(char * args,int from_tty)6955796c8dcSSimon Schubert dummy_cmd (char *args, int from_tty)
6965796c8dcSSimon Schubert {
6975796c8dcSSimon Schubert }
6985796c8dcSSimon Schubert
6995796c8dcSSimon Schubert extern initialize_file_ftype _initialize_mem; /* -Wmissing-prototype */
7005796c8dcSSimon Schubert
7015796c8dcSSimon Schubert static struct cmd_list_element *mem_set_cmdlist;
7025796c8dcSSimon Schubert static struct cmd_list_element *mem_show_cmdlist;
7035796c8dcSSimon Schubert
7045796c8dcSSimon Schubert void
_initialize_mem(void)7055796c8dcSSimon Schubert _initialize_mem (void)
7065796c8dcSSimon Schubert {
7075796c8dcSSimon Schubert add_com ("mem", class_vars, mem_command, _("\
7085796c8dcSSimon Schubert Define attributes for memory region or reset memory region handling to\n\
7095796c8dcSSimon Schubert target-based.\n\
7105796c8dcSSimon Schubert Usage: mem auto\n\
7115796c8dcSSimon Schubert mem <lo addr> <hi addr> [<mode> <width> <cache>],\n\
7125796c8dcSSimon Schubert where <mode> may be rw (read/write), ro (read-only) or wo (write-only),\n\
7135796c8dcSSimon Schubert <width> may be 8, 16, 32, or 64, and\n\
7145796c8dcSSimon Schubert <cache> may be cache or nocache"));
7155796c8dcSSimon Schubert
7165796c8dcSSimon Schubert add_cmd ("mem", class_vars, mem_enable_command, _("\
7175796c8dcSSimon Schubert Enable memory region.\n\
7185796c8dcSSimon Schubert Arguments are the code numbers of the memory regions to enable.\n\
719c50c785cSJohn Marino Usage: enable mem <code number>...\n\
7205796c8dcSSimon Schubert Do \"info mem\" to see current list of code numbers."), &enablelist);
7215796c8dcSSimon Schubert
7225796c8dcSSimon Schubert add_cmd ("mem", class_vars, mem_disable_command, _("\
7235796c8dcSSimon Schubert Disable memory region.\n\
7245796c8dcSSimon Schubert Arguments are the code numbers of the memory regions to disable.\n\
725c50c785cSJohn Marino Usage: disable mem <code number>...\n\
7265796c8dcSSimon Schubert Do \"info mem\" to see current list of code numbers."), &disablelist);
7275796c8dcSSimon Schubert
7285796c8dcSSimon Schubert add_cmd ("mem", class_vars, mem_delete_command, _("\
7295796c8dcSSimon Schubert Delete memory region.\n\
7305796c8dcSSimon Schubert Arguments are the code numbers of the memory regions to delete.\n\
731c50c785cSJohn Marino Usage: delete mem <code number>...\n\
7325796c8dcSSimon Schubert Do \"info mem\" to see current list of code numbers."), &deletelist);
7335796c8dcSSimon Schubert
7345796c8dcSSimon Schubert add_info ("mem", mem_info_command,
7355796c8dcSSimon Schubert _("Memory region attributes"));
7365796c8dcSSimon Schubert
7375796c8dcSSimon Schubert add_prefix_cmd ("mem", class_vars, dummy_cmd, _("\
7385796c8dcSSimon Schubert Memory regions settings"),
7395796c8dcSSimon Schubert &mem_set_cmdlist, "set mem ",
7405796c8dcSSimon Schubert 0/* allow-unknown */, &setlist);
7415796c8dcSSimon Schubert add_prefix_cmd ("mem", class_vars, dummy_cmd, _("\
7425796c8dcSSimon Schubert Memory regions settings"),
7435796c8dcSSimon Schubert &mem_show_cmdlist, "show mem ",
7445796c8dcSSimon Schubert 0/* allow-unknown */, &showlist);
7455796c8dcSSimon Schubert
7465796c8dcSSimon Schubert add_setshow_boolean_cmd ("inaccessible-by-default", no_class,
7475796c8dcSSimon Schubert &inaccessible_by_default, _("\
7485796c8dcSSimon Schubert Set handling of unknown memory regions."), _("\
7495796c8dcSSimon Schubert Show handling of unknown memory regions."), _("\
7505796c8dcSSimon Schubert If on, and some memory map is defined, debugger will emit errors on\n\
7515796c8dcSSimon Schubert accesses to memory not defined in the memory map. If off, accesses to all\n\
7525796c8dcSSimon Schubert memory addresses will be allowed."),
7535796c8dcSSimon Schubert NULL,
7545796c8dcSSimon Schubert show_inaccessible_by_default,
7555796c8dcSSimon Schubert &mem_set_cmdlist,
7565796c8dcSSimon Schubert &mem_show_cmdlist);
7575796c8dcSSimon Schubert }
758