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