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