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