xref: /netbsd/external/gpl3/gdb/dist/gdb/memattr.c (revision 1424dfb3)
166e63ce3Schristos /* Memory attributes support, for GDB.
266e63ce3Schristos 
3*1424dfb3Schristos    Copyright (C) 2001-2020 Free Software Foundation, Inc.
466e63ce3Schristos 
566e63ce3Schristos    This file is part of GDB.
666e63ce3Schristos 
766e63ce3Schristos    This program is free software; you can redistribute it and/or modify
866e63ce3Schristos    it under the terms of the GNU General Public License as published by
966e63ce3Schristos    the Free Software Foundation; either version 3 of the License, or
1066e63ce3Schristos    (at your option) any later version.
1166e63ce3Schristos 
1266e63ce3Schristos    This program is distributed in the hope that it will be useful,
1366e63ce3Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
1466e63ce3Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1566e63ce3Schristos    GNU General Public License for more details.
1666e63ce3Schristos 
1766e63ce3Schristos    You should have received a copy of the GNU General Public License
1866e63ce3Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
1966e63ce3Schristos 
2066e63ce3Schristos #include "defs.h"
2166e63ce3Schristos #include "command.h"
2266e63ce3Schristos #include "gdbcmd.h"
2366e63ce3Schristos #include "memattr.h"
2466e63ce3Schristos #include "target.h"
257af5a897Schristos #include "target-dcache.h"
2666e63ce3Schristos #include "value.h"
2766e63ce3Schristos #include "language.h"
2866e63ce3Schristos #include "breakpoint.h"
2966e63ce3Schristos #include "cli/cli-utils.h"
3007163879Schristos #include <algorithm>
31*1424dfb3Schristos #include "gdbarch.h"
3266e63ce3Schristos 
3307163879Schristos static std::vector<mem_region> user_mem_region_list, target_mem_region_list;
3407163879Schristos static std::vector<mem_region> *mem_region_list = &target_mem_region_list;
3566e63ce3Schristos static int mem_number = 0;
3666e63ce3Schristos 
3766e63ce3Schristos /* If this flag is set, the memory region list should be automatically
3866e63ce3Schristos    updated from the target.  If it is clear, the list is user-controlled
3966e63ce3Schristos    and should be left alone.  */
4007163879Schristos 
4107163879Schristos static bool
mem_use_target()4207163879Schristos mem_use_target ()
4307163879Schristos {
4407163879Schristos   return mem_region_list == &target_mem_region_list;
4507163879Schristos }
4666e63ce3Schristos 
4766e63ce3Schristos /* If this flag is set, we have tried to fetch the target memory regions
4866e63ce3Schristos    since the last time it was invalidated.  If that list is still
4966e63ce3Schristos    empty, then the target can't supply memory regions.  */
5007163879Schristos static bool target_mem_regions_valid;
5166e63ce3Schristos 
5266e63ce3Schristos /* If this flag is set, gdb will assume that memory ranges not
5366e63ce3Schristos    specified by the memory map have type MEM_NONE, and will
5466e63ce3Schristos    emit errors on all accesses to that memory.  */
55*1424dfb3Schristos static bool inaccessible_by_default = true;
5666e63ce3Schristos 
5766e63ce3Schristos static void
show_inaccessible_by_default(struct ui_file * file,int from_tty,struct cmd_list_element * c,const char * value)5866e63ce3Schristos show_inaccessible_by_default (struct ui_file *file, int from_tty,
5966e63ce3Schristos 			      struct cmd_list_element *c,
6066e63ce3Schristos 			      const char *value)
6166e63ce3Schristos {
6266e63ce3Schristos   if (inaccessible_by_default)
6366e63ce3Schristos     fprintf_filtered (file, _("Unknown memory addresses will "
6466e63ce3Schristos 			      "be treated as inaccessible.\n"));
6566e63ce3Schristos   else
6666e63ce3Schristos     fprintf_filtered (file, _("Unknown memory addresses "
6766e63ce3Schristos 			      "will be treated as RAM.\n"));
6866e63ce3Schristos }
6966e63ce3Schristos 
7066e63ce3Schristos /* This function should be called before any command which would
7166e63ce3Schristos    modify the memory region list.  It will handle switching from
7266e63ce3Schristos    a target-provided list to a local list, if necessary.  */
7366e63ce3Schristos 
7466e63ce3Schristos static void
require_user_regions(int from_tty)7566e63ce3Schristos require_user_regions (int from_tty)
7666e63ce3Schristos {
7766e63ce3Schristos   /* If we're already using a user-provided list, nothing to do.  */
7807163879Schristos   if (!mem_use_target ())
7966e63ce3Schristos     return;
8066e63ce3Schristos 
8166e63ce3Schristos   /* Switch to a user-provided list (possibly a copy of the current
8266e63ce3Schristos      one).  */
8307163879Schristos   mem_region_list = &user_mem_region_list;
8466e63ce3Schristos 
8566e63ce3Schristos   /* If we don't have a target-provided region list yet, then
8666e63ce3Schristos      no need to warn.  */
8707163879Schristos   if (target_mem_region_list.empty ())
8866e63ce3Schristos     return;
8966e63ce3Schristos 
9066e63ce3Schristos   /* Otherwise, let the user know how to get back.  */
9166e63ce3Schristos   if (from_tty)
9266e63ce3Schristos     warning (_("Switching to manual control of memory regions; use "
9366e63ce3Schristos 	       "\"mem auto\" to fetch regions from the target again."));
9466e63ce3Schristos 
9507163879Schristos   /* And create a new list (copy of the target-supplied regions) for the user
9607163879Schristos      to modify.  */
9707163879Schristos   user_mem_region_list = target_mem_region_list;
9866e63ce3Schristos }
9966e63ce3Schristos 
10066e63ce3Schristos /* This function should be called before any command which would
10166e63ce3Schristos    read the memory region list, other than those which call
10266e63ce3Schristos    require_user_regions.  It will handle fetching the
10366e63ce3Schristos    target-provided list, if necessary.  */
10466e63ce3Schristos 
10566e63ce3Schristos static void
require_target_regions(void)10666e63ce3Schristos require_target_regions (void)
10766e63ce3Schristos {
10807163879Schristos   if (mem_use_target () && !target_mem_regions_valid)
10966e63ce3Schristos     {
11007163879Schristos       target_mem_regions_valid = true;
11166e63ce3Schristos       target_mem_region_list = target_memory_map ();
11266e63ce3Schristos     }
11366e63ce3Schristos }
11466e63ce3Schristos 
11507163879Schristos /* Create a new user-defined memory region.  */
11607163879Schristos 
11766e63ce3Schristos static void
create_user_mem_region(CORE_ADDR lo,CORE_ADDR hi,const mem_attrib & attrib)11807163879Schristos create_user_mem_region (CORE_ADDR lo, CORE_ADDR hi,
11907163879Schristos 			const mem_attrib &attrib)
12066e63ce3Schristos {
12166e63ce3Schristos   /* lo == hi is a useless empty region.  */
12266e63ce3Schristos   if (lo >= hi && hi != 0)
12366e63ce3Schristos     {
12466e63ce3Schristos       printf_unfiltered (_("invalid memory region: low >= high\n"));
12566e63ce3Schristos       return;
12666e63ce3Schristos     }
12766e63ce3Schristos 
12807163879Schristos   mem_region newobj (lo, hi, attrib);
12966e63ce3Schristos 
13007163879Schristos   auto it = std::lower_bound (user_mem_region_list.begin (),
13107163879Schristos 			      user_mem_region_list.end (),
13207163879Schristos 			      newobj);
13307163879Schristos   int ix = std::distance (user_mem_region_list.begin (), it);
13466e63ce3Schristos 
13566e63ce3Schristos   /* Check for an overlapping memory region.  We only need to check
136*1424dfb3Schristos      in the vincinity - at most one before and one after the
13766e63ce3Schristos      insertion point.  */
13807163879Schristos   for (int i = ix - 1; i < ix + 1; i++)
13966e63ce3Schristos     {
14066e63ce3Schristos       if (i < 0)
14166e63ce3Schristos 	continue;
14207163879Schristos       if (i >= user_mem_region_list.size ())
14366e63ce3Schristos 	continue;
14466e63ce3Schristos 
14507163879Schristos       mem_region &n = user_mem_region_list[i];
14666e63ce3Schristos 
14707163879Schristos       if ((lo >= n.lo && (lo < n.hi || n.hi == 0))
14807163879Schristos 	  || (hi > n.lo && (hi <= n.hi || n.hi == 0))
14907163879Schristos 	  || (lo <= n.lo && ((hi >= n.hi && n.hi != 0) || hi == 0)))
15066e63ce3Schristos 	{
15166e63ce3Schristos 	  printf_unfiltered (_("overlapping memory region\n"));
15266e63ce3Schristos 	  return;
15366e63ce3Schristos 	}
15466e63ce3Schristos     }
15566e63ce3Schristos 
156ed6a76a9Schristos   newobj.number = ++mem_number;
15707163879Schristos   user_mem_region_list.insert (it, newobj);
15866e63ce3Schristos }
15966e63ce3Schristos 
16007163879Schristos /* Look up the memory region corresponding to ADDR.  */
16107163879Schristos 
16266e63ce3Schristos struct mem_region *
lookup_mem_region(CORE_ADDR addr)16366e63ce3Schristos lookup_mem_region (CORE_ADDR addr)
16466e63ce3Schristos {
16507163879Schristos   static struct mem_region region (0, 0);
16666e63ce3Schristos   CORE_ADDR lo;
16766e63ce3Schristos   CORE_ADDR hi;
16866e63ce3Schristos 
16966e63ce3Schristos   require_target_regions ();
17066e63ce3Schristos 
17166e63ce3Schristos   /* First we initialize LO and HI so that they describe the entire
17266e63ce3Schristos      memory space.  As we process the memory region chain, they are
17366e63ce3Schristos      redefined to describe the minimal region containing ADDR.  LO
17466e63ce3Schristos      and HI are used in the case where no memory region is defined
17566e63ce3Schristos      that contains ADDR.  If a memory region is disabled, it is
17666e63ce3Schristos      treated as if it does not exist.  The initial values for LO
17766e63ce3Schristos      and HI represent the bottom and top of memory.  */
17866e63ce3Schristos 
17966e63ce3Schristos   lo = 0;
18066e63ce3Schristos   hi = 0;
18166e63ce3Schristos 
18207163879Schristos   /* Either find memory range containing ADDR, or set LO and HI
18366e63ce3Schristos      to the nearest boundaries of an existing memory range.
18466e63ce3Schristos 
18566e63ce3Schristos      If we ever want to support a huge list of memory regions, this
18666e63ce3Schristos      check should be replaced with a binary search (probably using
18766e63ce3Schristos      VEC_lower_bound).  */
18807163879Schristos   for (mem_region &m : *mem_region_list)
18966e63ce3Schristos     {
19007163879Schristos       if (m.enabled_p == 1)
19166e63ce3Schristos 	{
19266e63ce3Schristos 	  /* If the address is in the memory region, return that
19366e63ce3Schristos 	     memory range.  */
19407163879Schristos 	  if (addr >= m.lo && (addr < m.hi || m.hi == 0))
19507163879Schristos 	    return &m;
19666e63ce3Schristos 
19766e63ce3Schristos 	  /* This (correctly) won't match if m->hi == 0, representing
19866e63ce3Schristos 	     the top of the address space, because CORE_ADDR is unsigned;
19966e63ce3Schristos 	     no value of LO is less than zero.  */
20007163879Schristos 	  if (addr >= m.hi && lo < m.hi)
20107163879Schristos 	    lo = m.hi;
20266e63ce3Schristos 
20366e63ce3Schristos 	  /* This will never set HI to zero; if we're here and ADDR
20466e63ce3Schristos 	     is at or below M, and the region starts at zero, then ADDR
20566e63ce3Schristos 	     would have been in the region.  */
20607163879Schristos 	  if (addr <= m.lo && (hi == 0 || hi > m.lo))
20707163879Schristos 	    hi = m.lo;
20866e63ce3Schristos 	}
20966e63ce3Schristos     }
21066e63ce3Schristos 
21166e63ce3Schristos   /* Because no region was found, we must cons up one based on what
21266e63ce3Schristos      was learned above.  */
21366e63ce3Schristos   region.lo = lo;
21466e63ce3Schristos   region.hi = hi;
21566e63ce3Schristos 
21666e63ce3Schristos   /* When no memory map is defined at all, we always return
21766e63ce3Schristos      'default_mem_attrib', so that we do not make all memory
21866e63ce3Schristos      inaccessible for targets that don't provide a memory map.  */
21907163879Schristos   if (inaccessible_by_default && !mem_region_list->empty ())
22007163879Schristos     region.attrib = mem_attrib::unknown ();
22166e63ce3Schristos   else
22207163879Schristos     region.attrib = mem_attrib ();
22366e63ce3Schristos 
22466e63ce3Schristos   return &region;
22566e63ce3Schristos }
22666e63ce3Schristos 
22766e63ce3Schristos /* Invalidate any memory regions fetched from the target.  */
22866e63ce3Schristos 
22966e63ce3Schristos void
invalidate_target_mem_regions(void)23066e63ce3Schristos invalidate_target_mem_regions (void)
23166e63ce3Schristos {
23266e63ce3Schristos   if (!target_mem_regions_valid)
23366e63ce3Schristos     return;
23466e63ce3Schristos 
23507163879Schristos   target_mem_regions_valid = false;
23607163879Schristos   target_mem_region_list.clear ();
23766e63ce3Schristos }
23866e63ce3Schristos 
23907163879Schristos /* Clear user-defined memory region list.  */
24066e63ce3Schristos 
24166e63ce3Schristos static void
user_mem_clear(void)24207163879Schristos user_mem_clear (void)
24366e63ce3Schristos {
24407163879Schristos   user_mem_region_list.clear ();
24566e63ce3Schristos }
24666e63ce3Schristos 
24766e63ce3Schristos 
24866e63ce3Schristos static void
mem_command(const char * args,int from_tty)24907163879Schristos mem_command (const char *args, int from_tty)
25066e63ce3Schristos {
25166e63ce3Schristos   CORE_ADDR lo, hi;
25266e63ce3Schristos 
25366e63ce3Schristos   if (!args)
25466e63ce3Schristos     error_no_arg (_("No mem"));
25566e63ce3Schristos 
25666e63ce3Schristos   /* For "mem auto", switch back to using a target provided list.  */
25766e63ce3Schristos   if (strcmp (args, "auto") == 0)
25866e63ce3Schristos     {
25907163879Schristos       if (mem_use_target ())
26066e63ce3Schristos 	return;
26166e63ce3Schristos 
26207163879Schristos       user_mem_clear ();
26307163879Schristos       mem_region_list = &target_mem_region_list;
26466e63ce3Schristos 
26566e63ce3Schristos       return;
26666e63ce3Schristos     }
26766e63ce3Schristos 
26866e63ce3Schristos   require_user_regions (from_tty);
26966e63ce3Schristos 
27007163879Schristos   std::string tok = extract_arg (&args);
27107163879Schristos   if (tok == "")
27266e63ce3Schristos     error (_("no lo address"));
27307163879Schristos   lo = parse_and_eval_address (tok.c_str ());
27466e63ce3Schristos 
27507163879Schristos   tok = extract_arg (&args);
27607163879Schristos   if (tok == "")
27766e63ce3Schristos     error (_("no hi address"));
27807163879Schristos   hi = parse_and_eval_address (tok.c_str ());
27966e63ce3Schristos 
28007163879Schristos   mem_attrib attrib;
28107163879Schristos   while ((tok = extract_arg (&args)) != "")
28266e63ce3Schristos     {
28307163879Schristos       if (tok == "rw")
28466e63ce3Schristos 	attrib.mode = MEM_RW;
28507163879Schristos       else if (tok == "ro")
28666e63ce3Schristos 	attrib.mode = MEM_RO;
28707163879Schristos       else if (tok == "wo")
28866e63ce3Schristos 	attrib.mode = MEM_WO;
28966e63ce3Schristos 
29007163879Schristos       else if (tok == "8")
29166e63ce3Schristos 	attrib.width = MEM_WIDTH_8;
29207163879Schristos       else if (tok == "16")
29366e63ce3Schristos 	{
29466e63ce3Schristos 	  if ((lo % 2 != 0) || (hi % 2 != 0))
29566e63ce3Schristos 	    error (_("region bounds not 16 bit aligned"));
29666e63ce3Schristos 	  attrib.width = MEM_WIDTH_16;
29766e63ce3Schristos 	}
29807163879Schristos       else if (tok == "32")
29966e63ce3Schristos 	{
30066e63ce3Schristos 	  if ((lo % 4 != 0) || (hi % 4 != 0))
30166e63ce3Schristos 	    error (_("region bounds not 32 bit aligned"));
30266e63ce3Schristos 	  attrib.width = MEM_WIDTH_32;
30366e63ce3Schristos 	}
30407163879Schristos       else if (tok == "64")
30566e63ce3Schristos 	{
30666e63ce3Schristos 	  if ((lo % 8 != 0) || (hi % 8 != 0))
30766e63ce3Schristos 	    error (_("region bounds not 64 bit aligned"));
30866e63ce3Schristos 	  attrib.width = MEM_WIDTH_64;
30966e63ce3Schristos 	}
31066e63ce3Schristos 
31166e63ce3Schristos #if 0
31207163879Schristos       else if (tok == "hwbreak")
31366e63ce3Schristos 	attrib.hwbreak = 1;
31407163879Schristos       else if (tok == "swbreak")
31566e63ce3Schristos 	attrib.hwbreak = 0;
31666e63ce3Schristos #endif
31766e63ce3Schristos 
31807163879Schristos       else if (tok == "cache")
31966e63ce3Schristos 	attrib.cache = 1;
32007163879Schristos       else if (tok == "nocache")
32166e63ce3Schristos 	attrib.cache = 0;
32266e63ce3Schristos 
32366e63ce3Schristos #if 0
32407163879Schristos       else if (tok == "verify")
32566e63ce3Schristos 	attrib.verify = 1;
32607163879Schristos       else if (tok == "noverify")
32766e63ce3Schristos 	attrib.verify = 0;
32866e63ce3Schristos #endif
32966e63ce3Schristos 
33066e63ce3Schristos       else
33107163879Schristos 	error (_("unknown attribute: %s"), tok.c_str ());
33266e63ce3Schristos     }
33366e63ce3Schristos 
33407163879Schristos   create_user_mem_region (lo, hi, attrib);
33566e63ce3Schristos }
33666e63ce3Schristos 
33766e63ce3Schristos 
33866e63ce3Schristos static void
info_mem_command(const char * args,int from_tty)33907163879Schristos info_mem_command (const char *args, int from_tty)
34066e63ce3Schristos {
34107163879Schristos   if (mem_use_target ())
34266e63ce3Schristos     printf_filtered (_("Using memory regions provided by the target.\n"));
34366e63ce3Schristos   else
34466e63ce3Schristos     printf_filtered (_("Using user-defined memory regions.\n"));
34566e63ce3Schristos 
34666e63ce3Schristos   require_target_regions ();
34766e63ce3Schristos 
34807163879Schristos   if (mem_region_list->empty ())
34966e63ce3Schristos     {
35066e63ce3Schristos       printf_unfiltered (_("There are no memory regions defined.\n"));
35166e63ce3Schristos       return;
35266e63ce3Schristos     }
35366e63ce3Schristos 
35466e63ce3Schristos   printf_filtered ("Num ");
35566e63ce3Schristos   printf_filtered ("Enb ");
35666e63ce3Schristos   printf_filtered ("Low Addr   ");
35748596154Schristos   if (gdbarch_addr_bit (target_gdbarch ()) > 32)
35866e63ce3Schristos     printf_filtered ("        ");
35966e63ce3Schristos   printf_filtered ("High Addr  ");
36048596154Schristos   if (gdbarch_addr_bit (target_gdbarch ()) > 32)
36166e63ce3Schristos     printf_filtered ("        ");
36266e63ce3Schristos   printf_filtered ("Attrs ");
36366e63ce3Schristos   printf_filtered ("\n");
36466e63ce3Schristos 
36507163879Schristos   for (const mem_region &m : *mem_region_list)
36666e63ce3Schristos     {
3671c468f90Schristos       const char *tmp;
36866e63ce3Schristos 
36966e63ce3Schristos       printf_filtered ("%-3d %-3c\t",
37007163879Schristos 		       m.number,
37107163879Schristos 		       m.enabled_p ? 'y' : 'n');
37248596154Schristos       if (gdbarch_addr_bit (target_gdbarch ()) <= 32)
37307163879Schristos 	tmp = hex_string_custom (m.lo, 8);
37466e63ce3Schristos       else
37507163879Schristos 	tmp = hex_string_custom (m.lo, 16);
37666e63ce3Schristos 
37766e63ce3Schristos       printf_filtered ("%s ", tmp);
37866e63ce3Schristos 
37948596154Schristos       if (gdbarch_addr_bit (target_gdbarch ()) <= 32)
38066e63ce3Schristos 	{
38107163879Schristos 	  if (m.hi == 0)
38266e63ce3Schristos 	    tmp = "0x100000000";
38366e63ce3Schristos 	  else
38407163879Schristos 	    tmp = hex_string_custom (m.hi, 8);
38566e63ce3Schristos 	}
38666e63ce3Schristos       else
38766e63ce3Schristos 	{
38807163879Schristos 	  if (m.hi == 0)
38966e63ce3Schristos 	    tmp = "0x10000000000000000";
39066e63ce3Schristos 	  else
39107163879Schristos 	    tmp = hex_string_custom (m.hi, 16);
39266e63ce3Schristos 	}
39366e63ce3Schristos 
39466e63ce3Schristos       printf_filtered ("%s ", tmp);
39566e63ce3Schristos 
39666e63ce3Schristos       /* Print a token for each attribute.
39766e63ce3Schristos 
39866e63ce3Schristos        * FIXME: Should we output a comma after each token?  It may
39966e63ce3Schristos        * make it easier for users to read, but we'd lose the ability
40066e63ce3Schristos        * to cut-and-paste the list of attributes when defining a new
40166e63ce3Schristos        * region.  Perhaps that is not important.
40266e63ce3Schristos        *
40366e63ce3Schristos        * FIXME: If more attributes are added to GDB, the output may
40466e63ce3Schristos        * become cluttered and difficult for users to read.  At that
40566e63ce3Schristos        * time, we may want to consider printing tokens only if they
40666e63ce3Schristos        * are different from the default attribute.  */
40766e63ce3Schristos 
40807163879Schristos       switch (m.attrib.mode)
40966e63ce3Schristos 	{
41066e63ce3Schristos 	case MEM_RW:
41166e63ce3Schristos 	  printf_filtered ("rw ");
41266e63ce3Schristos 	  break;
41366e63ce3Schristos 	case MEM_RO:
41466e63ce3Schristos 	  printf_filtered ("ro ");
41566e63ce3Schristos 	  break;
41666e63ce3Schristos 	case MEM_WO:
41766e63ce3Schristos 	  printf_filtered ("wo ");
41866e63ce3Schristos 	  break;
41966e63ce3Schristos 	case MEM_FLASH:
42007163879Schristos 	  printf_filtered ("flash blocksize 0x%x ", m.attrib.blocksize);
42166e63ce3Schristos 	  break;
42266e63ce3Schristos 	}
42366e63ce3Schristos 
42407163879Schristos       switch (m.attrib.width)
42566e63ce3Schristos 	{
42666e63ce3Schristos 	case MEM_WIDTH_8:
42766e63ce3Schristos 	  printf_filtered ("8 ");
42866e63ce3Schristos 	  break;
42966e63ce3Schristos 	case MEM_WIDTH_16:
43066e63ce3Schristos 	  printf_filtered ("16 ");
43166e63ce3Schristos 	  break;
43266e63ce3Schristos 	case MEM_WIDTH_32:
43366e63ce3Schristos 	  printf_filtered ("32 ");
43466e63ce3Schristos 	  break;
43566e63ce3Schristos 	case MEM_WIDTH_64:
43666e63ce3Schristos 	  printf_filtered ("64 ");
43766e63ce3Schristos 	  break;
43866e63ce3Schristos 	case MEM_WIDTH_UNSPECIFIED:
43966e63ce3Schristos 	  break;
44066e63ce3Schristos 	}
44166e63ce3Schristos 
44266e63ce3Schristos #if 0
44366e63ce3Schristos       if (attrib->hwbreak)
44466e63ce3Schristos 	printf_filtered ("hwbreak");
44566e63ce3Schristos       else
44666e63ce3Schristos 	printf_filtered ("swbreak");
44766e63ce3Schristos #endif
44866e63ce3Schristos 
44907163879Schristos       if (m.attrib.cache)
45066e63ce3Schristos 	printf_filtered ("cache ");
45166e63ce3Schristos       else
45266e63ce3Schristos 	printf_filtered ("nocache ");
45366e63ce3Schristos 
45466e63ce3Schristos #if 0
45566e63ce3Schristos       if (attrib->verify)
45666e63ce3Schristos 	printf_filtered ("verify ");
45766e63ce3Schristos       else
45866e63ce3Schristos 	printf_filtered ("noverify ");
45966e63ce3Schristos #endif
46066e63ce3Schristos 
46166e63ce3Schristos       printf_filtered ("\n");
46266e63ce3Schristos     }
46366e63ce3Schristos }
46466e63ce3Schristos 
46566e63ce3Schristos 
46666e63ce3Schristos /* Enable the memory region number NUM.  */
46766e63ce3Schristos 
46866e63ce3Schristos static void
mem_enable(int num)46966e63ce3Schristos mem_enable (int num)
47066e63ce3Schristos {
47107163879Schristos   for (mem_region &m : *mem_region_list)
47207163879Schristos     if (m.number == num)
47366e63ce3Schristos       {
47407163879Schristos 	m.enabled_p = 1;
47566e63ce3Schristos 	return;
47666e63ce3Schristos       }
47766e63ce3Schristos   printf_unfiltered (_("No memory region number %d.\n"), num);
47866e63ce3Schristos }
47966e63ce3Schristos 
48066e63ce3Schristos static void
enable_mem_command(const char * args,int from_tty)48107163879Schristos enable_mem_command (const char *args, int from_tty)
48266e63ce3Schristos {
48366e63ce3Schristos   require_user_regions (from_tty);
48466e63ce3Schristos 
48566e63ce3Schristos   target_dcache_invalidate ();
48666e63ce3Schristos 
48766e63ce3Schristos   if (args == NULL || *args == '\0')
48866e63ce3Schristos     { /* Enable all mem regions.  */
48907163879Schristos       for (mem_region &m : *mem_region_list)
49007163879Schristos 	m.enabled_p = 1;
49166e63ce3Schristos     }
49266e63ce3Schristos   else
49366e63ce3Schristos     {
4941c468f90Schristos       number_or_range_parser parser (args);
4951c468f90Schristos       while (!parser.finished ())
49666e63ce3Schristos 	{
49707163879Schristos 	  int num = parser.get_number ();
49866e63ce3Schristos 	  mem_enable (num);
49966e63ce3Schristos 	}
50066e63ce3Schristos     }
50166e63ce3Schristos }
50266e63ce3Schristos 
50366e63ce3Schristos 
50466e63ce3Schristos /* Disable the memory region number NUM.  */
50566e63ce3Schristos 
50666e63ce3Schristos static void
mem_disable(int num)50766e63ce3Schristos mem_disable (int num)
50866e63ce3Schristos {
50907163879Schristos   for (mem_region &m : *mem_region_list)
51007163879Schristos     if (m.number == num)
51166e63ce3Schristos       {
51207163879Schristos 	m.enabled_p = 0;
51366e63ce3Schristos 	return;
51466e63ce3Schristos       }
51566e63ce3Schristos   printf_unfiltered (_("No memory region number %d.\n"), num);
51666e63ce3Schristos }
51766e63ce3Schristos 
51866e63ce3Schristos static void
disable_mem_command(const char * args,int from_tty)51907163879Schristos disable_mem_command (const char *args, int from_tty)
52066e63ce3Schristos {
52166e63ce3Schristos   require_user_regions (from_tty);
52266e63ce3Schristos 
52366e63ce3Schristos   target_dcache_invalidate ();
52466e63ce3Schristos 
52566e63ce3Schristos   if (args == NULL || *args == '\0')
52666e63ce3Schristos     {
52707163879Schristos       for (mem_region &m : *mem_region_list)
52807163879Schristos 	m.enabled_p = false;
52966e63ce3Schristos     }
53066e63ce3Schristos   else
53166e63ce3Schristos     {
5321c468f90Schristos       number_or_range_parser parser (args);
5331c468f90Schristos       while (!parser.finished ())
53466e63ce3Schristos 	{
5351c468f90Schristos 	  int num = parser.get_number ();
53666e63ce3Schristos 	  mem_disable (num);
53766e63ce3Schristos 	}
53866e63ce3Schristos     }
53966e63ce3Schristos }
54066e63ce3Schristos 
54166e63ce3Schristos /* Delete the memory region number NUM.  */
54266e63ce3Schristos 
54366e63ce3Schristos static void
mem_delete(int num)54466e63ce3Schristos mem_delete (int num)
54566e63ce3Schristos {
54666e63ce3Schristos   if (!mem_region_list)
54766e63ce3Schristos     {
54866e63ce3Schristos       printf_unfiltered (_("No memory region number %d.\n"), num);
54966e63ce3Schristos       return;
55066e63ce3Schristos     }
55166e63ce3Schristos 
55207163879Schristos   auto it = std::remove_if (mem_region_list->begin (), mem_region_list->end (),
55307163879Schristos 			    [num] (const mem_region &m)
55466e63ce3Schristos     {
55507163879Schristos       return m.number == num;
55607163879Schristos     });
55766e63ce3Schristos 
55807163879Schristos   if (it != mem_region_list->end ())
55907163879Schristos     mem_region_list->erase (it);
56007163879Schristos   else
56107163879Schristos     printf_unfiltered (_("No memory region number %d.\n"), num);
56266e63ce3Schristos }
56366e63ce3Schristos 
56466e63ce3Schristos static void
delete_mem_command(const char * args,int from_tty)56507163879Schristos delete_mem_command (const char *args, int from_tty)
56666e63ce3Schristos {
56766e63ce3Schristos   require_user_regions (from_tty);
56866e63ce3Schristos 
56966e63ce3Schristos   target_dcache_invalidate ();
57066e63ce3Schristos 
57166e63ce3Schristos   if (args == NULL || *args == '\0')
57266e63ce3Schristos     {
57366e63ce3Schristos       if (query (_("Delete all memory regions? ")))
57407163879Schristos 	user_mem_clear ();
57566e63ce3Schristos       dont_repeat ();
57666e63ce3Schristos       return;
57766e63ce3Schristos     }
57866e63ce3Schristos 
5791c468f90Schristos   number_or_range_parser parser (args);
5801c468f90Schristos   while (!parser.finished ())
58166e63ce3Schristos     {
5821c468f90Schristos       int num = parser.get_number ();
58366e63ce3Schristos       mem_delete (num);
58466e63ce3Schristos     }
58566e63ce3Schristos 
58666e63ce3Schristos   dont_repeat ();
58766e63ce3Schristos }
58866e63ce3Schristos 
58966e63ce3Schristos static struct cmd_list_element *mem_set_cmdlist;
59066e63ce3Schristos static struct cmd_list_element *mem_show_cmdlist;
59166e63ce3Schristos 
592*1424dfb3Schristos void _initialize_mem ();
59366e63ce3Schristos void
_initialize_mem()594*1424dfb3Schristos _initialize_mem ()
59566e63ce3Schristos {
59666e63ce3Schristos   add_com ("mem", class_vars, mem_command, _("\
597*1424dfb3Schristos Define attributes for memory region or reset memory region handling to "
598*1424dfb3Schristos "target-based.\n\
59966e63ce3Schristos Usage: mem auto\n\
60007163879Schristos        mem LOW HIGH [MODE WIDTH CACHE],\n\
60107163879Schristos where MODE  may be rw (read/write), ro (read-only) or wo (write-only),\n\
60207163879Schristos       WIDTH may be 8, 16, 32, or 64, and\n\
60307163879Schristos       CACHE may be cache or nocache"));
60466e63ce3Schristos 
60507163879Schristos   add_cmd ("mem", class_vars, enable_mem_command, _("\
60666e63ce3Schristos Enable memory region.\n\
60707163879Schristos Arguments are the IDs of the memory regions to enable.\n\
60807163879Schristos Usage: enable mem [ID]...\n\
60907163879Schristos Do \"info mem\" to see current list of IDs."), &enablelist);
61066e63ce3Schristos 
61107163879Schristos   add_cmd ("mem", class_vars, disable_mem_command, _("\
61266e63ce3Schristos Disable memory region.\n\
61307163879Schristos Arguments are the IDs of the memory regions to disable.\n\
61407163879Schristos Usage: disable mem [ID]...\n\
61507163879Schristos Do \"info mem\" to see current list of IDs."), &disablelist);
61666e63ce3Schristos 
61707163879Schristos   add_cmd ("mem", class_vars, delete_mem_command, _("\
61866e63ce3Schristos Delete memory region.\n\
61907163879Schristos Arguments are the IDs of the memory regions to delete.\n\
62007163879Schristos Usage: delete mem [ID]...\n\
62107163879Schristos Do \"info mem\" to see current list of IDs."), &deletelist);
62266e63ce3Schristos 
62307163879Schristos   add_info ("mem", info_mem_command,
624*1424dfb3Schristos 	    _("Memory region attributes."));
62566e63ce3Schristos 
626*1424dfb3Schristos   add_basic_prefix_cmd ("mem", class_vars, _("\
627*1424dfb3Schristos Memory regions settings."),
62866e63ce3Schristos 			&mem_set_cmdlist, "set mem ",
62966e63ce3Schristos 			0/* allow-unknown */, &setlist);
630*1424dfb3Schristos   add_show_prefix_cmd ("mem", class_vars, _("\
631*1424dfb3Schristos Memory regions settings."),
63266e63ce3Schristos 		       &mem_show_cmdlist, "show mem  ",
63366e63ce3Schristos 		       0/* allow-unknown */, &showlist);
63466e63ce3Schristos 
63566e63ce3Schristos   add_setshow_boolean_cmd ("inaccessible-by-default", no_class,
63666e63ce3Schristos 				  &inaccessible_by_default, _("\
63766e63ce3Schristos Set handling of unknown memory regions."), _("\
63866e63ce3Schristos Show handling of unknown memory regions."), _("\
63966e63ce3Schristos If on, and some memory map is defined, debugger will emit errors on\n\
64066e63ce3Schristos accesses to memory not defined in the memory map. If off, accesses to all\n\
64166e63ce3Schristos memory addresses will be allowed."),
64266e63ce3Schristos 				NULL,
64366e63ce3Schristos 				show_inaccessible_by_default,
64466e63ce3Schristos 				&mem_set_cmdlist,
64566e63ce3Schristos 				&mem_show_cmdlist);
64666e63ce3Schristos }
647