2002-08-08 Michael Snyder <msnyder@redhat.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 {
b6d1a1d5 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
C
63 {
64 printf_unfiltered ("overlapping memory region\n");
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)
143 error_no_arg ("No mem");
144
145 tok = strtok (args, " \t");
146 if (!tok)
147 error ("no lo address");
148 lo = parse_and_eval_address (tok);
149
150 tok = strtok (NULL, " \t");
151 if (!tok)
152 error ("no hi address");
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))
170 error ("region bounds not 16 bit aligned");
171 attrib.width = MEM_WIDTH_16;
172 }
173 else if (strcmp (tok, "32") == 0)
174 {
175 if ((lo % 4 != 0) || (hi % 4 != 0))
176 error ("region bounds not 32 bit aligned");
177 attrib.width = MEM_WIDTH_32;
178 }
179 else if (strcmp (tok, "64") == 0)
180 {
181 if ((lo % 8 != 0) || (hi % 8 != 0))
182 error ("region bounds not 64 bit aligned");
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
206 error ("unknown attribute: %s", tok);
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 {
221 printf_unfiltered ("There are no memory regions defined.\n");
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 {
2b236d82 238 CORE_ADDR hi;
ab35b611
EZ
239 char *tmp;
240 printf_filtered ("%-3d %-3c\t",
29e57380 241 m->number,
b5de0fa7 242 m->enabled_p ? 'y' : 'n');
ab35b611 243 if (TARGET_ADDR_BIT <= 32)
14a5e767 244 tmp = local_hex_string_custom ((unsigned long) m->lo, "08l");
ab35b611 245 else
14a5e767 246 tmp = local_hex_string_custom ((unsigned long) m->lo, "016l");
ab35b611
EZ
247
248 printf_filtered ("%s ", tmp);
2b236d82
DH
249 hi = (m->hi == 0 ? ~0 : m->hi);
250
ab35b611 251 if (TARGET_ADDR_BIT <= 32)
2b236d82 252 tmp = local_hex_string_custom ((unsigned long) hi, "08l");
ab35b611 253 else
2b236d82 254 tmp = local_hex_string_custom ((unsigned long) hi, "016l");
ab35b611
EZ
255
256 printf_filtered ("%s ", tmp);
29e57380
C
257
258 /* Print a token for each attribute.
259
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.
264 *
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. */
269
270 attrib = &m->attrib;
271 switch (attrib->mode)
272 {
273 case MEM_RW:
274 printf_filtered ("rw ");
275 break;
276 case MEM_RO:
277 printf_filtered ("ro ");
278 break;
279 case MEM_WO:
280 printf_filtered ("wo ");
281 break;
282 }
283
284 switch (attrib->width)
285 {
286 case MEM_WIDTH_8:
287 printf_filtered ("8 ");
288 break;
289 case MEM_WIDTH_16:
290 printf_filtered ("16 ");
291 break;
292 case MEM_WIDTH_32:
293 printf_filtered ("32 ");
294 break;
295 case MEM_WIDTH_64:
296 printf_filtered ("64 ");
297 break;
298 case MEM_WIDTH_UNSPECIFIED:
299 break;
300 }
301
302#if 0
303 if (attrib->hwbreak)
304 printf_filtered ("hwbreak");
305 else
306 printf_filtered ("swbreak");
307#endif
308
309 if (attrib->cache)
310 printf_filtered ("cache ");
311 else
312 printf_filtered ("nocache ");
313
314#if 0
315 if (attrib->verify)
316 printf_filtered ("verify ");
317 else
318 printf_filtered ("noverify ");
319#endif
320
321 printf_filtered ("\n");
322
323 gdb_flush (gdb_stdout);
324 }
325}
326\f
327
328/* Enable the memory region number NUM. */
329
330static void
331mem_enable (int num)
332{
333 struct mem_region *m;
334
335 for (m = mem_region_chain; m; m = m->next)
336 if (m->number == num)
337 {
b5de0fa7 338 m->enabled_p = 1;
29e57380
C
339 return;
340 }
341 printf_unfiltered ("No memory region number %d.\n", num);
342}
343
344static void
345mem_enable_command (char *args, int from_tty)
346{
347 char *p = args;
348 char *p1;
349 int num;
350 struct mem_region *m;
351
352 dcache_invalidate (target_dcache);
353
354 if (p == 0)
355 {
356 for (m = mem_region_chain; m; m = m->next)
b5de0fa7 357 m->enabled_p = 1;
29e57380
C
358 }
359 else
360 while (*p)
361 {
362 p1 = p;
363 while (*p1 >= '0' && *p1 <= '9')
364 p1++;
365 if (*p1 && *p1 != ' ' && *p1 != '\t')
366 error ("Arguments must be memory region numbers.");
367
368 num = atoi (p);
369 mem_enable (num);
370
371 p = p1;
372 while (*p == ' ' || *p == '\t')
373 p++;
374 }
375}
376\f
377
378/* Disable the memory region number NUM. */
379
380static void
381mem_disable (int num)
382{
383 struct mem_region *m;
384
385 for (m = mem_region_chain; m; m = m->next)
386 if (m->number == num)
387 {
b5de0fa7 388 m->enabled_p = 0;
29e57380
C
389 return;
390 }
391 printf_unfiltered ("No memory region number %d.\n", num);
392}
393
394static void
395mem_disable_command (char *args, int from_tty)
396{
397 char *p = args;
398 char *p1;
399 int num;
400 struct mem_region *m;
401
402 dcache_invalidate (target_dcache);
403
404 if (p == 0)
405 {
406 for (m = mem_region_chain; m; m = m->next)
b5de0fa7 407 m->enabled_p = 0;
29e57380
C
408 }
409 else
410 while (*p)
411 {
412 p1 = p;
413 while (*p1 >= '0' && *p1 <= '9')
414 p1++;
415 if (*p1 && *p1 != ' ' && *p1 != '\t')
416 error ("Arguments must be memory region numbers.");
417
418 num = atoi (p);
419 mem_disable (num);
420
421 p = p1;
422 while (*p == ' ' || *p == '\t')
423 p++;
424 }
425}
426
427/* Clear memory region list */
428
429static void
430mem_clear (void)
431{
432 struct mem_region *m;
433
434 while ((m = mem_region_chain) != 0)
435 {
436 mem_region_chain = m->next;
437 delete_mem_region (m);
438 }
439}
440
441/* Delete the memory region number NUM. */
442
443static void
444mem_delete (int num)
445{
446 struct mem_region *m1, *m;
447
448 if (!mem_region_chain)
449 {
450 printf_unfiltered ("No memory region number %d.\n", num);
451 return;
452 }
453
454 if (mem_region_chain->number == num)
455 {
456 m1 = mem_region_chain;
457 mem_region_chain = m1->next;
458 delete_mem_region (m1);
459 }
460 else
461 for (m = mem_region_chain; m->next; m = m->next)
462 {
463 if (m->next->number == num)
464 {
465 m1 = m->next;
466 m->next = m1->next;
467 delete_mem_region (m1);
468 break;
469 }
470 }
471}
472
473static void
474mem_delete_command (char *args, int from_tty)
475{
476 char *p = args;
477 char *p1;
478 int num;
479
480 dcache_invalidate (target_dcache);
481
482 if (p == 0)
483 {
484 if (query ("Delete all memory regions? "))
485 mem_clear ();
486 dont_repeat ();
487 return;
488 }
489
490 while (*p)
491 {
492 p1 = p;
493 while (*p1 >= '0' && *p1 <= '9')
494 p1++;
495 if (*p1 && *p1 != ' ' && *p1 != '\t')
496 error ("Arguments must be memory region numbers.");
497
498 num = atoi (p);
499 mem_delete (num);
500
501 p = p1;
502 while (*p == ' ' || *p == '\t')
503 p++;
504 }
505
506 dont_repeat ();
507}
508\f
509void
5ae5f592 510_initialize_mem (void)
29e57380
C
511{
512 add_com ("mem", class_vars, mem_command,
ab35b611 513 "Define attributes for memory region.\n\
f9ba0717
MS
514Usage: mem <lo addr> <hi addr> [<mode> <width> <cache>], \n\
515where <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");
29e57380
C
518
519 add_cmd ("mem", class_vars, mem_enable_command,
520 "Enable memory region.\n\
521Arguments are the code numbers of the memory regions to enable.\n\
ab35b611 522Usage: enable mem <code number>\n\
29e57380
C
523Do \"info mem\" to see current list of code numbers.", &enablelist);
524
525 add_cmd ("mem", class_vars, mem_disable_command,
526 "Disable memory region.\n\
527Arguments are the code numbers of the memory regions to disable.\n\
ab35b611 528Usage: disable mem <code number>\n\
29e57380
C
529Do \"info mem\" to see current list of code numbers.", &disablelist);
530
531 add_cmd ("mem", class_vars, mem_delete_command,
532 "Delete memory region.\n\
533Arguments are the code numbers of the memory regions to delete.\n\
ab35b611 534Usage: delete mem <code number>\n\
29e57380
C
535Do \"info mem\" to see current list of code numbers.", &deletelist);
536
537 add_info ("mem", mem_info_command,
538 "Memory region attributes");
539}
This page took 0.171952 seconds and 4 git commands to generate.