OSDN Git Service

70f625bae46dd2d053472526c9413f25dc8d8cd9
[pf3gnuchains/pf3gnuchains4x.git] / gdb / memattr.c
1 /* Memory attributes support, for GDB.
2
3    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
4    Free Software Foundation, Inc.
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
20    Foundation, Inc., 51 Franklin Street, Fifth Floor,
21    Boston, MA 02110-1301, USA.  */
22
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"
30 #include "vec.h"
31 #include "gdb_string.h"
32
33 const struct mem_attrib default_mem_attrib =
34 {
35   MEM_RW,                       /* mode */
36   MEM_WIDTH_UNSPECIFIED,
37   0,                            /* hwbreak */
38   0,                            /* cache */
39   0,                            /* verify */
40   -1 /* Flash blocksize not specified.  */
41 };
42
43 VEC(mem_region_s) *mem_region_list, *target_mem_region_list;
44 static int mem_number = 0;
45
46 /* If this flag is set, the memory region list should be automatically
47    updated from the target.  If it is clear, the list is user-controlled
48    and should be left alone.  */
49 static int mem_use_target = 1;
50
51 /* If this flag is set, we have tried to fetch the target memory regions
52    since the last time it was invalidated.  If that list is still
53    empty, then the target can't supply memory regions.  */
54 static int target_mem_regions_valid;
55
56 /* Predicate function which returns true if LHS should sort before RHS
57    in a list of memory regions, useful for VEC_lower_bound.  */
58
59 static int
60 mem_region_lessthan (const struct mem_region *lhs,
61                      const struct mem_region *rhs)
62 {
63   return lhs->lo < rhs->lo;
64 }
65
66 /* A helper function suitable for qsort, used to sort a
67    VEC(mem_region_s) by starting address.  */
68
69 int
70 mem_region_cmp (const void *untyped_lhs, const void *untyped_rhs)
71 {
72   const struct mem_region *lhs = untyped_lhs;
73   const struct mem_region *rhs = untyped_rhs;
74
75   if (lhs->lo < rhs->lo)
76     return -1;
77   else if (lhs->lo == rhs->lo)
78     return 0;
79   else
80     return 1;
81 }
82
83 /* Allocate a new memory region, with default settings.  */
84
85 void
86 mem_region_init (struct mem_region *new)
87 {
88   memset (new, 0, sizeof (struct mem_region));
89   new->enabled_p = 1;
90   new->attrib = default_mem_attrib;
91 }
92
93 /* This function should be called before any command which would
94    modify the memory region list.  It will handle switching from
95    a target-provided list to a local list, if necessary.  */
96
97 static void
98 require_user_regions (int from_tty)
99 {
100   struct mem_region *m;
101   int ix, length;
102
103   /* If we're already using a user-provided list, nothing to do.  */
104   if (!mem_use_target)
105     return;
106
107   /* Switch to a user-provided list (possibly a copy of the current
108      one).  */
109   mem_use_target = 0;
110
111   /* If we don't have a target-provided region list yet, then
112      no need to warn.  */
113   if (mem_region_list == NULL)
114     return;
115
116   /* Otherwise, let the user know how to get back.  */
117   if (from_tty)
118     warning (_("Switching to manual control of memory regions; use "
119                "\"mem auto\" to fetch regions from the target again."));
120
121   /* And create a new list for the user to modify.  */
122   length = VEC_length (mem_region_s, target_mem_region_list);
123   mem_region_list = VEC_alloc (mem_region_s, length);
124   for (ix = 0; VEC_iterate (mem_region_s, target_mem_region_list, ix, m); ix++)
125     VEC_quick_push (mem_region_s, mem_region_list, m);
126 }
127
128 /* This function should be called before any command which would
129    read the memory region list, other than those which call
130    require_user_regions.  It will handle fetching the
131    target-provided list, if necessary.  */
132
133 static void
134 require_target_regions (void)
135 {
136   if (mem_use_target && !target_mem_regions_valid)
137     {
138       target_mem_regions_valid = 1;
139       target_mem_region_list = target_memory_map ();
140       mem_region_list = target_mem_region_list;
141     }
142 }
143
144 static void
145 create_mem_region (CORE_ADDR lo, CORE_ADDR hi,
146                    const struct mem_attrib *attrib)
147 {
148   struct mem_region new;
149   int i, ix;
150
151   /* lo == hi is a useless empty region */
152   if (lo >= hi && hi != 0)
153     {
154       printf_unfiltered (_("invalid memory region: low >= high\n"));
155       return;
156     }
157
158   mem_region_init (&new);
159   new.lo = lo;
160   new.hi = hi;
161
162   ix = VEC_lower_bound (mem_region_s, mem_region_list, &new,
163                         mem_region_lessthan);
164
165   /* Check for an overlapping memory region.  We only need to check
166      in the vicinity - at most one before and one after the
167      insertion point.  */
168   for (i = ix - 1; i < ix + 1; i++)
169     {
170       struct mem_region *n;
171
172       if (i < 0)
173         continue;
174       if (i >= VEC_length (mem_region_s, mem_region_list))
175         continue;
176
177       n = VEC_index (mem_region_s, mem_region_list, i);
178
179       if ((lo >= n->lo && (lo < n->hi || n->hi == 0)) 
180           || (hi > n->lo && (hi <= n->hi || n->hi == 0))
181           || (lo <= n->lo && (hi >= n->hi || hi == 0)))
182         {
183           printf_unfiltered (_("overlapping memory region\n"));
184           return;
185         }
186     }
187
188   new.number = ++mem_number;
189   new.attrib = *attrib;
190   VEC_safe_insert (mem_region_s, mem_region_list, ix, &new);
191 }
192
193 /*
194  * Look up the memory region cooresponding to ADDR.
195  */
196 struct mem_region *
197 lookup_mem_region (CORE_ADDR addr)
198 {
199   static struct mem_region region;
200   struct mem_region *m;
201   CORE_ADDR lo;
202   CORE_ADDR hi;
203   int ix;
204
205   require_target_regions ();
206
207   /* First we initialize LO and HI so that they describe the entire
208      memory space.  As we process the memory region chain, they are
209      redefined to describe the minimal region containing ADDR.  LO
210      and HI are used in the case where no memory region is defined
211      that contains ADDR.  If a memory region is disabled, it is
212      treated as if it does not exist.  */
213
214   lo = (CORE_ADDR) 0;
215   hi = (CORE_ADDR) ~ 0;
216
217   /* If we ever want to support a huge list of memory regions, this
218      check should be replaced with a binary search (probably using
219      VEC_lower_bound).  */
220   for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++)
221     {
222       if (m->enabled_p == 1)
223         {
224           if (addr >= m->lo && (addr < m->hi || m->hi == 0))
225             return m;
226
227           if (addr >= m->hi && lo < m->hi)
228             lo = m->hi;
229
230           if (addr <= m->lo && hi > m->lo)
231             hi = m->lo;
232         }
233     }
234
235   /* Because no region was found, we must cons up one based on what
236      was learned above.  */
237   region.lo = lo;
238   region.hi = hi;
239   region.attrib = default_mem_attrib;
240   return &region;
241 }
242
243 /* Invalidate any memory regions fetched from the target.  */
244
245 void
246 invalidate_target_mem_regions (void)
247 {
248   struct mem_region *m;
249   int ix;
250
251   if (!target_mem_regions_valid)
252     return;
253
254   target_mem_regions_valid = 0;
255   VEC_free (mem_region_s, target_mem_region_list);
256   if (mem_use_target)
257     mem_region_list = NULL;
258 }
259
260 /* Clear memory region list */
261
262 static void
263 mem_clear (void)
264 {
265   VEC_free (mem_region_s, mem_region_list);
266 }
267 \f
268
269 static void
270 mem_command (char *args, int from_tty)
271 {
272   CORE_ADDR lo, hi;
273   char *tok;
274   struct mem_attrib attrib;
275
276   if (!args)
277     error_no_arg (_("No mem"));
278
279   /* For "mem auto", switch back to using a target provided list.  */
280   if (strcmp (args, "auto") == 0)
281     {
282       if (mem_use_target)
283         return;
284
285       if (mem_region_list != target_mem_region_list)
286         {
287           mem_clear ();
288           mem_region_list = target_mem_region_list;
289         }
290
291       mem_use_target = 1;
292       return;
293     }
294
295   require_user_regions (from_tty);
296
297   tok = strtok (args, " \t");
298   if (!tok)
299     error (_("no lo address"));
300   lo = parse_and_eval_address (tok);
301
302   tok = strtok (NULL, " \t");
303   if (!tok)
304     error (_("no hi address"));
305   hi = parse_and_eval_address (tok);
306
307   attrib = default_mem_attrib;
308   while ((tok = strtok (NULL, " \t")) != NULL)
309     {
310       if (strcmp (tok, "rw") == 0)
311         attrib.mode = MEM_RW;
312       else if (strcmp (tok, "ro") == 0)
313         attrib.mode = MEM_RO;
314       else if (strcmp (tok, "wo") == 0)
315         attrib.mode = MEM_WO;
316
317       else if (strcmp (tok, "8") == 0)
318         attrib.width = MEM_WIDTH_8;
319       else if (strcmp (tok, "16") == 0)
320         {
321           if ((lo % 2 != 0) || (hi % 2 != 0))
322             error (_("region bounds not 16 bit aligned"));
323           attrib.width = MEM_WIDTH_16;
324         }
325       else if (strcmp (tok, "32") == 0)
326         {
327           if ((lo % 4 != 0) || (hi % 4 != 0))
328             error (_("region bounds not 32 bit aligned"));
329           attrib.width = MEM_WIDTH_32;
330         }
331       else if (strcmp (tok, "64") == 0)
332         {
333           if ((lo % 8 != 0) || (hi % 8 != 0))
334             error (_("region bounds not 64 bit aligned"));
335           attrib.width = MEM_WIDTH_64;
336         }
337
338 #if 0
339       else if (strcmp (tok, "hwbreak") == 0)
340         attrib.hwbreak = 1;
341       else if (strcmp (tok, "swbreak") == 0)
342         attrib.hwbreak = 0;
343 #endif
344
345       else if (strcmp (tok, "cache") == 0)
346         attrib.cache = 1;
347       else if (strcmp (tok, "nocache") == 0)
348         attrib.cache = 0;
349
350 #if 0
351       else if (strcmp (tok, "verify") == 0)
352         attrib.verify = 1;
353       else if (strcmp (tok, "noverify") == 0)
354         attrib.verify = 0;
355 #endif
356
357       else
358         error (_("unknown attribute: %s"), tok);
359     }
360
361   create_mem_region (lo, hi, &attrib);
362 }
363 \f
364
365 static void
366 mem_info_command (char *args, int from_tty)
367 {
368   struct mem_region *m;
369   struct mem_attrib *attrib;
370   int ix;
371
372   if (mem_use_target)
373     printf_filtered (_("Using memory regions provided by the target.\n"));
374   else
375     printf_filtered (_("Using user-defined memory regions.\n"));
376
377   require_target_regions ();
378
379   if (!mem_region_list)
380     {
381       printf_unfiltered (_("There are no memory regions defined.\n"));
382       return;
383     }
384
385   printf_filtered ("Num ");
386   printf_filtered ("Enb ");
387   printf_filtered ("Low Addr   ");
388   if (TARGET_ADDR_BIT > 32)
389     printf_filtered ("        ");
390   printf_filtered ("High Addr  ");
391   if (TARGET_ADDR_BIT > 32)
392     printf_filtered ("        ");
393   printf_filtered ("Attrs ");
394   printf_filtered ("\n");
395
396   for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++)
397     {
398       char *tmp;
399       printf_filtered ("%-3d %-3c\t",
400                        m->number,
401                        m->enabled_p ? 'y' : 'n');
402       if (TARGET_ADDR_BIT <= 32)
403         tmp = hex_string_custom ((unsigned long) m->lo, 8);
404       else
405         tmp = hex_string_custom ((unsigned long) m->lo, 16);
406       
407       printf_filtered ("%s ", tmp);
408
409       if (TARGET_ADDR_BIT <= 32)
410         {
411         if (m->hi == 0)
412           tmp = "0x100000000";
413         else
414           tmp = hex_string_custom ((unsigned long) m->hi, 8);
415         }
416       else
417         {
418         if (m->hi == 0)
419           tmp = "0x10000000000000000";
420         else
421           tmp = hex_string_custom ((unsigned long) m->hi, 16);
422         }
423
424       printf_filtered ("%s ", tmp);
425
426       /* Print a token for each attribute.
427
428        * FIXME: Should we output a comma after each token?  It may
429        * make it easier for users to read, but we'd lose the ability
430        * to cut-and-paste the list of attributes when defining a new
431        * region.  Perhaps that is not important.
432        *
433        * FIXME: If more attributes are added to GDB, the output may
434        * become cluttered and difficult for users to read.  At that
435        * time, we may want to consider printing tokens only if they
436        * are different from the default attribute.  */
437
438       attrib = &m->attrib;
439       switch (attrib->mode)
440         {
441         case MEM_RW:
442           printf_filtered ("rw ");
443           break;
444         case MEM_RO:
445           printf_filtered ("ro ");
446           break;
447         case MEM_WO:
448           printf_filtered ("wo ");
449           break;
450         case MEM_FLASH:
451           printf_filtered ("flash blocksize 0x%x ", attrib->blocksize);
452           break;
453         }
454
455       switch (attrib->width)
456         {
457         case MEM_WIDTH_8:
458           printf_filtered ("8 ");
459           break;
460         case MEM_WIDTH_16:
461           printf_filtered ("16 ");
462           break;
463         case MEM_WIDTH_32:
464           printf_filtered ("32 ");
465           break;
466         case MEM_WIDTH_64:
467           printf_filtered ("64 ");
468           break;
469         case MEM_WIDTH_UNSPECIFIED:
470           break;
471         }
472
473 #if 0
474       if (attrib->hwbreak)
475         printf_filtered ("hwbreak");
476       else
477         printf_filtered ("swbreak");
478 #endif
479
480       if (attrib->cache)
481         printf_filtered ("cache ");
482       else
483         printf_filtered ("nocache ");
484
485 #if 0
486       if (attrib->verify)
487         printf_filtered ("verify ");
488       else
489         printf_filtered ("noverify ");
490 #endif
491
492       printf_filtered ("\n");
493
494       gdb_flush (gdb_stdout);
495     }
496 }
497 \f
498
499 /* Enable the memory region number NUM. */
500
501 static void
502 mem_enable (int num)
503 {
504   struct mem_region *m;
505   int ix;
506
507   for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++)
508     if (m->number == num)
509       {
510         m->enabled_p = 1;
511         return;
512       }
513   printf_unfiltered (_("No memory region number %d.\n"), num);
514 }
515
516 static void
517 mem_enable_command (char *args, int from_tty)
518 {
519   char *p = args;
520   char *p1;
521   int num;
522   struct mem_region *m;
523   int ix;
524
525   require_user_regions (from_tty);
526
527   dcache_invalidate (target_dcache);
528
529   if (p == 0)
530     {
531       for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++)
532         m->enabled_p = 1;
533     }
534   else
535     while (*p)
536       {
537         p1 = p;
538         while (*p1 >= '0' && *p1 <= '9')
539           p1++;
540         if (*p1 && *p1 != ' ' && *p1 != '\t')
541           error (_("Arguments must be memory region numbers."));
542
543         num = atoi (p);
544         mem_enable (num);
545
546         p = p1;
547         while (*p == ' ' || *p == '\t')
548           p++;
549       }
550 }
551 \f
552
553 /* Disable the memory region number NUM. */
554
555 static void
556 mem_disable (int num)
557 {
558   struct mem_region *m;
559   int ix;
560
561   for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++)
562     if (m->number == num)
563       {
564         m->enabled_p = 0;
565         return;
566       }
567   printf_unfiltered (_("No memory region number %d.\n"), num);
568 }
569
570 static void
571 mem_disable_command (char *args, int from_tty)
572 {
573   char *p = args;
574   char *p1;
575   int num;
576   struct mem_region *m;
577   int ix;
578
579   require_user_regions (from_tty);
580
581   dcache_invalidate (target_dcache);
582
583   if (p == 0)
584     {
585       for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++)
586         m->enabled_p = 0;
587     }
588   else
589     while (*p)
590       {
591         p1 = p;
592         while (*p1 >= '0' && *p1 <= '9')
593           p1++;
594         if (*p1 && *p1 != ' ' && *p1 != '\t')
595           error (_("Arguments must be memory region numbers."));
596
597         num = atoi (p);
598         mem_disable (num);
599
600         p = p1;
601         while (*p == ' ' || *p == '\t')
602           p++;
603       }
604 }
605
606 /* Delete the memory region number NUM. */
607
608 static void
609 mem_delete (int num)
610 {
611   struct mem_region *m1, *m;
612   int ix;
613
614   if (!mem_region_list)
615     {
616       printf_unfiltered (_("No memory region number %d.\n"), num);
617       return;
618     }
619
620   for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++)
621     if (m->number == num)
622       break;
623
624   if (m == NULL)
625     {
626       printf_unfiltered (_("No memory region number %d.\n"), num);
627       return;
628     }
629
630   VEC_ordered_remove (mem_region_s, mem_region_list, ix);
631 }
632
633 static void
634 mem_delete_command (char *args, int from_tty)
635 {
636   char *p = args;
637   char *p1;
638   int num;
639
640   require_user_regions (from_tty);
641
642   dcache_invalidate (target_dcache);
643
644   if (p == 0)
645     {
646       if (query ("Delete all memory regions? "))
647         mem_clear ();
648       dont_repeat ();
649       return;
650     }
651
652   while (*p)
653     {
654       p1 = p;
655       while (*p1 >= '0' && *p1 <= '9')
656         p1++;
657       if (*p1 && *p1 != ' ' && *p1 != '\t')
658         error (_("Arguments must be memory region numbers."));
659
660       num = atoi (p);
661       mem_delete (num);
662
663       p = p1;
664       while (*p == ' ' || *p == '\t')
665         p++;
666     }
667
668   dont_repeat ();
669 }
670 \f
671 extern initialize_file_ftype _initialize_mem; /* -Wmissing-prototype */
672
673 void
674 _initialize_mem (void)
675 {
676   add_com ("mem", class_vars, mem_command, _("\
677 Define attributes for memory region or reset memory region handling to\n\
678 target-based.\n\
679 Usage: mem auto\n\
680        mem <lo addr> <hi addr> [<mode> <width> <cache>], \n\
681 where <mode>  may be rw (read/write), ro (read-only) or wo (write-only), \n\
682       <width> may be 8, 16, 32, or 64, and \n\
683       <cache> may be cache or nocache"));
684
685   add_cmd ("mem", class_vars, mem_enable_command, _("\
686 Enable memory region.\n\
687 Arguments are the code numbers of the memory regions to enable.\n\
688 Usage: enable mem <code number>\n\
689 Do \"info mem\" to see current list of code numbers."), &enablelist);
690
691   add_cmd ("mem", class_vars, mem_disable_command, _("\
692 Disable memory region.\n\
693 Arguments are the code numbers of the memory regions to disable.\n\
694 Usage: disable mem <code number>\n\
695 Do \"info mem\" to see current list of code numbers."), &disablelist);
696
697   add_cmd ("mem", class_vars, mem_delete_command, _("\
698 Delete memory region.\n\
699 Arguments are the code numbers of the memory regions to delete.\n\
700 Usage: delete mem <code number>\n\
701 Do \"info mem\" to see current list of code numbers."), &deletelist);
702
703   add_info ("mem", mem_info_command,
704             _("Memory region attributes"));
705 }