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