2005-03-07 Manoj Iyer <manjo@austin.ibm.com>
[deliverable/binutils-gdb.git] / gdb / memattr.c
CommitLineData
80629b1b 1/* Memory attributes support, for GDB.
14a5e767
AC
2
3 Copyright 2001, 2002 Free Software Foundation, Inc.
80629b1b
EZ
4
5 This file is part of GDB.
6
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.
11
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.
16
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. */
21
29e57380
C
22#include "defs.h"
23#include "command.h"
24#include "gdbcmd.h"
25#include "memattr.h"
26#include "target.h"
27#include "value.h"
28#include "language.h"
29#include "gdb_string.h"
30
29e57380
C
31const struct mem_attrib default_mem_attrib =
32{
33 MEM_RW, /* mode */
34 MEM_WIDTH_UNSPECIFIED,
81a9a963
AC
35 0, /* hwbreak */
36 0, /* cache */
37 0 /* verify */
29e57380
C
38};
39
40static struct mem_region *mem_region_chain = NULL;
f4d650ec 41static int mem_number = 0;
29e57380
C
42
43static struct mem_region *
44create_mem_region (CORE_ADDR lo, CORE_ADDR hi,
45 const struct mem_attrib *attrib)
46{
3172dc30 47 struct mem_region *n, *new;
29e57380 48
b6d1a1d5 49 /* lo == hi is a useless empty region */
2b236d82 50 if (lo >= hi && hi != 0)
29e57380 51 {
a3f17187 52 printf_unfiltered (_("invalid memory region: low >= high\n"));
29e57380
C
53 return NULL;
54 }
55
56 n = mem_region_chain;
57 while (n)
58 {
59 /* overlapping node */
2b236d82
DH
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)))
29e57380 63 {
a3f17187 64 printf_unfiltered (_("overlapping memory region\n"));
29e57380
C
65 return NULL;
66 }
2ed3d0b5 67 n = n->next;
29e57380
C
68 }
69
70 new = xmalloc (sizeof (struct mem_region));
71 new->lo = lo;
72 new->hi = hi;
73 new->number = ++mem_number;
b5de0fa7 74 new->enabled_p = 1;
29e57380
C
75 new->attrib = *attrib;
76
77 /* link in new node */
78 new->next = mem_region_chain;
79 mem_region_chain = new;
80
81 return new;
82}
83
84static void
85delete_mem_region (struct mem_region *m)
86{
f4d650ec 87 xfree (m);
29e57380
C
88}
89
90/*
91 * Look up the memory region cooresponding to ADDR.
92 */
93struct mem_region *
94lookup_mem_region (CORE_ADDR addr)
95{
96 static struct mem_region region;
97 struct mem_region *m;
98 CORE_ADDR lo;
99 CORE_ADDR hi;
100
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. */
107
108 lo = (CORE_ADDR) 0;
109 hi = (CORE_ADDR) ~ 0;
110
111 for (m = mem_region_chain; m; m = m->next)
112 {
b5de0fa7 113 if (m->enabled_p == 1)
29e57380 114 {
2b236d82 115 if (addr >= m->lo && (addr < m->hi || m->hi == 0))
29e57380
C
116 return m;
117
118 if (addr >= m->hi && lo < m->hi)
119 lo = m->hi;
120
121 if (addr <= m->lo && hi > m->lo)
122 hi = m->lo;
123 }
124 }
125
126 /* Because no region was found, we must cons up one based on what
127 was learned above. */
128 region.lo = lo;
129 region.hi = hi;
130 region.attrib = default_mem_attrib;
131 return &region;
132}
133\f
134
135static void
136mem_command (char *args, int from_tty)
137{
138 CORE_ADDR lo, hi;
139 char *tok;
140 struct mem_attrib attrib;
141
142 if (!args)
e2e0b3e5 143 error_no_arg (_("No mem"));
29e57380
C
144
145 tok = strtok (args, " \t");
146 if (!tok)
8a3fe4f8 147 error (_("no lo address"));
29e57380
C
148 lo = parse_and_eval_address (tok);
149
150 tok = strtok (NULL, " \t");
151 if (!tok)
8a3fe4f8 152 error (_("no hi address"));
29e57380
C
153 hi = parse_and_eval_address (tok);
154
155 attrib = default_mem_attrib;
156 while ((tok = strtok (NULL, " \t")) != NULL)
157 {
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;
164
165 else if (strcmp (tok, "8") == 0)
166 attrib.width = MEM_WIDTH_8;
167 else if (strcmp (tok, "16") == 0)
168 {
169 if ((lo % 2 != 0) || (hi % 2 != 0))
8a3fe4f8 170 error (_("region bounds not 16 bit aligned"));
29e57380
C
171 attrib.width = MEM_WIDTH_16;
172 }
173 else if (strcmp (tok, "32") == 0)
174 {
175 if ((lo % 4 != 0) || (hi % 4 != 0))
8a3fe4f8 176 error (_("region bounds not 32 bit aligned"));
29e57380
C
177 attrib.width = MEM_WIDTH_32;
178 }
179 else if (strcmp (tok, "64") == 0)
180 {
181 if ((lo % 8 != 0) || (hi % 8 != 0))
8a3fe4f8 182 error (_("region bounds not 64 bit aligned"));
29e57380
C
183 attrib.width = MEM_WIDTH_64;
184 }
185
186#if 0
187 else if (strcmp (tok, "hwbreak") == 0)
81a9a963 188 attrib.hwbreak = 1;
29e57380 189 else if (strcmp (tok, "swbreak") == 0)
81a9a963 190 attrib.hwbreak = 0;
29e57380
C
191#endif
192
193 else if (strcmp (tok, "cache") == 0)
81a9a963 194 attrib.cache = 1;
29e57380 195 else if (strcmp (tok, "nocache") == 0)
81a9a963 196 attrib.cache = 0;
29e57380
C
197
198#if 0
199 else if (strcmp (tok, "verify") == 0)
81a9a963 200 attrib.verify = 1;
29e57380 201 else if (strcmp (tok, "noverify") == 0)
81a9a963 202 attrib.verify = 0;
29e57380
C
203#endif
204
205 else
8a3fe4f8 206 error (_("unknown attribute: %s"), tok);
29e57380
C
207 }
208
209 create_mem_region (lo, hi, &attrib);
210}
211\f
212
213static void
214mem_info_command (char *args, int from_tty)
215{
216 struct mem_region *m;
217 struct mem_attrib *attrib;
218
219 if (!mem_region_chain)
220 {
a3f17187 221 printf_unfiltered (_("There are no memory regions defined.\n"));
29e57380
C
222 return;
223 }
224
ab35b611
EZ
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");
235
29e57380
C
236 for (m = mem_region_chain; m; m = m->next)
237 {
ab35b611
EZ
238 char *tmp;
239 printf_filtered ("%-3d %-3c\t",
29e57380 240 m->number,
b5de0fa7 241 m->enabled_p ? 'y' : 'n');
ab35b611 242 if (TARGET_ADDR_BIT <= 32)
bb599908 243 tmp = hex_string_custom ((unsigned long) m->lo, 8);
ab35b611 244 else
bb599908 245 tmp = hex_string_custom ((unsigned long) m->lo, 16);
ab35b611
EZ
246
247 printf_filtered ("%s ", tmp);
2b236d82 248
ab35b611 249 if (TARGET_ADDR_BIT <= 32)
2163ab9d
DH
250 {
251 if (m->hi == 0)
252 tmp = "0x100000000";
253 else
bb599908 254 tmp = hex_string_custom ((unsigned long) m->hi, 8);
2163ab9d 255 }
ab35b611 256 else
2163ab9d
DH
257 {
258 if (m->hi == 0)
259 tmp = "0x10000000000000000";
260 else
bb599908 261 tmp = hex_string_custom ((unsigned long) m->hi, 16);
2163ab9d
DH
262 }
263
ab35b611 264 printf_filtered ("%s ", tmp);
29e57380
C
265
266 /* Print a token for each attribute.
267
268 * FIXME: Should we output a comma after each token? It may
269 * make it easier for users to read, but we'd lose the ability
270 * to cut-and-paste the list of attributes when defining a new
271 * region. Perhaps that is not important.
272 *
273 * FIXME: If more attributes are added to GDB, the output may
274 * become cluttered and difficult for users to read. At that
275 * time, we may want to consider printing tokens only if they
276 * are different from the default attribute. */
277
278 attrib = &m->attrib;
279 switch (attrib->mode)
280 {
281 case MEM_RW:
282 printf_filtered ("rw ");
283 break;
284 case MEM_RO:
285 printf_filtered ("ro ");
286 break;
287 case MEM_WO:
288 printf_filtered ("wo ");
289 break;
290 }
291
292 switch (attrib->width)
293 {
294 case MEM_WIDTH_8:
295 printf_filtered ("8 ");
296 break;
297 case MEM_WIDTH_16:
298 printf_filtered ("16 ");
299 break;
300 case MEM_WIDTH_32:
301 printf_filtered ("32 ");
302 break;
303 case MEM_WIDTH_64:
304 printf_filtered ("64 ");
305 break;
306 case MEM_WIDTH_UNSPECIFIED:
307 break;
308 }
309
310#if 0
311 if (attrib->hwbreak)
312 printf_filtered ("hwbreak");
313 else
314 printf_filtered ("swbreak");
315#endif
316
317 if (attrib->cache)
318 printf_filtered ("cache ");
319 else
320 printf_filtered ("nocache ");
321
322#if 0
323 if (attrib->verify)
324 printf_filtered ("verify ");
325 else
326 printf_filtered ("noverify ");
327#endif
328
329 printf_filtered ("\n");
330
331 gdb_flush (gdb_stdout);
332 }
333}
334\f
335
336/* Enable the memory region number NUM. */
337
338static void
339mem_enable (int num)
340{
341 struct mem_region *m;
342
343 for (m = mem_region_chain; m; m = m->next)
344 if (m->number == num)
345 {
b5de0fa7 346 m->enabled_p = 1;
29e57380
C
347 return;
348 }
a3f17187 349 printf_unfiltered (_("No memory region number %d.\n"), num);
29e57380
C
350}
351
352static void
353mem_enable_command (char *args, int from_tty)
354{
355 char *p = args;
356 char *p1;
357 int num;
358 struct mem_region *m;
359
360 dcache_invalidate (target_dcache);
361
362 if (p == 0)
363 {
364 for (m = mem_region_chain; m; m = m->next)
b5de0fa7 365 m->enabled_p = 1;
29e57380
C
366 }
367 else
368 while (*p)
369 {
370 p1 = p;
371 while (*p1 >= '0' && *p1 <= '9')
372 p1++;
373 if (*p1 && *p1 != ' ' && *p1 != '\t')
8a3fe4f8 374 error (_("Arguments must be memory region numbers."));
29e57380
C
375
376 num = atoi (p);
377 mem_enable (num);
378
379 p = p1;
380 while (*p == ' ' || *p == '\t')
381 p++;
382 }
383}
384\f
385
386/* Disable the memory region number NUM. */
387
388static void
389mem_disable (int num)
390{
391 struct mem_region *m;
392
393 for (m = mem_region_chain; m; m = m->next)
394 if (m->number == num)
395 {
b5de0fa7 396 m->enabled_p = 0;
29e57380
C
397 return;
398 }
a3f17187 399 printf_unfiltered (_("No memory region number %d.\n"), num);
29e57380
C
400}
401
402static void
403mem_disable_command (char *args, int from_tty)
404{
405 char *p = args;
406 char *p1;
407 int num;
408 struct mem_region *m;
409
410 dcache_invalidate (target_dcache);
411
412 if (p == 0)
413 {
414 for (m = mem_region_chain; m; m = m->next)
b5de0fa7 415 m->enabled_p = 0;
29e57380
C
416 }
417 else
418 while (*p)
419 {
420 p1 = p;
421 while (*p1 >= '0' && *p1 <= '9')
422 p1++;
423 if (*p1 && *p1 != ' ' && *p1 != '\t')
8a3fe4f8 424 error (_("Arguments must be memory region numbers."));
29e57380
C
425
426 num = atoi (p);
427 mem_disable (num);
428
429 p = p1;
430 while (*p == ' ' || *p == '\t')
431 p++;
432 }
433}
434
435/* Clear memory region list */
436
437static void
438mem_clear (void)
439{
440 struct mem_region *m;
441
442 while ((m = mem_region_chain) != 0)
443 {
444 mem_region_chain = m->next;
445 delete_mem_region (m);
446 }
447}
448
449/* Delete the memory region number NUM. */
450
451static void
452mem_delete (int num)
453{
454 struct mem_region *m1, *m;
455
456 if (!mem_region_chain)
457 {
a3f17187 458 printf_unfiltered (_("No memory region number %d.\n"), num);
29e57380
C
459 return;
460 }
461
462 if (mem_region_chain->number == num)
463 {
464 m1 = mem_region_chain;
465 mem_region_chain = m1->next;
466 delete_mem_region (m1);
467 }
468 else
469 for (m = mem_region_chain; m->next; m = m->next)
470 {
471 if (m->next->number == num)
472 {
473 m1 = m->next;
474 m->next = m1->next;
475 delete_mem_region (m1);
476 break;
477 }
478 }
479}
480
481static void
482mem_delete_command (char *args, int from_tty)
483{
484 char *p = args;
485 char *p1;
486 int num;
487
488 dcache_invalidate (target_dcache);
489
490 if (p == 0)
491 {
492 if (query ("Delete all memory regions? "))
493 mem_clear ();
494 dont_repeat ();
495 return;
496 }
497
498 while (*p)
499 {
500 p1 = p;
501 while (*p1 >= '0' && *p1 <= '9')
502 p1++;
503 if (*p1 && *p1 != ' ' && *p1 != '\t')
8a3fe4f8 504 error (_("Arguments must be memory region numbers."));
29e57380
C
505
506 num = atoi (p);
507 mem_delete (num);
508
509 p = p1;
510 while (*p == ' ' || *p == '\t')
511 p++;
512 }
513
514 dont_repeat ();
515}
516\f
b9362cc7
AC
517extern initialize_file_ftype _initialize_mem; /* -Wmissing-prototype */
518
29e57380 519void
5ae5f592 520_initialize_mem (void)
29e57380 521{
1bedd215
AC
522 add_com ("mem", class_vars, mem_command, _("\
523Define attributes for memory region.\n\
f9ba0717
MS
524Usage: mem <lo addr> <hi addr> [<mode> <width> <cache>], \n\
525where <mode> may be rw (read/write), ro (read-only) or wo (write-only), \n\
526 <width> may be 8, 16, 32, or 64, and \n\
1bedd215 527 <cache> may be cache or nocache"));
29e57380 528
1a966eab
AC
529 add_cmd ("mem", class_vars, mem_enable_command, _("\
530Enable memory region.\n\
29e57380 531Arguments are the code numbers of the memory regions to enable.\n\
ab35b611 532Usage: enable mem <code number>\n\
1a966eab 533Do \"info mem\" to see current list of code numbers."), &enablelist);
29e57380 534
1a966eab
AC
535 add_cmd ("mem", class_vars, mem_disable_command, _("\
536Disable memory region.\n\
29e57380 537Arguments are the code numbers of the memory regions to disable.\n\
ab35b611 538Usage: disable mem <code number>\n\
1a966eab 539Do \"info mem\" to see current list of code numbers."), &disablelist);
29e57380 540
1a966eab
AC
541 add_cmd ("mem", class_vars, mem_delete_command, _("\
542Delete memory region.\n\
29e57380 543Arguments are the code numbers of the memory regions to delete.\n\
ab35b611 544Usage: delete mem <code number>\n\
1a966eab 545Do \"info mem\" to see current list of code numbers."), &deletelist);
29e57380
C
546
547 add_info ("mem", mem_info_command,
1bedd215 548 _("Memory region attributes"));
29e57380 549}
This page took 0.80944 seconds and 4 git commands to generate.