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