1 /* Memory attributes support, for GDB.
2 Copyright 2001 Free Software Foundation, Inc.
4 This file is part of GDB.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
28 #include "gdb_string.h"
30 /* FIXME: While this conflicts with the enum defined in breakpoint.h,
31 I used them to be consistant with how breakpoints, tracepoints, and
32 displays are implemented. It doesn't lose now because breakpoint.h
40 const struct mem_attrib default_mem_attrib
=
43 MEM_WIDTH_UNSPECIFIED
,
49 static struct mem_region
*mem_region_chain
= NULL
;
50 static int mem_number
= 0;
52 static struct mem_region
*
53 create_mem_region (CORE_ADDR lo
, CORE_ADDR hi
,
54 const struct mem_attrib
*attrib
)
56 struct mem_region
*n
, *new;
60 printf_unfiltered ("invalid memory region\n");
67 /* overlapping node */
68 if ((lo
>= n
->lo
&& lo
<= n
->hi
) ||
69 (hi
>= n
->lo
&& hi
<= n
->hi
))
71 printf_unfiltered ("overlapping memory region\n");
77 new = xmalloc (sizeof (struct mem_region
));
80 new->number
= ++mem_number
;
81 new->status
= enabled
;
82 new->attrib
= *attrib
;
84 /* link in new node */
85 new->next
= mem_region_chain
;
86 mem_region_chain
= new;
92 delete_mem_region (struct mem_region
*m
)
98 * Look up the memory region cooresponding to ADDR.
101 lookup_mem_region (CORE_ADDR addr
)
103 static struct mem_region region
;
104 struct mem_region
*m
;
108 /* First we initialize LO and HI so that they describe the entire
109 memory space. As we process the memory region chain, they are
110 redefined to describe the minimal region containing ADDR. LO
111 and HI are used in the case where no memory region is defined
112 that contains ADDR. If a memory region is disabled, it is
113 treated as if it does not exist. */
116 hi
= (CORE_ADDR
) ~ 0;
118 for (m
= mem_region_chain
; m
; m
= m
->next
)
120 if (m
->status
== enabled
)
122 if (addr
>= m
->lo
&& addr
< m
->hi
)
125 if (addr
>= m
->hi
&& lo
< m
->hi
)
128 if (addr
<= m
->lo
&& hi
> m
->lo
)
133 /* Because no region was found, we must cons up one based on what
134 was learned above. */
137 region
.attrib
= default_mem_attrib
;
143 mem_command (char *args
, int from_tty
)
147 struct mem_attrib attrib
;
150 error_no_arg ("No mem");
152 tok
= strtok (args
, " \t");
154 error ("no lo address");
155 lo
= parse_and_eval_address (tok
);
157 tok
= strtok (NULL
, " \t");
159 error ("no hi address");
160 hi
= parse_and_eval_address (tok
);
162 attrib
= default_mem_attrib
;
163 while ((tok
= strtok (NULL
, " \t")) != NULL
)
165 if (strcmp (tok
, "rw") == 0)
166 attrib
.mode
= MEM_RW
;
167 else if (strcmp (tok
, "ro") == 0)
168 attrib
.mode
= MEM_RO
;
169 else if (strcmp (tok
, "wo") == 0)
170 attrib
.mode
= MEM_WO
;
172 else if (strcmp (tok
, "8") == 0)
173 attrib
.width
= MEM_WIDTH_8
;
174 else if (strcmp (tok
, "16") == 0)
176 if ((lo
% 2 != 0) || (hi
% 2 != 0))
177 error ("region bounds not 16 bit aligned");
178 attrib
.width
= MEM_WIDTH_16
;
180 else if (strcmp (tok
, "32") == 0)
182 if ((lo
% 4 != 0) || (hi
% 4 != 0))
183 error ("region bounds not 32 bit aligned");
184 attrib
.width
= MEM_WIDTH_32
;
186 else if (strcmp (tok
, "64") == 0)
188 if ((lo
% 8 != 0) || (hi
% 8 != 0))
189 error ("region bounds not 64 bit aligned");
190 attrib
.width
= MEM_WIDTH_64
;
194 else if (strcmp (tok
, "hwbreak") == 0)
195 attrib
.hwbreak
= true;
196 else if (strcmp (tok
, "swbreak") == 0)
197 attrib
.hwbreak
= false;
200 else if (strcmp (tok
, "cache") == 0)
202 else if (strcmp (tok
, "nocache") == 0)
203 attrib
.cache
= false;
206 else if (strcmp (tok
, "verify") == 0)
207 attrib
.verify
= true;
208 else if (strcmp (tok
, "noverify") == 0)
209 attrib
.verify
= false;
213 error ("unknown attribute: %s", tok
);
216 create_mem_region (lo
, hi
, &attrib
);
221 mem_info_command (char *args
, int from_tty
)
223 struct mem_region
*m
;
224 struct mem_attrib
*attrib
;
226 if (!mem_region_chain
)
228 printf_unfiltered ("There are no memory regions defined.\n");
232 printf_filtered ("Num ");
233 printf_filtered ("Enb ");
234 printf_filtered ("Low Addr ");
235 if (TARGET_ADDR_BIT
> 32)
236 printf_filtered (" ");
237 printf_filtered ("High Addr ");
238 if (TARGET_ADDR_BIT
> 32)
239 printf_filtered (" ");
240 printf_filtered ("Attrs ");
241 printf_filtered ("\n");
243 for (m
= mem_region_chain
; m
; m
= m
->next
)
246 printf_filtered ("%-3d %-3c\t",
248 m
->status
? 'y' : 'n');
249 if (TARGET_ADDR_BIT
<= 32)
250 tmp
= longest_local_hex_string_custom ((unsigned long) m
->lo
, "08l");
252 tmp
= longest_local_hex_string_custom ((unsigned long) m
->lo
, "016l");
254 printf_filtered ("%s ", tmp
);
256 if (TARGET_ADDR_BIT
<= 32)
257 tmp
= longest_local_hex_string_custom ((unsigned long) m
->hi
, "08l");
259 tmp
= longest_local_hex_string_custom ((unsigned long) m
->hi
, "016l");
261 printf_filtered ("%s ", tmp
);
263 /* Print a token for each attribute.
265 * FIXME: Should we output a comma after each token? It may
266 * make it easier for users to read, but we'd lose the ability
267 * to cut-and-paste the list of attributes when defining a new
268 * region. Perhaps that is not important.
270 * FIXME: If more attributes are added to GDB, the output may
271 * become cluttered and difficult for users to read. At that
272 * time, we may want to consider printing tokens only if they
273 * are different from the default attribute. */
276 switch (attrib
->mode
)
279 printf_filtered ("rw ");
282 printf_filtered ("ro ");
285 printf_filtered ("wo ");
289 switch (attrib
->width
)
292 printf_filtered ("8 ");
295 printf_filtered ("16 ");
298 printf_filtered ("32 ");
301 printf_filtered ("64 ");
303 case MEM_WIDTH_UNSPECIFIED
:
309 printf_filtered ("hwbreak");
311 printf_filtered ("swbreak");
315 printf_filtered ("cache ");
317 printf_filtered ("nocache ");
321 printf_filtered ("verify ");
323 printf_filtered ("noverify ");
326 printf_filtered ("\n");
328 gdb_flush (gdb_stdout
);
333 /* Enable the memory region number NUM. */
338 struct mem_region
*m
;
340 for (m
= mem_region_chain
; m
; m
= m
->next
)
341 if (m
->number
== num
)
346 printf_unfiltered ("No memory region number %d.\n", num
);
350 mem_enable_command (char *args
, int from_tty
)
355 struct mem_region
*m
;
357 dcache_invalidate (target_dcache
);
361 for (m
= mem_region_chain
; m
; m
= m
->next
)
368 while (*p1
>= '0' && *p1
<= '9')
370 if (*p1
&& *p1
!= ' ' && *p1
!= '\t')
371 error ("Arguments must be memory region numbers.");
377 while (*p
== ' ' || *p
== '\t')
383 /* Disable the memory region number NUM. */
386 mem_disable (int num
)
388 struct mem_region
*m
;
390 for (m
= mem_region_chain
; m
; m
= m
->next
)
391 if (m
->number
== num
)
393 m
->status
= disabled
;
396 printf_unfiltered ("No memory region number %d.\n", num
);
400 mem_disable_command (char *args
, int from_tty
)
405 struct mem_region
*m
;
407 dcache_invalidate (target_dcache
);
411 for (m
= mem_region_chain
; m
; m
= m
->next
)
412 m
->status
= disabled
;
418 while (*p1
>= '0' && *p1
<= '9')
420 if (*p1
&& *p1
!= ' ' && *p1
!= '\t')
421 error ("Arguments must be memory region numbers.");
427 while (*p
== ' ' || *p
== '\t')
432 /* Clear memory region list */
437 struct mem_region
*m
;
439 while ((m
= mem_region_chain
) != 0)
441 mem_region_chain
= m
->next
;
442 delete_mem_region (m
);
446 /* Delete the memory region number NUM. */
451 struct mem_region
*m1
, *m
;
453 if (!mem_region_chain
)
455 printf_unfiltered ("No memory region number %d.\n", num
);
459 if (mem_region_chain
->number
== num
)
461 m1
= mem_region_chain
;
462 mem_region_chain
= m1
->next
;
463 delete_mem_region (m1
);
466 for (m
= mem_region_chain
; m
->next
; m
= m
->next
)
468 if (m
->next
->number
== num
)
472 delete_mem_region (m1
);
479 mem_delete_command (char *args
, int from_tty
)
485 dcache_invalidate (target_dcache
);
489 if (query ("Delete all memory regions? "))
498 while (*p1
>= '0' && *p1
<= '9')
500 if (*p1
&& *p1
!= ' ' && *p1
!= '\t')
501 error ("Arguments must be memory region numbers.");
507 while (*p
== ' ' || *p
== '\t')
517 add_com ("mem", class_vars
, mem_command
,
518 "Define attributes for memory region.\n\
519 Usage: mem <lo addr> <hi addr> [<mode> <width> <cache>]");
521 add_cmd ("mem", class_vars
, mem_enable_command
,
522 "Enable memory region.\n\
523 Arguments are the code numbers of the memory regions to enable.\n\
524 Usage: enable mem <code number>\n\
525 Do \"info mem\" to see current list of code numbers.", &enablelist
);
527 add_cmd ("mem", class_vars
, mem_disable_command
,
528 "Disable memory region.\n\
529 Arguments are the code numbers of the memory regions to disable.\n\
530 Usage: disable mem <code number>\n\
531 Do \"info mem\" to see current list of code numbers.", &disablelist
);
533 add_cmd ("mem", class_vars
, mem_delete_command
,
534 "Delete memory region.\n\
535 Arguments are the code numbers of the memory regions to delete.\n\
536 Usage: delete mem <code number>\n\
537 Do \"info mem\" to see current list of code numbers.", &deletelist
);
539 add_info ("mem", mem_info_command
,
540 "Memory region attributes");