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