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. The initial values for LO
213 and HI represent the bottom and top of memory. */
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
221 for (ix
= 0; VEC_iterate (mem_region_s
, mem_region_list
, ix
, m
); ix
++)
223 if (m
->enabled_p
== 1)
225 if (addr
>= m
->lo
&& (addr
< m
->hi
|| m
->hi
== 0))
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. */
231 if (addr
>= m
->hi
&& lo
< m
->hi
)
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
))
242 /* Because no region was found, we must cons up one based on what
243 was learned above. */
246 region
.attrib
= default_mem_attrib
;
250 /* Invalidate any memory regions fetched from the target. */
253 invalidate_target_mem_regions (void)
255 struct mem_region
*m
;
258 if (!target_mem_regions_valid
)
261 target_mem_regions_valid
= 0;
262 VEC_free (mem_region_s
, target_mem_region_list
);
264 mem_region_list
= NULL
;
267 /* Clear memory region list */
272 VEC_free (mem_region_s
, mem_region_list
);
277 mem_command (char *args
, int from_tty
)
281 struct mem_attrib attrib
;
284 error_no_arg (_("No mem"));
286 /* For "mem auto", switch back to using a target provided list. */
287 if (strcmp (args
, "auto") == 0)
292 if (mem_region_list
!= target_mem_region_list
)
295 mem_region_list
= target_mem_region_list
;
302 require_user_regions (from_tty
);
304 tok
= strtok (args
, " \t");
306 error (_("no lo address"));
307 lo
= parse_and_eval_address (tok
);
309 tok
= strtok (NULL
, " \t");
311 error (_("no hi address"));
312 hi
= parse_and_eval_address (tok
);
314 attrib
= default_mem_attrib
;
315 while ((tok
= strtok (NULL
, " \t")) != NULL
)
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
;
324 else if (strcmp (tok
, "8") == 0)
325 attrib
.width
= MEM_WIDTH_8
;
326 else if (strcmp (tok
, "16") == 0)
328 if ((lo
% 2 != 0) || (hi
% 2 != 0))
329 error (_("region bounds not 16 bit aligned"));
330 attrib
.width
= MEM_WIDTH_16
;
332 else if (strcmp (tok
, "32") == 0)
334 if ((lo
% 4 != 0) || (hi
% 4 != 0))
335 error (_("region bounds not 32 bit aligned"));
336 attrib
.width
= MEM_WIDTH_32
;
338 else if (strcmp (tok
, "64") == 0)
340 if ((lo
% 8 != 0) || (hi
% 8 != 0))
341 error (_("region bounds not 64 bit aligned"));
342 attrib
.width
= MEM_WIDTH_64
;
346 else if (strcmp (tok
, "hwbreak") == 0)
348 else if (strcmp (tok
, "swbreak") == 0)
352 else if (strcmp (tok
, "cache") == 0)
354 else if (strcmp (tok
, "nocache") == 0)
358 else if (strcmp (tok
, "verify") == 0)
360 else if (strcmp (tok
, "noverify") == 0)
365 error (_("unknown attribute: %s"), tok
);
368 create_mem_region (lo
, hi
, &attrib
);
373 mem_info_command (char *args
, int from_tty
)
375 struct mem_region
*m
;
376 struct mem_attrib
*attrib
;
380 printf_filtered (_("Using memory regions provided by the target.\n"));
382 printf_filtered (_("Using user-defined memory regions.\n"));
384 require_target_regions ();
386 if (!mem_region_list
)
388 printf_unfiltered (_("There are no memory regions defined.\n"));
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");
403 for (ix
= 0; VEC_iterate (mem_region_s
, mem_region_list
, ix
, m
); ix
++)
406 printf_filtered ("%-3d %-3c\t",
408 m
->enabled_p
? 'y' : 'n');
409 if (TARGET_ADDR_BIT
<= 32)
410 tmp
= hex_string_custom ((unsigned long) m
->lo
, 8);
412 tmp
= hex_string_custom ((unsigned long) m
->lo
, 16);
414 printf_filtered ("%s ", tmp
);
416 if (TARGET_ADDR_BIT
<= 32)
421 tmp
= hex_string_custom ((unsigned long) m
->hi
, 8);
426 tmp
= "0x10000000000000000";
428 tmp
= hex_string_custom ((unsigned long) m
->hi
, 16);
431 printf_filtered ("%s ", tmp
);
433 /* Print a token for each attribute.
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.
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. */
446 switch (attrib
->mode
)
449 printf_filtered ("rw ");
452 printf_filtered ("ro ");
455 printf_filtered ("wo ");
458 printf_filtered ("flash blocksize 0x%x ", attrib
->blocksize
);
462 switch (attrib
->width
)
465 printf_filtered ("8 ");
468 printf_filtered ("16 ");
471 printf_filtered ("32 ");
474 printf_filtered ("64 ");
476 case MEM_WIDTH_UNSPECIFIED
:
482 printf_filtered ("hwbreak");
484 printf_filtered ("swbreak");
488 printf_filtered ("cache ");
490 printf_filtered ("nocache ");
494 printf_filtered ("verify ");
496 printf_filtered ("noverify ");
499 printf_filtered ("\n");
501 gdb_flush (gdb_stdout
);
506 /* Enable the memory region number NUM. */
511 struct mem_region
*m
;
514 for (ix
= 0; VEC_iterate (mem_region_s
, mem_region_list
, ix
, m
); ix
++)
515 if (m
->number
== num
)
520 printf_unfiltered (_("No memory region number %d.\n"), num
);
524 mem_enable_command (char *args
, int from_tty
)
529 struct mem_region
*m
;
532 require_user_regions (from_tty
);
534 dcache_invalidate (target_dcache
);
538 for (ix
= 0; VEC_iterate (mem_region_s
, mem_region_list
, ix
, m
); ix
++)
545 while (*p1
>= '0' && *p1
<= '9')
547 if (*p1
&& *p1
!= ' ' && *p1
!= '\t')
548 error (_("Arguments must be memory region numbers."));
554 while (*p
== ' ' || *p
== '\t')
560 /* Disable the memory region number NUM. */
563 mem_disable (int num
)
565 struct mem_region
*m
;
568 for (ix
= 0; VEC_iterate (mem_region_s
, mem_region_list
, ix
, m
); ix
++)
569 if (m
->number
== num
)
574 printf_unfiltered (_("No memory region number %d.\n"), num
);
578 mem_disable_command (char *args
, int from_tty
)
583 struct mem_region
*m
;
586 require_user_regions (from_tty
);
588 dcache_invalidate (target_dcache
);
592 for (ix
= 0; VEC_iterate (mem_region_s
, mem_region_list
, ix
, m
); ix
++)
599 while (*p1
>= '0' && *p1
<= '9')
601 if (*p1
&& *p1
!= ' ' && *p1
!= '\t')
602 error (_("Arguments must be memory region numbers."));
608 while (*p
== ' ' || *p
== '\t')
613 /* Delete the memory region number NUM. */
618 struct mem_region
*m1
, *m
;
621 if (!mem_region_list
)
623 printf_unfiltered (_("No memory region number %d.\n"), num
);
627 for (ix
= 0; VEC_iterate (mem_region_s
, mem_region_list
, ix
, m
); ix
++)
628 if (m
->number
== num
)
633 printf_unfiltered (_("No memory region number %d.\n"), num
);
637 VEC_ordered_remove (mem_region_s
, mem_region_list
, ix
);
641 mem_delete_command (char *args
, int from_tty
)
647 require_user_regions (from_tty
);
649 dcache_invalidate (target_dcache
);
653 if (query ("Delete all memory regions? "))
662 while (*p1
>= '0' && *p1
<= '9')
664 if (*p1
&& *p1
!= ' ' && *p1
!= '\t')
665 error (_("Arguments must be memory region numbers."));
671 while (*p
== ' ' || *p
== '\t')
678 extern initialize_file_ftype _initialize_mem
; /* -Wmissing-prototype */
681 _initialize_mem (void)
683 add_com ("mem", class_vars
, mem_command
, _("\
684 Define attributes for memory region or reset memory region handling to\n\
687 mem <lo addr> <hi addr> [<mode> <width> <cache>], \n\
688 where <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\
690 <cache> may be cache or nocache"));
692 add_cmd ("mem", class_vars
, mem_enable_command
, _("\
693 Enable memory region.\n\
694 Arguments are the code numbers of the memory regions to enable.\n\
695 Usage: enable mem <code number>\n\
696 Do \"info mem\" to see current list of code numbers."), &enablelist
);
698 add_cmd ("mem", class_vars
, mem_disable_command
, _("\
699 Disable memory region.\n\
700 Arguments are the code numbers of the memory regions to disable.\n\
701 Usage: disable mem <code number>\n\
702 Do \"info mem\" to see current list of code numbers."), &disablelist
);
704 add_cmd ("mem", class_vars
, mem_delete_command
, _("\
705 Delete memory region.\n\
706 Arguments are the code numbers of the memory regions to delete.\n\
707 Usage: delete mem <code number>\n\
708 Do \"info mem\" to see current list of code numbers."), &deletelist
);
710 add_info ("mem", mem_info_command
,
711 _("Memory region attributes"));