Automatic date update in version.in
[binutils-gdb.git] / gdb / memattr.c
blob6d406be36337db4abfae57643cfec7f888f52cdb
1 /* Memory attributes support, for GDB.
3 Copyright (C) 2001-2024 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
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 "breakpoint.h"
29 #include "cli/cli-utils.h"
30 #include <algorithm>
31 #include "gdbarch.h"
32 #include "inferior.h"
33 #include "progspace.h"
35 static std::vector<mem_region> user_mem_region_list, target_mem_region_list;
36 static std::vector<mem_region> *mem_region_list = &target_mem_region_list;
37 static int mem_number = 0;
39 /* If this flag is set, the memory region list should be automatically
40 updated from the target. If it is clear, the list is user-controlled
41 and should be left alone. */
43 static bool
44 mem_use_target ()
46 return mem_region_list == &target_mem_region_list;
49 /* If this flag is set, we have tried to fetch the target memory regions
50 since the last time it was invalidated. If that list is still
51 empty, then the target can't supply memory regions. */
52 static bool target_mem_regions_valid;
54 /* If this flag is set, gdb will assume that memory ranges not
55 specified by the memory map have type MEM_NONE, and will
56 emit errors on all accesses to that memory. */
57 static bool inaccessible_by_default = true;
59 static void
60 show_inaccessible_by_default (struct ui_file *file, int from_tty,
61 struct cmd_list_element *c,
62 const char *value)
64 if (inaccessible_by_default)
65 gdb_printf (file, _("Unknown memory addresses will "
66 "be treated as inaccessible.\n"));
67 else
68 gdb_printf (file, _("Unknown memory addresses "
69 "will be treated as RAM.\n"));
72 /* This function should be called before any command which would
73 modify the memory region list. It will handle switching from
74 a target-provided list to a local list, if necessary. */
76 static void
77 require_user_regions (int from_tty)
79 /* If we're already using a user-provided list, nothing to do. */
80 if (!mem_use_target ())
81 return;
83 /* Switch to a user-provided list (possibly a copy of the current
84 one). */
85 mem_region_list = &user_mem_region_list;
87 /* If we don't have a target-provided region list yet, then
88 no need to warn. */
89 if (target_mem_region_list.empty ())
90 return;
92 /* Otherwise, let the user know how to get back. */
93 if (from_tty)
94 warning (_("Switching to manual control of memory regions; use "
95 "\"mem auto\" to fetch regions from the target again."));
97 /* And create a new list (copy of the target-supplied regions) for the user
98 to modify. */
99 user_mem_region_list = target_mem_region_list;
102 /* This function should be called before any command which would
103 read the memory region list, other than those which call
104 require_user_regions. It will handle fetching the
105 target-provided list, if necessary. */
107 static void
108 require_target_regions (void)
110 if (mem_use_target () && !target_mem_regions_valid)
112 target_mem_regions_valid = true;
113 target_mem_region_list = target_memory_map ();
117 /* Create a new user-defined memory region. */
119 static void
120 create_user_mem_region (CORE_ADDR lo, CORE_ADDR hi,
121 const mem_attrib &attrib)
123 /* lo == hi is a useless empty region. */
124 if (lo >= hi && hi != 0)
126 gdb_printf (_("invalid memory region: low >= high\n"));
127 return;
130 mem_region newobj (lo, hi, attrib);
132 auto it = std::lower_bound (user_mem_region_list.begin (),
133 user_mem_region_list.end (),
134 newobj);
135 int ix = std::distance (user_mem_region_list.begin (), it);
137 /* Check for an overlapping memory region. We only need to check
138 in the vincinity - at most one before and one after the
139 insertion point. */
140 for (int i = ix - 1; i < ix + 1; i++)
142 if (i < 0)
143 continue;
144 if (i >= user_mem_region_list.size ())
145 continue;
147 mem_region &n = user_mem_region_list[i];
149 if ((lo >= n.lo && (lo < n.hi || n.hi == 0))
150 || (hi > n.lo && (hi <= n.hi || n.hi == 0))
151 || (lo <= n.lo && ((hi >= n.hi && n.hi != 0) || hi == 0)))
153 gdb_printf (_("overlapping memory region\n"));
154 return;
158 newobj.number = ++mem_number;
159 user_mem_region_list.insert (it, newobj);
162 /* Look up the memory region corresponding to ADDR. */
164 struct mem_region *
165 lookup_mem_region (CORE_ADDR addr)
167 static struct mem_region region (0, 0);
168 CORE_ADDR lo;
169 CORE_ADDR hi;
171 require_target_regions ();
173 /* First we initialize LO and HI so that they describe the entire
174 memory space. As we process the memory region chain, they are
175 redefined to describe the minimal region containing ADDR. LO
176 and HI are used in the case where no memory region is defined
177 that contains ADDR. If a memory region is disabled, it is
178 treated as if it does not exist. The initial values for LO
179 and HI represent the bottom and top of memory. */
181 lo = 0;
182 hi = 0;
184 /* Either find memory range containing ADDR, or set LO and HI
185 to the nearest boundaries of an existing memory range.
187 If we ever want to support a huge list of memory regions, this
188 check should be replaced with a binary search (probably using
189 VEC_lower_bound). */
190 for (mem_region &m : *mem_region_list)
192 if (m.enabled_p == 1)
194 /* If the address is in the memory region, return that
195 memory range. */
196 if (addr >= m.lo && (addr < m.hi || m.hi == 0))
197 return &m;
199 /* This (correctly) won't match if m->hi == 0, representing
200 the top of the address space, because CORE_ADDR is unsigned;
201 no value of LO is less than zero. */
202 if (addr >= m.hi && lo < m.hi)
203 lo = m.hi;
205 /* This will never set HI to zero; if we're here and ADDR
206 is at or below M, and the region starts at zero, then ADDR
207 would have been in the region. */
208 if (addr <= m.lo && (hi == 0 || hi > m.lo))
209 hi = m.lo;
213 /* Because no region was found, we must cons up one based on what
214 was learned above. */
215 region.lo = lo;
216 region.hi = hi;
218 /* When no memory map is defined at all, we always return
219 'default_mem_attrib', so that we do not make all memory
220 inaccessible for targets that don't provide a memory map. */
221 if (inaccessible_by_default && !mem_region_list->empty ())
222 region.attrib = mem_attrib::unknown ();
223 else
224 region.attrib = mem_attrib ();
226 return &region;
229 /* Invalidate any memory regions fetched from the target. */
231 void
232 invalidate_target_mem_regions (void)
234 if (!target_mem_regions_valid)
235 return;
237 target_mem_regions_valid = false;
238 target_mem_region_list.clear ();
241 /* Clear user-defined memory region list. */
243 static void
244 user_mem_clear (void)
246 user_mem_region_list.clear ();
250 static void
251 mem_command (const char *args, int from_tty)
253 CORE_ADDR lo, hi;
255 if (!args)
256 error_no_arg (_("No mem"));
258 /* For "mem auto", switch back to using a target provided list. */
259 if (strcmp (args, "auto") == 0)
261 if (mem_use_target ())
262 return;
264 user_mem_clear ();
265 mem_region_list = &target_mem_region_list;
267 return;
270 require_user_regions (from_tty);
272 std::string tok = extract_arg (&args);
273 if (tok == "")
274 error (_("no lo address"));
275 lo = parse_and_eval_address (tok.c_str ());
277 tok = extract_arg (&args);
278 if (tok == "")
279 error (_("no hi address"));
280 hi = parse_and_eval_address (tok.c_str ());
282 mem_attrib attrib;
283 while ((tok = extract_arg (&args)) != "")
285 if (tok == "rw")
286 attrib.mode = MEM_RW;
287 else if (tok == "ro")
288 attrib.mode = MEM_RO;
289 else if (tok == "wo")
290 attrib.mode = MEM_WO;
292 else if (tok == "8")
293 attrib.width = MEM_WIDTH_8;
294 else if (tok == "16")
296 if ((lo % 2 != 0) || (hi % 2 != 0))
297 error (_("region bounds not 16 bit aligned"));
298 attrib.width = MEM_WIDTH_16;
300 else if (tok == "32")
302 if ((lo % 4 != 0) || (hi % 4 != 0))
303 error (_("region bounds not 32 bit aligned"));
304 attrib.width = MEM_WIDTH_32;
306 else if (tok == "64")
308 if ((lo % 8 != 0) || (hi % 8 != 0))
309 error (_("region bounds not 64 bit aligned"));
310 attrib.width = MEM_WIDTH_64;
313 #if 0
314 else if (tok == "hwbreak")
315 attrib.hwbreak = 1;
316 else if (tok == "swbreak")
317 attrib.hwbreak = 0;
318 #endif
320 else if (tok == "cache")
321 attrib.cache = 1;
322 else if (tok == "nocache")
323 attrib.cache = 0;
325 #if 0
326 else if (tok == "verify")
327 attrib.verify = 1;
328 else if (tok == "noverify")
329 attrib.verify = 0;
330 #endif
332 else
333 error (_("unknown attribute: %s"), tok.c_str ());
336 create_user_mem_region (lo, hi, attrib);
340 static void
341 info_mem_command (const char *args, int from_tty)
343 if (mem_use_target ())
344 gdb_printf (_("Using memory regions provided by the target.\n"));
345 else
346 gdb_printf (_("Using user-defined memory regions.\n"));
348 require_target_regions ();
350 if (mem_region_list->empty ())
352 gdb_printf (_("There are no memory regions defined.\n"));
353 return;
356 gdb_printf ("Num ");
357 gdb_printf ("Enb ");
358 gdb_printf ("Low Addr ");
359 if (gdbarch_addr_bit (current_inferior ()->arch ()) > 32)
360 gdb_printf (" ");
361 gdb_printf ("High Addr ");
362 if (gdbarch_addr_bit (current_inferior ()->arch ()) > 32)
363 gdb_printf (" ");
364 gdb_printf ("Attrs ");
365 gdb_printf ("\n");
367 for (const mem_region &m : *mem_region_list)
369 const char *tmp;
371 gdb_printf ("%-3d %-3c\t",
372 m.number,
373 m.enabled_p ? 'y' : 'n');
374 if (gdbarch_addr_bit (current_inferior ()->arch ()) <= 32)
375 tmp = hex_string_custom (m.lo, 8);
376 else
377 tmp = hex_string_custom (m.lo, 16);
379 gdb_printf ("%s ", tmp);
381 if (gdbarch_addr_bit (current_inferior ()->arch ()) <= 32)
383 if (m.hi == 0)
384 tmp = "0x100000000";
385 else
386 tmp = hex_string_custom (m.hi, 8);
388 else
390 if (m.hi == 0)
391 tmp = "0x10000000000000000";
392 else
393 tmp = hex_string_custom (m.hi, 16);
396 gdb_printf ("%s ", tmp);
398 /* Print a token for each attribute.
400 * FIXME: Should we output a comma after each token? It may
401 * make it easier for users to read, but we'd lose the ability
402 * to cut-and-paste the list of attributes when defining a new
403 * region. Perhaps that is not important.
405 * FIXME: If more attributes are added to GDB, the output may
406 * become cluttered and difficult for users to read. At that
407 * time, we may want to consider printing tokens only if they
408 * are different from the default attribute. */
410 switch (m.attrib.mode)
412 case MEM_RW:
413 gdb_printf ("rw ");
414 break;
415 case MEM_RO:
416 gdb_printf ("ro ");
417 break;
418 case MEM_WO:
419 gdb_printf ("wo ");
420 break;
421 case MEM_FLASH:
422 gdb_printf ("flash blocksize 0x%x ", m.attrib.blocksize);
423 break;
426 switch (m.attrib.width)
428 case MEM_WIDTH_8:
429 gdb_printf ("8 ");
430 break;
431 case MEM_WIDTH_16:
432 gdb_printf ("16 ");
433 break;
434 case MEM_WIDTH_32:
435 gdb_printf ("32 ");
436 break;
437 case MEM_WIDTH_64:
438 gdb_printf ("64 ");
439 break;
440 case MEM_WIDTH_UNSPECIFIED:
441 break;
444 #if 0
445 if (attrib->hwbreak)
446 gdb_printf ("hwbreak");
447 else
448 gdb_printf ("swbreak");
449 #endif
451 if (m.attrib.cache)
452 gdb_printf ("cache ");
453 else
454 gdb_printf ("nocache ");
456 #if 0
457 if (attrib->verify)
458 gdb_printf ("verify ");
459 else
460 gdb_printf ("noverify ");
461 #endif
463 gdb_printf ("\n");
468 /* Enable the memory region number NUM. */
470 static void
471 mem_enable (int num)
473 for (mem_region &m : *mem_region_list)
474 if (m.number == num)
476 m.enabled_p = 1;
477 return;
479 gdb_printf (_("No memory region number %d.\n"), num);
482 static void
483 enable_mem_command (const char *args, int from_tty)
485 require_user_regions (from_tty);
487 target_dcache_invalidate (current_program_space->aspace);
489 if (args == NULL || *args == '\0')
490 { /* Enable all mem regions. */
491 for (mem_region &m : *mem_region_list)
492 m.enabled_p = 1;
494 else
496 number_or_range_parser parser (args);
497 while (!parser.finished ())
499 int num = parser.get_number ();
500 mem_enable (num);
506 /* Disable the memory region number NUM. */
508 static void
509 mem_disable (int num)
511 for (mem_region &m : *mem_region_list)
512 if (m.number == num)
514 m.enabled_p = 0;
515 return;
517 gdb_printf (_("No memory region number %d.\n"), num);
520 static void
521 disable_mem_command (const char *args, int from_tty)
523 require_user_regions (from_tty);
525 target_dcache_invalidate (current_program_space->aspace);
527 if (args == NULL || *args == '\0')
529 for (mem_region &m : *mem_region_list)
530 m.enabled_p = false;
532 else
534 number_or_range_parser parser (args);
535 while (!parser.finished ())
537 int num = parser.get_number ();
538 mem_disable (num);
543 /* Delete the memory region number NUM. */
545 static void
546 mem_delete (int num)
548 if (!mem_region_list)
550 gdb_printf (_("No memory region number %d.\n"), num);
551 return;
554 auto it = std::remove_if (mem_region_list->begin (), mem_region_list->end (),
555 [num] (const mem_region &m)
557 return m.number == num;
560 if (it != mem_region_list->end ())
561 mem_region_list->erase (it);
562 else
563 gdb_printf (_("No memory region number %d.\n"), num);
566 static void
567 delete_mem_command (const char *args, int from_tty)
569 require_user_regions (from_tty);
571 target_dcache_invalidate (current_program_space->aspace);
573 if (args == NULL || *args == '\0')
575 if (query (_("Delete all memory regions? ")))
576 user_mem_clear ();
577 dont_repeat ();
578 return;
581 number_or_range_parser parser (args);
582 while (!parser.finished ())
584 int num = parser.get_number ();
585 mem_delete (num);
588 dont_repeat ();
591 static struct cmd_list_element *mem_set_cmdlist;
592 static struct cmd_list_element *mem_show_cmdlist;
594 void _initialize_mem ();
595 void
596 _initialize_mem ()
598 add_com ("mem", class_vars, mem_command, _("\
599 Define attributes for memory region or reset memory region handling to "
600 "target-based.\n\
601 Usage: mem auto\n\
602 mem LOW HIGH [MODE WIDTH CACHE],\n\
603 where MODE may be rw (read/write), ro (read-only) or wo (write-only),\n\
604 WIDTH may be 8, 16, 32, or 64, and\n\
605 CACHE may be cache or nocache"));
607 add_cmd ("mem", class_vars, enable_mem_command, _("\
608 Enable memory region.\n\
609 Arguments are the IDs of the memory regions to enable.\n\
610 Usage: enable mem [ID]...\n\
611 Do \"info mem\" to see current list of IDs."), &enablelist);
613 add_cmd ("mem", class_vars, disable_mem_command, _("\
614 Disable memory region.\n\
615 Arguments are the IDs of the memory regions to disable.\n\
616 Usage: disable mem [ID]...\n\
617 Do \"info mem\" to see current list of IDs."), &disablelist);
619 add_cmd ("mem", class_vars, delete_mem_command, _("\
620 Delete memory region.\n\
621 Arguments are the IDs of the memory regions to delete.\n\
622 Usage: delete mem [ID]...\n\
623 Do \"info mem\" to see current list of IDs."), &deletelist);
625 add_info ("mem", info_mem_command,
626 _("Memory region attributes."));
628 add_setshow_prefix_cmd ("mem", class_vars,
629 _("Memory regions settings."),
630 _("Memory regions settings."),
631 &mem_set_cmdlist, &mem_show_cmdlist,
632 &setlist, &showlist);
634 add_setshow_boolean_cmd ("inaccessible-by-default", no_class,
635 &inaccessible_by_default, _("\
636 Set handling of unknown memory regions."), _("\
637 Show handling of unknown memory regions."), _("\
638 If on, and some memory map is defined, debugger will emit errors on\n\
639 accesses to memory not defined in the memory map. If off, accesses to all\n\
640 memory addresses will be allowed."),
641 NULL,
642 show_inaccessible_by_default,
643 &mem_set_cmdlist,
644 &mem_show_cmdlist);