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