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