1 /* Memory attributes support, for GDB.
3 Copyright 2001, 2002 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
29 #include "gdb_string.h"
31 const struct mem_attrib default_mem_attrib
=
34 MEM_WIDTH_UNSPECIFIED
,
40 static struct mem_region
*mem_region_chain
= NULL
;
41 static int mem_number
= 0;
43 static struct mem_region
*
44 create_mem_region (CORE_ADDR lo
, CORE_ADDR hi
,
45 const struct mem_attrib
*attrib
)
47 struct mem_region
*n
, *new;
49 /* lo == hi is a useless empty region */
50 if (lo
>= hi
&& hi
!= 0)
52 printf_unfiltered ("invalid memory region: low >= high\n");
59 /* overlapping node */
60 if ((lo
>= n
->lo
&& (lo
< n
->hi
|| n
->hi
== 0))
61 || (hi
> n
->lo
&& (hi
<= n
->hi
|| n
->hi
== 0))
62 || (lo
<= n
->lo
&& (hi
>= n
->hi
|| hi
== 0)))
64 printf_unfiltered ("overlapping memory region\n");
70 new = xmalloc (sizeof (struct mem_region
));
73 new->number
= ++mem_number
;
75 new->attrib
= *attrib
;
77 /* link in new node */
78 new->next
= mem_region_chain
;
79 mem_region_chain
= new;
85 delete_mem_region (struct mem_region
*m
)
91 * Look up the memory region cooresponding to ADDR.
94 lookup_mem_region (CORE_ADDR addr
)
96 static struct mem_region region
;
101 /* First we initialize LO and HI so that they describe the entire
102 memory space. As we process the memory region chain, they are
103 redefined to describe the minimal region containing ADDR. LO
104 and HI are used in the case where no memory region is defined
105 that contains ADDR. If a memory region is disabled, it is
106 treated as if it does not exist. */
109 hi
= (CORE_ADDR
) ~ 0;
111 for (m
= mem_region_chain
; m
; m
= m
->next
)
113 if (m
->enabled_p
== 1)
115 if (addr
>= m
->lo
&& (addr
< m
->hi
|| m
->hi
== 0))
118 if (addr
>= m
->hi
&& lo
< m
->hi
)
121 if (addr
<= m
->lo
&& hi
> m
->lo
)
126 /* Because no region was found, we must cons up one based on what
127 was learned above. */
130 region
.attrib
= default_mem_attrib
;
136 mem_command (char *args
, int from_tty
)
140 struct mem_attrib attrib
;
143 error_no_arg ("No mem");
145 tok
= strtok (args
, " \t");
147 error ("no lo address");
148 lo
= parse_and_eval_address (tok
);
150 tok
= strtok (NULL
, " \t");
152 error ("no hi address");
153 hi
= parse_and_eval_address (tok
);
155 attrib
= default_mem_attrib
;
156 while ((tok
= strtok (NULL
, " \t")) != NULL
)
158 if (strcmp (tok
, "rw") == 0)
159 attrib
.mode
= MEM_RW
;
160 else if (strcmp (tok
, "ro") == 0)
161 attrib
.mode
= MEM_RO
;
162 else if (strcmp (tok
, "wo") == 0)
163 attrib
.mode
= MEM_WO
;
165 else if (strcmp (tok
, "8") == 0)
166 attrib
.width
= MEM_WIDTH_8
;
167 else if (strcmp (tok
, "16") == 0)
169 if ((lo
% 2 != 0) || (hi
% 2 != 0))
170 error ("region bounds not 16 bit aligned");
171 attrib
.width
= MEM_WIDTH_16
;
173 else if (strcmp (tok
, "32") == 0)
175 if ((lo
% 4 != 0) || (hi
% 4 != 0))
176 error ("region bounds not 32 bit aligned");
177 attrib
.width
= MEM_WIDTH_32
;
179 else if (strcmp (tok
, "64") == 0)
181 if ((lo
% 8 != 0) || (hi
% 8 != 0))
182 error ("region bounds not 64 bit aligned");
183 attrib
.width
= MEM_WIDTH_64
;
187 else if (strcmp (tok
, "hwbreak") == 0)
189 else if (strcmp (tok
, "swbreak") == 0)
193 else if (strcmp (tok
, "cache") == 0)
195 else if (strcmp (tok
, "nocache") == 0)
199 else if (strcmp (tok
, "verify") == 0)
201 else if (strcmp (tok
, "noverify") == 0)
206 error ("unknown attribute: %s", tok
);
209 create_mem_region (lo
, hi
, &attrib
);
214 mem_info_command (char *args
, int from_tty
)
216 struct mem_region
*m
;
217 struct mem_attrib
*attrib
;
219 if (!mem_region_chain
)
221 printf_unfiltered ("There are no memory regions defined.\n");
225 printf_filtered ("Num ");
226 printf_filtered ("Enb ");
227 printf_filtered ("Low Addr ");
228 if (TARGET_ADDR_BIT
> 32)
229 printf_filtered (" ");
230 printf_filtered ("High Addr ");
231 if (TARGET_ADDR_BIT
> 32)
232 printf_filtered (" ");
233 printf_filtered ("Attrs ");
234 printf_filtered ("\n");
236 for (m
= mem_region_chain
; m
; m
= m
->next
)
240 printf_filtered ("%-3d %-3c\t",
242 m
->enabled_p
? 'y' : 'n');
243 if (TARGET_ADDR_BIT
<= 32)
244 tmp
= local_hex_string_custom ((unsigned long) m
->lo
, "08l");
246 tmp
= local_hex_string_custom ((unsigned long) m
->lo
, "016l");
248 printf_filtered ("%s ", tmp
);
249 hi
= (m
->hi
== 0 ? ~0 : m
->hi
);
251 if (TARGET_ADDR_BIT
<= 32)
252 tmp
= local_hex_string_custom ((unsigned long) hi
, "08l");
254 tmp
= local_hex_string_custom ((unsigned long) hi
, "016l");
256 printf_filtered ("%s ", tmp
);
258 /* Print a token for each attribute.
260 * FIXME: Should we output a comma after each token? It may
261 * make it easier for users to read, but we'd lose the ability
262 * to cut-and-paste the list of attributes when defining a new
263 * region. Perhaps that is not important.
265 * FIXME: If more attributes are added to GDB, the output may
266 * become cluttered and difficult for users to read. At that
267 * time, we may want to consider printing tokens only if they
268 * are different from the default attribute. */
271 switch (attrib
->mode
)
274 printf_filtered ("rw ");
277 printf_filtered ("ro ");
280 printf_filtered ("wo ");
284 switch (attrib
->width
)
287 printf_filtered ("8 ");
290 printf_filtered ("16 ");
293 printf_filtered ("32 ");
296 printf_filtered ("64 ");
298 case MEM_WIDTH_UNSPECIFIED
:
304 printf_filtered ("hwbreak");
306 printf_filtered ("swbreak");
310 printf_filtered ("cache ");
312 printf_filtered ("nocache ");
316 printf_filtered ("verify ");
318 printf_filtered ("noverify ");
321 printf_filtered ("\n");
323 gdb_flush (gdb_stdout
);
328 /* Enable the memory region number NUM. */
333 struct mem_region
*m
;
335 for (m
= mem_region_chain
; m
; m
= m
->next
)
336 if (m
->number
== num
)
341 printf_unfiltered ("No memory region number %d.\n", num
);
345 mem_enable_command (char *args
, int from_tty
)
350 struct mem_region
*m
;
352 dcache_invalidate (target_dcache
);
356 for (m
= mem_region_chain
; m
; m
= m
->next
)
363 while (*p1
>= '0' && *p1
<= '9')
365 if (*p1
&& *p1
!= ' ' && *p1
!= '\t')
366 error ("Arguments must be memory region numbers.");
372 while (*p
== ' ' || *p
== '\t')
378 /* Disable the memory region number NUM. */
381 mem_disable (int num
)
383 struct mem_region
*m
;
385 for (m
= mem_region_chain
; m
; m
= m
->next
)
386 if (m
->number
== num
)
391 printf_unfiltered ("No memory region number %d.\n", num
);
395 mem_disable_command (char *args
, int from_tty
)
400 struct mem_region
*m
;
402 dcache_invalidate (target_dcache
);
406 for (m
= mem_region_chain
; m
; m
= m
->next
)
413 while (*p1
>= '0' && *p1
<= '9')
415 if (*p1
&& *p1
!= ' ' && *p1
!= '\t')
416 error ("Arguments must be memory region numbers.");
422 while (*p
== ' ' || *p
== '\t')
427 /* Clear memory region list */
432 struct mem_region
*m
;
434 while ((m
= mem_region_chain
) != 0)
436 mem_region_chain
= m
->next
;
437 delete_mem_region (m
);
441 /* Delete the memory region number NUM. */
446 struct mem_region
*m1
, *m
;
448 if (!mem_region_chain
)
450 printf_unfiltered ("No memory region number %d.\n", num
);
454 if (mem_region_chain
->number
== num
)
456 m1
= mem_region_chain
;
457 mem_region_chain
= m1
->next
;
458 delete_mem_region (m1
);
461 for (m
= mem_region_chain
; m
->next
; m
= m
->next
)
463 if (m
->next
->number
== num
)
467 delete_mem_region (m1
);
474 mem_delete_command (char *args
, int from_tty
)
480 dcache_invalidate (target_dcache
);
484 if (query ("Delete all memory regions? "))
493 while (*p1
>= '0' && *p1
<= '9')
495 if (*p1
&& *p1
!= ' ' && *p1
!= '\t')
496 error ("Arguments must be memory region numbers.");
502 while (*p
== ' ' || *p
== '\t')
510 _initialize_mem (void)
512 add_com ("mem", class_vars
, mem_command
,
513 "Define attributes for memory region.\n\
514 Usage: mem <lo addr> <hi addr> [<mode> <width> <cache>], \n\
515 where <mode> may be rw (read/write), ro (read-only) or wo (write-only), \n\
516 <width> may be 8, 16, 32, or 64, and \n\
517 <cache> may be cache or nocache");
519 add_cmd ("mem", class_vars
, mem_enable_command
,
520 "Enable memory region.\n\
521 Arguments are the code numbers of the memory regions to enable.\n\
522 Usage: enable mem <code number>\n\
523 Do \"info mem\" to see current list of code numbers.", &enablelist
);
525 add_cmd ("mem", class_vars
, mem_disable_command
,
526 "Disable memory region.\n\
527 Arguments are the code numbers of the memory regions to disable.\n\
528 Usage: disable mem <code number>\n\
529 Do \"info mem\" to see current list of code numbers.", &disablelist
);
531 add_cmd ("mem", class_vars
, mem_delete_command
,
532 "Delete memory region.\n\
533 Arguments are the code numbers of the memory regions to delete.\n\
534 Usage: delete mem <code number>\n\
535 Do \"info mem\" to see current list of code numbers.", &deletelist
);
537 add_info ("mem", mem_info_command
,
538 "Memory region attributes");