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