1 /* Memory attributes support, for GDB.
3 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
4 Free Software Foundation, Inc.
6 This file is part of GDB.
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.
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.
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. */
31 #include "gdb_string.h"
33 const struct mem_attrib default_mem_attrib
=
36 MEM_WIDTH_UNSPECIFIED
,
40 -1 /* Flash blocksize not specified. */
43 VEC(mem_region_s
) *mem_region_list
, *target_mem_region_list
;
44 static int mem_number
= 0;
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. */
49 static int mem_use_target
= 1;
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. */
54 static int target_mem_regions_valid
;
56 /* Predicate function which returns true if LHS should sort before RHS
57 in a list of memory regions, useful for VEC_lower_bound. */
60 mem_region_lessthan (const struct mem_region
*lhs
,
61 const struct mem_region
*rhs
)
63 return lhs
->lo
< rhs
->lo
;
66 /* A helper function suitable for qsort, used to sort a
67 VEC(mem_region_s) by starting address. */
70 mem_region_cmp (const void *untyped_lhs
, const void *untyped_rhs
)
72 const struct mem_region
*lhs
= untyped_lhs
;
73 const struct mem_region
*rhs
= untyped_rhs
;
75 if (lhs
->lo
< rhs
->lo
)
77 else if (lhs
->lo
== rhs
->lo
)
83 /* Allocate a new memory region, with default settings. */
86 mem_region_init (struct mem_region
*new)
88 memset (new, 0, sizeof (struct mem_region
));
90 new->attrib
= default_mem_attrib
;
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. */
98 require_user_regions (int from_tty
)
100 struct mem_region
*m
;
103 /* If we're already using a user-provided list, nothing to do. */
107 /* Switch to a user-provided list (possibly a copy of the current
111 /* If we don't have a target-provided region list yet, then
113 if (mem_region_list
== NULL
)
116 /* Otherwise, let the user know how to get back. */
118 warning (_("Switching to manual control of memory regions; use "
119 "\"mem auto\" to fetch regions from the target again."));
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
);
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. */
134 require_target_regions (void)
136 if (mem_use_target
&& !target_mem_regions_valid
)
138 target_mem_regions_valid
= 1;
139 target_mem_region_list
= target_memory_map ();
140 mem_region_list
= target_mem_region_list
;
145 create_mem_region (CORE_ADDR lo
, CORE_ADDR hi
,
146 const struct mem_attrib
*attrib
)
148 struct mem_region
new;
151 /* lo == hi is a useless empty region */
152 if (lo
>= hi
&& hi
!= 0)
154 printf_unfiltered (_("invalid memory region: low >= high\n"));
158 mem_region_init (&new);
162 ix
= VEC_lower_bound (mem_region_s
, mem_region_list
, &new,
163 mem_region_lessthan
);
165 /* Check for an overlapping memory region. We only need to check
166 in the vicinity - at most one before and one after the
168 for (i
= ix
- 1; i
< ix
+ 1; i
++)
170 struct mem_region
*n
;
174 if (i
>= VEC_length (mem_region_s
, mem_region_list
))
177 n
= VEC_index (mem_region_s
, mem_region_list
, i
);
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)))
183 printf_unfiltered (_("overlapping memory region\n"));
188 new.number
= ++mem_number
;
189 new.attrib
= *attrib
;
190 VEC_safe_insert (mem_region_s
, mem_region_list
, ix
, &new);
194 * Look up the memory region cooresponding to ADDR.
197 lookup_mem_region (CORE_ADDR addr
)
199 static struct mem_region region
;
200 struct mem_region
*m
;
205 require_target_regions ();
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
212 treated as if it does not exist. */
215 hi
= (CORE_ADDR
) ~ 0;
217 /* If we ever want to support a huge list of memory regions, this
218 check should be replaced with a binary search (probably using
220 for (ix
= 0; VEC_iterate (mem_region_s
, mem_region_list
, ix
, m
); ix
++)
222 if (m
->enabled_p
== 1)
224 if (addr
>= m
->lo
&& (addr
< m
->hi
|| m
->hi
== 0))
227 if (addr
>= m
->hi
&& lo
< m
->hi
)
230 if (addr
<= m
->lo
&& hi
> m
->lo
)
235 /* Because no region was found, we must cons up one based on what
236 was learned above. */
239 region
.attrib
= default_mem_attrib
;
243 /* Invalidate any memory regions fetched from the target. */
246 invalidate_target_mem_regions (void)
248 struct mem_region
*m
;
251 if (!target_mem_regions_valid
)
254 target_mem_regions_valid
= 0;
255 VEC_free (mem_region_s
, target_mem_region_list
);
257 mem_region_list
= NULL
;
260 /* Clear memory region list */
265 VEC_free (mem_region_s
, mem_region_list
);
270 mem_command (char *args
, int from_tty
)
274 struct mem_attrib attrib
;
277 error_no_arg (_("No mem"));
279 /* For "mem auto", switch back to using a target provided list. */
280 if (strcmp (args
, "auto") == 0)
285 if (mem_region_list
!= target_mem_region_list
)
288 mem_region_list
= target_mem_region_list
;
295 require_user_regions (from_tty
);
297 tok
= strtok (args
, " \t");
299 error (_("no lo address"));
300 lo
= parse_and_eval_address (tok
);
302 tok
= strtok (NULL
, " \t");
304 error (_("no hi address"));
305 hi
= parse_and_eval_address (tok
);
307 attrib
= default_mem_attrib
;
308 while ((tok
= strtok (NULL
, " \t")) != NULL
)
310 if (strcmp (tok
, "rw") == 0)
311 attrib
.mode
= MEM_RW
;
312 else if (strcmp (tok
, "ro") == 0)
313 attrib
.mode
= MEM_RO
;
314 else if (strcmp (tok
, "wo") == 0)
315 attrib
.mode
= MEM_WO
;
317 else if (strcmp (tok
, "8") == 0)
318 attrib
.width
= MEM_WIDTH_8
;
319 else if (strcmp (tok
, "16") == 0)
321 if ((lo
% 2 != 0) || (hi
% 2 != 0))
322 error (_("region bounds not 16 bit aligned"));
323 attrib
.width
= MEM_WIDTH_16
;
325 else if (strcmp (tok
, "32") == 0)
327 if ((lo
% 4 != 0) || (hi
% 4 != 0))
328 error (_("region bounds not 32 bit aligned"));
329 attrib
.width
= MEM_WIDTH_32
;
331 else if (strcmp (tok
, "64") == 0)
333 if ((lo
% 8 != 0) || (hi
% 8 != 0))
334 error (_("region bounds not 64 bit aligned"));
335 attrib
.width
= MEM_WIDTH_64
;
339 else if (strcmp (tok
, "hwbreak") == 0)
341 else if (strcmp (tok
, "swbreak") == 0)
345 else if (strcmp (tok
, "cache") == 0)
347 else if (strcmp (tok
, "nocache") == 0)
351 else if (strcmp (tok
, "verify") == 0)
353 else if (strcmp (tok
, "noverify") == 0)
358 error (_("unknown attribute: %s"), tok
);
361 create_mem_region (lo
, hi
, &attrib
);
366 mem_info_command (char *args
, int from_tty
)
368 struct mem_region
*m
;
369 struct mem_attrib
*attrib
;
373 printf_filtered (_("Using memory regions provided by the target.\n"));
375 printf_filtered (_("Using user-defined memory regions.\n"));
377 require_target_regions ();
379 if (!mem_region_list
)
381 printf_unfiltered (_("There are no memory regions defined.\n"));
385 printf_filtered ("Num ");
386 printf_filtered ("Enb ");
387 printf_filtered ("Low Addr ");
388 if (TARGET_ADDR_BIT
> 32)
389 printf_filtered (" ");
390 printf_filtered ("High Addr ");
391 if (TARGET_ADDR_BIT
> 32)
392 printf_filtered (" ");
393 printf_filtered ("Attrs ");
394 printf_filtered ("\n");
396 for (ix
= 0; VEC_iterate (mem_region_s
, mem_region_list
, ix
, m
); ix
++)
399 printf_filtered ("%-3d %-3c\t",
401 m
->enabled_p
? 'y' : 'n');
402 if (TARGET_ADDR_BIT
<= 32)
403 tmp
= hex_string_custom ((unsigned long) m
->lo
, 8);
405 tmp
= hex_string_custom ((unsigned long) m
->lo
, 16);
407 printf_filtered ("%s ", tmp
);
409 if (TARGET_ADDR_BIT
<= 32)
414 tmp
= hex_string_custom ((unsigned long) m
->hi
, 8);
419 tmp
= "0x10000000000000000";
421 tmp
= hex_string_custom ((unsigned long) m
->hi
, 16);
424 printf_filtered ("%s ", tmp
);
426 /* Print a token for each attribute.
428 * FIXME: Should we output a comma after each token? It may
429 * make it easier for users to read, but we'd lose the ability
430 * to cut-and-paste the list of attributes when defining a new
431 * region. Perhaps that is not important.
433 * FIXME: If more attributes are added to GDB, the output may
434 * become cluttered and difficult for users to read. At that
435 * time, we may want to consider printing tokens only if they
436 * are different from the default attribute. */
439 switch (attrib
->mode
)
442 printf_filtered ("rw ");
445 printf_filtered ("ro ");
448 printf_filtered ("wo ");
451 printf_filtered ("flash blocksize 0x%x ", attrib
->blocksize
);
455 switch (attrib
->width
)
458 printf_filtered ("8 ");
461 printf_filtered ("16 ");
464 printf_filtered ("32 ");
467 printf_filtered ("64 ");
469 case MEM_WIDTH_UNSPECIFIED
:
475 printf_filtered ("hwbreak");
477 printf_filtered ("swbreak");
481 printf_filtered ("cache ");
483 printf_filtered ("nocache ");
487 printf_filtered ("verify ");
489 printf_filtered ("noverify ");
492 printf_filtered ("\n");
494 gdb_flush (gdb_stdout
);
499 /* Enable the memory region number NUM. */
504 struct mem_region
*m
;
507 for (ix
= 0; VEC_iterate (mem_region_s
, mem_region_list
, ix
, m
); ix
++)
508 if (m
->number
== num
)
513 printf_unfiltered (_("No memory region number %d.\n"), num
);
517 mem_enable_command (char *args
, int from_tty
)
522 struct mem_region
*m
;
525 require_user_regions (from_tty
);
527 dcache_invalidate (target_dcache
);
531 for (ix
= 0; VEC_iterate (mem_region_s
, mem_region_list
, ix
, m
); ix
++)
538 while (*p1
>= '0' && *p1
<= '9')
540 if (*p1
&& *p1
!= ' ' && *p1
!= '\t')
541 error (_("Arguments must be memory region numbers."));
547 while (*p
== ' ' || *p
== '\t')
553 /* Disable the memory region number NUM. */
556 mem_disable (int num
)
558 struct mem_region
*m
;
561 for (ix
= 0; VEC_iterate (mem_region_s
, mem_region_list
, ix
, m
); ix
++)
562 if (m
->number
== num
)
567 printf_unfiltered (_("No memory region number %d.\n"), num
);
571 mem_disable_command (char *args
, int from_tty
)
576 struct mem_region
*m
;
579 require_user_regions (from_tty
);
581 dcache_invalidate (target_dcache
);
585 for (ix
= 0; VEC_iterate (mem_region_s
, mem_region_list
, ix
, m
); ix
++)
592 while (*p1
>= '0' && *p1
<= '9')
594 if (*p1
&& *p1
!= ' ' && *p1
!= '\t')
595 error (_("Arguments must be memory region numbers."));
601 while (*p
== ' ' || *p
== '\t')
606 /* Delete the memory region number NUM. */
611 struct mem_region
*m1
, *m
;
614 if (!mem_region_list
)
616 printf_unfiltered (_("No memory region number %d.\n"), num
);
620 for (ix
= 0; VEC_iterate (mem_region_s
, mem_region_list
, ix
, m
); ix
++)
621 if (m
->number
== num
)
626 printf_unfiltered (_("No memory region number %d.\n"), num
);
630 VEC_ordered_remove (mem_region_s
, mem_region_list
, ix
);
634 mem_delete_command (char *args
, int from_tty
)
640 require_user_regions (from_tty
);
642 dcache_invalidate (target_dcache
);
646 if (query ("Delete all memory regions? "))
655 while (*p1
>= '0' && *p1
<= '9')
657 if (*p1
&& *p1
!= ' ' && *p1
!= '\t')
658 error (_("Arguments must be memory region numbers."));
664 while (*p
== ' ' || *p
== '\t')
671 extern initialize_file_ftype _initialize_mem
; /* -Wmissing-prototype */
674 _initialize_mem (void)
676 add_com ("mem", class_vars
, mem_command
, _("\
677 Define attributes for memory region or reset memory region handling to\n\
680 mem <lo addr> <hi addr> [<mode> <width> <cache>], \n\
681 where <mode> may be rw (read/write), ro (read-only) or wo (write-only), \n\
682 <width> may be 8, 16, 32, or 64, and \n\
683 <cache> may be cache or nocache"));
685 add_cmd ("mem", class_vars
, mem_enable_command
, _("\
686 Enable memory region.\n\
687 Arguments are the code numbers of the memory regions to enable.\n\
688 Usage: enable mem <code number>\n\
689 Do \"info mem\" to see current list of code numbers."), &enablelist
);
691 add_cmd ("mem", class_vars
, mem_disable_command
, _("\
692 Disable memory region.\n\
693 Arguments are the code numbers of the memory regions to disable.\n\
694 Usage: disable mem <code number>\n\
695 Do \"info mem\" to see current list of code numbers."), &disablelist
);
697 add_cmd ("mem", class_vars
, mem_delete_command
, _("\
698 Delete memory region.\n\
699 Arguments are the code numbers of the memory regions to delete.\n\
700 Usage: delete mem <code number>\n\
701 Do \"info mem\" to see current list of code numbers."), &deletelist
);
703 add_info ("mem", mem_info_command
,
704 _("Memory region attributes"));