xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/memattr.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1 /* Memory attributes support, for GDB.
2 
3    Copyright (C) 2001-2019 Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 #include "defs.h"
21 #include "command.h"
22 #include "gdbcmd.h"
23 #include "memattr.h"
24 #include "target.h"
25 #include "target-dcache.h"
26 #include "value.h"
27 #include "language.h"
28 #include "common/vec.h"
29 #include "breakpoint.h"
30 #include "cli/cli-utils.h"
31 #include <algorithm>
32 
33 static std::vector<mem_region> user_mem_region_list, target_mem_region_list;
34 static std::vector<mem_region> *mem_region_list = &target_mem_region_list;
35 static int mem_number = 0;
36 
37 /* If this flag is set, the memory region list should be automatically
38    updated from the target.  If it is clear, the list is user-controlled
39    and should be left alone.  */
40 
41 static bool
42 mem_use_target ()
43 {
44   return mem_region_list == &target_mem_region_list;
45 }
46 
47 /* If this flag is set, we have tried to fetch the target memory regions
48    since the last time it was invalidated.  If that list is still
49    empty, then the target can't supply memory regions.  */
50 static bool target_mem_regions_valid;
51 
52 /* If this flag is set, gdb will assume that memory ranges not
53    specified by the memory map have type MEM_NONE, and will
54    emit errors on all accesses to that memory.  */
55 static int inaccessible_by_default = 1;
56 
57 static void
58 show_inaccessible_by_default (struct ui_file *file, int from_tty,
59 			      struct cmd_list_element *c,
60 			      const char *value)
61 {
62   if (inaccessible_by_default)
63     fprintf_filtered (file, _("Unknown memory addresses will "
64 			      "be treated as inaccessible.\n"));
65   else
66     fprintf_filtered (file, _("Unknown memory addresses "
67 			      "will be treated as RAM.\n"));
68 }
69 
70 /* This function should be called before any command which would
71    modify the memory region list.  It will handle switching from
72    a target-provided list to a local list, if necessary.  */
73 
74 static void
75 require_user_regions (int from_tty)
76 {
77   /* If we're already using a user-provided list, nothing to do.  */
78   if (!mem_use_target ())
79     return;
80 
81   /* Switch to a user-provided list (possibly a copy of the current
82      one).  */
83   mem_region_list = &user_mem_region_list;
84 
85   /* If we don't have a target-provided region list yet, then
86      no need to warn.  */
87   if (target_mem_region_list.empty ())
88     return;
89 
90   /* Otherwise, let the user know how to get back.  */
91   if (from_tty)
92     warning (_("Switching to manual control of memory regions; use "
93 	       "\"mem auto\" to fetch regions from the target again."));
94 
95   /* And create a new list (copy of the target-supplied regions) for the user
96      to modify.  */
97   user_mem_region_list = target_mem_region_list;
98 }
99 
100 /* This function should be called before any command which would
101    read the memory region list, other than those which call
102    require_user_regions.  It will handle fetching the
103    target-provided list, if necessary.  */
104 
105 static void
106 require_target_regions (void)
107 {
108   if (mem_use_target () && !target_mem_regions_valid)
109     {
110       target_mem_regions_valid = true;
111       target_mem_region_list = target_memory_map ();
112     }
113 }
114 
115 /* Create a new user-defined memory region.  */
116 
117 static void
118 create_user_mem_region (CORE_ADDR lo, CORE_ADDR hi,
119 			const mem_attrib &attrib)
120 {
121   /* lo == hi is a useless empty region.  */
122   if (lo >= hi && hi != 0)
123     {
124       printf_unfiltered (_("invalid memory region: low >= high\n"));
125       return;
126     }
127 
128   mem_region newobj (lo, hi, attrib);
129 
130   auto it = std::lower_bound (user_mem_region_list.begin (),
131 			      user_mem_region_list.end (),
132 			      newobj);
133   int ix = std::distance (user_mem_region_list.begin (), it);
134 
135   /* Check for an overlapping memory region.  We only need to check
136      in the vicinity - at most one before and one after the
137      insertion point.  */
138   for (int i = ix - 1; i < ix + 1; i++)
139     {
140       if (i < 0)
141 	continue;
142       if (i >= user_mem_region_list.size ())
143 	continue;
144 
145       mem_region &n = user_mem_region_list[i];
146 
147       if ((lo >= n.lo && (lo < n.hi || n.hi == 0))
148 	  || (hi > n.lo && (hi <= n.hi || n.hi == 0))
149 	  || (lo <= n.lo && ((hi >= n.hi && n.hi != 0) || hi == 0)))
150 	{
151 	  printf_unfiltered (_("overlapping memory region\n"));
152 	  return;
153 	}
154     }
155 
156   newobj.number = ++mem_number;
157   user_mem_region_list.insert (it, newobj);
158 }
159 
160 /* Look up the memory region corresponding to ADDR.  */
161 
162 struct mem_region *
163 lookup_mem_region (CORE_ADDR addr)
164 {
165   static struct mem_region region (0, 0);
166   CORE_ADDR lo;
167   CORE_ADDR hi;
168 
169   require_target_regions ();
170 
171   /* First we initialize LO and HI so that they describe the entire
172      memory space.  As we process the memory region chain, they are
173      redefined to describe the minimal region containing ADDR.  LO
174      and HI are used in the case where no memory region is defined
175      that contains ADDR.  If a memory region is disabled, it is
176      treated as if it does not exist.  The initial values for LO
177      and HI represent the bottom and top of memory.  */
178 
179   lo = 0;
180   hi = 0;
181 
182   /* Either find memory range containing ADDR, or set LO and HI
183      to the nearest boundaries of an existing memory range.
184 
185      If we ever want to support a huge list of memory regions, this
186      check should be replaced with a binary search (probably using
187      VEC_lower_bound).  */
188   for (mem_region &m : *mem_region_list)
189     {
190       if (m.enabled_p == 1)
191 	{
192 	  /* If the address is in the memory region, return that
193 	     memory range.  */
194 	  if (addr >= m.lo && (addr < m.hi || m.hi == 0))
195 	    return &m;
196 
197 	  /* This (correctly) won't match if m->hi == 0, representing
198 	     the top of the address space, because CORE_ADDR is unsigned;
199 	     no value of LO is less than zero.  */
200 	  if (addr >= m.hi && lo < m.hi)
201 	    lo = m.hi;
202 
203 	  /* This will never set HI to zero; if we're here and ADDR
204 	     is at or below M, and the region starts at zero, then ADDR
205 	     would have been in the region.  */
206 	  if (addr <= m.lo && (hi == 0 || hi > m.lo))
207 	    hi = m.lo;
208 	}
209     }
210 
211   /* Because no region was found, we must cons up one based on what
212      was learned above.  */
213   region.lo = lo;
214   region.hi = hi;
215 
216   /* When no memory map is defined at all, we always return
217      'default_mem_attrib', so that we do not make all memory
218      inaccessible for targets that don't provide a memory map.  */
219   if (inaccessible_by_default && !mem_region_list->empty ())
220     region.attrib = mem_attrib::unknown ();
221   else
222     region.attrib = mem_attrib ();
223 
224   return &region;
225 }
226 
227 /* Invalidate any memory regions fetched from the target.  */
228 
229 void
230 invalidate_target_mem_regions (void)
231 {
232   if (!target_mem_regions_valid)
233     return;
234 
235   target_mem_regions_valid = false;
236   target_mem_region_list.clear ();
237 }
238 
239 /* Clear user-defined memory region list.  */
240 
241 static void
242 user_mem_clear (void)
243 {
244   user_mem_region_list.clear ();
245 }
246 
247 
248 static void
249 mem_command (const char *args, int from_tty)
250 {
251   CORE_ADDR lo, hi;
252 
253   if (!args)
254     error_no_arg (_("No mem"));
255 
256   /* For "mem auto", switch back to using a target provided list.  */
257   if (strcmp (args, "auto") == 0)
258     {
259       if (mem_use_target ())
260 	return;
261 
262       user_mem_clear ();
263       mem_region_list = &target_mem_region_list;
264 
265       return;
266     }
267 
268   require_user_regions (from_tty);
269 
270   std::string tok = extract_arg (&args);
271   if (tok == "")
272     error (_("no lo address"));
273   lo = parse_and_eval_address (tok.c_str ());
274 
275   tok = extract_arg (&args);
276   if (tok == "")
277     error (_("no hi address"));
278   hi = parse_and_eval_address (tok.c_str ());
279 
280   mem_attrib attrib;
281   while ((tok = extract_arg (&args)) != "")
282     {
283       if (tok == "rw")
284 	attrib.mode = MEM_RW;
285       else if (tok == "ro")
286 	attrib.mode = MEM_RO;
287       else if (tok == "wo")
288 	attrib.mode = MEM_WO;
289 
290       else if (tok == "8")
291 	attrib.width = MEM_WIDTH_8;
292       else if (tok == "16")
293 	{
294 	  if ((lo % 2 != 0) || (hi % 2 != 0))
295 	    error (_("region bounds not 16 bit aligned"));
296 	  attrib.width = MEM_WIDTH_16;
297 	}
298       else if (tok == "32")
299 	{
300 	  if ((lo % 4 != 0) || (hi % 4 != 0))
301 	    error (_("region bounds not 32 bit aligned"));
302 	  attrib.width = MEM_WIDTH_32;
303 	}
304       else if (tok == "64")
305 	{
306 	  if ((lo % 8 != 0) || (hi % 8 != 0))
307 	    error (_("region bounds not 64 bit aligned"));
308 	  attrib.width = MEM_WIDTH_64;
309 	}
310 
311 #if 0
312       else if (tok == "hwbreak")
313 	attrib.hwbreak = 1;
314       else if (tok == "swbreak")
315 	attrib.hwbreak = 0;
316 #endif
317 
318       else if (tok == "cache")
319 	attrib.cache = 1;
320       else if (tok == "nocache")
321 	attrib.cache = 0;
322 
323 #if 0
324       else if (tok == "verify")
325 	attrib.verify = 1;
326       else if (tok == "noverify")
327 	attrib.verify = 0;
328 #endif
329 
330       else
331 	error (_("unknown attribute: %s"), tok.c_str ());
332     }
333 
334   create_user_mem_region (lo, hi, attrib);
335 }
336 
337 
338 static void
339 info_mem_command (const char *args, int from_tty)
340 {
341   if (mem_use_target ())
342     printf_filtered (_("Using memory regions provided by the target.\n"));
343   else
344     printf_filtered (_("Using user-defined memory regions.\n"));
345 
346   require_target_regions ();
347 
348   if (mem_region_list->empty ())
349     {
350       printf_unfiltered (_("There are no memory regions defined.\n"));
351       return;
352     }
353 
354   printf_filtered ("Num ");
355   printf_filtered ("Enb ");
356   printf_filtered ("Low Addr   ");
357   if (gdbarch_addr_bit (target_gdbarch ()) > 32)
358     printf_filtered ("        ");
359   printf_filtered ("High Addr  ");
360   if (gdbarch_addr_bit (target_gdbarch ()) > 32)
361     printf_filtered ("        ");
362   printf_filtered ("Attrs ");
363   printf_filtered ("\n");
364 
365   for (const mem_region &m : *mem_region_list)
366     {
367       const char *tmp;
368 
369       printf_filtered ("%-3d %-3c\t",
370 		       m.number,
371 		       m.enabled_p ? 'y' : 'n');
372       if (gdbarch_addr_bit (target_gdbarch ()) <= 32)
373 	tmp = hex_string_custom (m.lo, 8);
374       else
375 	tmp = hex_string_custom (m.lo, 16);
376 
377       printf_filtered ("%s ", tmp);
378 
379       if (gdbarch_addr_bit (target_gdbarch ()) <= 32)
380 	{
381 	  if (m.hi == 0)
382 	    tmp = "0x100000000";
383 	  else
384 	    tmp = hex_string_custom (m.hi, 8);
385 	}
386       else
387 	{
388 	  if (m.hi == 0)
389 	    tmp = "0x10000000000000000";
390 	  else
391 	    tmp = hex_string_custom (m.hi, 16);
392 	}
393 
394       printf_filtered ("%s ", tmp);
395 
396       /* Print a token for each attribute.
397 
398        * FIXME: Should we output a comma after each token?  It may
399        * make it easier for users to read, but we'd lose the ability
400        * to cut-and-paste the list of attributes when defining a new
401        * region.  Perhaps that is not important.
402        *
403        * FIXME: If more attributes are added to GDB, the output may
404        * become cluttered and difficult for users to read.  At that
405        * time, we may want to consider printing tokens only if they
406        * are different from the default attribute.  */
407 
408       switch (m.attrib.mode)
409 	{
410 	case MEM_RW:
411 	  printf_filtered ("rw ");
412 	  break;
413 	case MEM_RO:
414 	  printf_filtered ("ro ");
415 	  break;
416 	case MEM_WO:
417 	  printf_filtered ("wo ");
418 	  break;
419 	case MEM_FLASH:
420 	  printf_filtered ("flash blocksize 0x%x ", m.attrib.blocksize);
421 	  break;
422 	}
423 
424       switch (m.attrib.width)
425 	{
426 	case MEM_WIDTH_8:
427 	  printf_filtered ("8 ");
428 	  break;
429 	case MEM_WIDTH_16:
430 	  printf_filtered ("16 ");
431 	  break;
432 	case MEM_WIDTH_32:
433 	  printf_filtered ("32 ");
434 	  break;
435 	case MEM_WIDTH_64:
436 	  printf_filtered ("64 ");
437 	  break;
438 	case MEM_WIDTH_UNSPECIFIED:
439 	  break;
440 	}
441 
442 #if 0
443       if (attrib->hwbreak)
444 	printf_filtered ("hwbreak");
445       else
446 	printf_filtered ("swbreak");
447 #endif
448 
449       if (m.attrib.cache)
450 	printf_filtered ("cache ");
451       else
452 	printf_filtered ("nocache ");
453 
454 #if 0
455       if (attrib->verify)
456 	printf_filtered ("verify ");
457       else
458 	printf_filtered ("noverify ");
459 #endif
460 
461       printf_filtered ("\n");
462 
463       gdb_flush (gdb_stdout);
464     }
465 }
466 
467 
468 /* Enable the memory region number NUM.  */
469 
470 static void
471 mem_enable (int num)
472 {
473   for (mem_region &m : *mem_region_list)
474     if (m.number == num)
475       {
476 	m.enabled_p = 1;
477 	return;
478       }
479   printf_unfiltered (_("No memory region number %d.\n"), num);
480 }
481 
482 static void
483 enable_mem_command (const char *args, int from_tty)
484 {
485   require_user_regions (from_tty);
486 
487   target_dcache_invalidate ();
488 
489   if (args == NULL || *args == '\0')
490     { /* Enable all mem regions.  */
491       for (mem_region &m : *mem_region_list)
492 	m.enabled_p = 1;
493     }
494   else
495     {
496       number_or_range_parser parser (args);
497       while (!parser.finished ())
498 	{
499 	  int num = parser.get_number ();
500 	  mem_enable (num);
501 	}
502     }
503 }
504 
505 
506 /* Disable the memory region number NUM.  */
507 
508 static void
509 mem_disable (int num)
510 {
511   for (mem_region &m : *mem_region_list)
512     if (m.number == num)
513       {
514 	m.enabled_p = 0;
515 	return;
516       }
517   printf_unfiltered (_("No memory region number %d.\n"), num);
518 }
519 
520 static void
521 disable_mem_command (const char *args, int from_tty)
522 {
523   require_user_regions (from_tty);
524 
525   target_dcache_invalidate ();
526 
527   if (args == NULL || *args == '\0')
528     {
529       for (mem_region &m : *mem_region_list)
530 	m.enabled_p = false;
531     }
532   else
533     {
534       number_or_range_parser parser (args);
535       while (!parser.finished ())
536 	{
537 	  int num = parser.get_number ();
538 	  mem_disable (num);
539 	}
540     }
541 }
542 
543 /* Delete the memory region number NUM.  */
544 
545 static void
546 mem_delete (int num)
547 {
548   if (!mem_region_list)
549     {
550       printf_unfiltered (_("No memory region number %d.\n"), num);
551       return;
552     }
553 
554   auto it = std::remove_if (mem_region_list->begin (), mem_region_list->end (),
555 			    [num] (const mem_region &m)
556     {
557       return m.number == num;
558     });
559 
560   if (it != mem_region_list->end ())
561     mem_region_list->erase (it);
562   else
563     printf_unfiltered (_("No memory region number %d.\n"), num);
564 }
565 
566 static void
567 delete_mem_command (const char *args, int from_tty)
568 {
569   require_user_regions (from_tty);
570 
571   target_dcache_invalidate ();
572 
573   if (args == NULL || *args == '\0')
574     {
575       if (query (_("Delete all memory regions? ")))
576 	user_mem_clear ();
577       dont_repeat ();
578       return;
579     }
580 
581   number_or_range_parser parser (args);
582   while (!parser.finished ())
583     {
584       int num = parser.get_number ();
585       mem_delete (num);
586     }
587 
588   dont_repeat ();
589 }
590 
591 static void
592 dummy_cmd (const char *args, int from_tty)
593 {
594 }
595 
596 static struct cmd_list_element *mem_set_cmdlist;
597 static struct cmd_list_element *mem_show_cmdlist;
598 
599 void
600 _initialize_mem (void)
601 {
602   add_com ("mem", class_vars, mem_command, _("\
603 Define attributes for memory region or reset memory region handling to\n\
604 target-based.\n\
605 Usage: mem auto\n\
606        mem LOW HIGH [MODE WIDTH CACHE],\n\
607 where MODE  may be rw (read/write), ro (read-only) or wo (write-only),\n\
608       WIDTH may be 8, 16, 32, or 64, and\n\
609       CACHE may be cache or nocache"));
610 
611   add_cmd ("mem", class_vars, enable_mem_command, _("\
612 Enable memory region.\n\
613 Arguments are the IDs of the memory regions to enable.\n\
614 Usage: enable mem [ID]...\n\
615 Do \"info mem\" to see current list of IDs."), &enablelist);
616 
617   add_cmd ("mem", class_vars, disable_mem_command, _("\
618 Disable memory region.\n\
619 Arguments are the IDs of the memory regions to disable.\n\
620 Usage: disable mem [ID]...\n\
621 Do \"info mem\" to see current list of IDs."), &disablelist);
622 
623   add_cmd ("mem", class_vars, delete_mem_command, _("\
624 Delete memory region.\n\
625 Arguments are the IDs of the memory regions to delete.\n\
626 Usage: delete mem [ID]...\n\
627 Do \"info mem\" to see current list of IDs."), &deletelist);
628 
629   add_info ("mem", info_mem_command,
630 	    _("Memory region attributes"));
631 
632   add_prefix_cmd ("mem", class_vars, dummy_cmd, _("\
633 Memory regions settings"),
634 		  &mem_set_cmdlist, "set mem ",
635 		  0/* allow-unknown */, &setlist);
636   add_prefix_cmd ("mem", class_vars, dummy_cmd, _("\
637 Memory regions settings"),
638 		  &mem_show_cmdlist, "show mem  ",
639 		  0/* allow-unknown */, &showlist);
640 
641   add_setshow_boolean_cmd ("inaccessible-by-default", no_class,
642 				  &inaccessible_by_default, _("\
643 Set handling of unknown memory regions."), _("\
644 Show handling of unknown memory regions."), _("\
645 If on, and some memory map is defined, debugger will emit errors on\n\
646 accesses to memory not defined in the memory map. If off, accesses to all\n\
647 memory addresses will be allowed."),
648 				NULL,
649 				show_inaccessible_by_default,
650 				&mem_set_cmdlist,
651 				&mem_show_cmdlist);
652 }
653