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