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