GDB (xrefs)
/tmp/gdb-8.1/gdb/memattr.c
Go to the documentation of this file.
1 /* Memory attributes support, for GDB.
2 
3  Copyright (C) 2001-2018 Free Software Foundation, Inc.
4 
5  This file is part of GDB.
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 
20 #include "defs.h"
21 #include "command.h"
22 #include "gdbcmd.h"
23 #include "memattr.h"
24 #include "target.h"
25 #include "target-dcache.h"
26 #include "value.h"
27 #include "language.h"
28 #include "vec.h"
29 #include "breakpoint.h"
30 #include "cli/cli-utils.h"
31 #include <algorithm>
32 
33 static std::vector<mem_region> user_mem_region_list, target_mem_region_list;
34 static std::vector<mem_region> *mem_region_list = &target_mem_region_list;
35 static int mem_number = 0;
36 
37 /* If this flag is set, the memory region list should be automatically
38  updated from the target. If it is clear, the list is user-controlled
39  and should be left alone. */
40 
41 static bool
43 {
45 }
46 
47 /* If this flag is set, we have tried to fetch the target memory regions
48  since the last time it was invalidated. If that list is still
49  empty, then the target can't supply memory regions. */
51 
52 /* If this flag is set, gdb will assume that memory ranges not
53  specified by the memory map have type MEM_NONE, and will
54  emit errors on all accesses to that memory. */
55 static int inaccessible_by_default = 1;
56 
57 static void
58 show_inaccessible_by_default (struct ui_file *file, int from_tty,
59  struct cmd_list_element *c,
60  const char *value)
61 {
63  fprintf_filtered (file, _("Unknown memory addresses will "
64  "be treated as inaccessible.\n"));
65  else
66  fprintf_filtered (file, _("Unknown memory addresses "
67  "will be treated as RAM.\n"));
68 }
69 
70 /* This function should be called before any command which would
71  modify the memory region list. It will handle switching from
72  a target-provided list to a local list, if necessary. */
73 
74 static void
75 require_user_regions (int from_tty)
76 {
77  /* If we're already using a user-provided list, nothing to do. */
78  if (!mem_use_target ())
79  return;
80 
81  /* Switch to a user-provided list (possibly a copy of the current
82  one). */
84 
85  /* If we don't have a target-provided region list yet, then
86  no need to warn. */
87  if (target_mem_region_list.empty ())
88  return;
89 
90  /* Otherwise, let the user know how to get back. */
91  if (from_tty)
92  warning (_("Switching to manual control of memory regions; use "
93  "\"mem auto\" to fetch regions from the target again."));
94 
95  /* And create a new list (copy of the target-supplied regions) for the user
96  to modify. */
98 }
99 
100 /* This function should be called before any command which would
101  read the memory region list, other than those which call
102  require_user_regions. It will handle fetching the
103  target-provided list, if necessary. */
104 
105 static void
107 {
109  {
112  }
113 }
114 
115 /* Create a new user-defined memory region. */
116 
117 static void
119  const mem_attrib &attrib)
120 {
121  /* lo == hi is a useless empty region. */
122  if (lo >= hi && hi != 0)
123  {
124  printf_unfiltered (_("invalid memory region: low >= high\n"));
125  return;
126  }
127 
128  mem_region newobj (lo, hi, attrib);
129 
130  auto it = std::lower_bound (user_mem_region_list.begin (),
131  user_mem_region_list.end (),
132  newobj);
133  int ix = std::distance (user_mem_region_list.begin (), it);
134 
135  /* Check for an overlapping memory region. We only need to check
136  in the vicinity - at most one before and one after the
137  insertion point. */
138  for (int i = ix - 1; i < ix + 1; i++)
139  {
140  if (i < 0)
141  continue;
142  if (i >= user_mem_region_list.size ())
143  continue;
144 
146 
147  if ((lo >= n.lo && (lo < n.hi || n.hi == 0))
148  || (hi > n.lo && (hi <= n.hi || n.hi == 0))
149  || (lo <= n.lo && ((hi >= n.hi && n.hi != 0) || hi == 0)))
150  {
151  printf_unfiltered (_("overlapping memory region\n"));
152  return;
153  }
154  }
155 
156  newobj.number = ++mem_number;
157  user_mem_region_list.insert (it, newobj);
158 }
159 
160 /* Look up the memory region corresponding to ADDR. */
161 
162 struct mem_region *
164 {
165  static struct mem_region region (0, 0);
166  CORE_ADDR lo;
167  CORE_ADDR hi;
168 
170 
171  /* First we initialize LO and HI so that they describe the entire
172  memory space. As we process the memory region chain, they are
173  redefined to describe the minimal region containing ADDR. LO
174  and HI are used in the case where no memory region is defined
175  that contains ADDR. If a memory region is disabled, it is
176  treated as if it does not exist. The initial values for LO
177  and HI represent the bottom and top of memory. */
178 
179  lo = 0;
180  hi = 0;
181 
182  /* Either find memory range containing ADDR, or set LO and HI
183  to the nearest boundaries of an existing memory range.
184 
185  If we ever want to support a huge list of memory regions, this
186  check should be replaced with a binary search (probably using
187  VEC_lower_bound). */
188  for (mem_region &m : *mem_region_list)
189  {
190  if (m.enabled_p == 1)
191  {
192  /* If the address is in the memory region, return that
193  memory range. */
194  if (addr >= m.lo && (addr < m.hi || m.hi == 0))
195  return &m;
196 
197  /* This (correctly) won't match if m->hi == 0, representing
198  the top of the address space, because CORE_ADDR is unsigned;
199  no value of LO is less than zero. */
200  if (addr >= m.hi && lo < m.hi)
201  lo = m.hi;
202 
203  /* This will never set HI to zero; if we're here and ADDR
204  is at or below M, and the region starts at zero, then ADDR
205  would have been in the region. */
206  if (addr <= m.lo && (hi == 0 || hi > m.lo))
207  hi = m.lo;
208  }
209  }
210 
211  /* Because no region was found, we must cons up one based on what
212  was learned above. */
213  region.lo = lo;
214  region.hi = hi;
215 
216  /* When no memory map is defined at all, we always return
217  'default_mem_attrib', so that we do not make all memory
218  inaccessible for targets that don't provide a memory map. */
219  if (inaccessible_by_default && !mem_region_list->empty ())
220  region.attrib = mem_attrib::unknown ();
221  else
222  region.attrib = mem_attrib ();
223 
224  return &region;
225 }
226 
227 /* Invalidate any memory regions fetched from the target. */
228 
229 void
231 {
233  return;
234 
235  target_mem_regions_valid = false;
236  target_mem_region_list.clear ();
237 }
238 
239 /* Clear user-defined memory region list. */
240 
241 static void
243 {
244  user_mem_region_list.clear ();
245 }
246 
247 
248 static void
249 mem_command (const char *args, int from_tty)
250 {
251  CORE_ADDR lo, hi;
252 
253  if (!args)
254  error_no_arg (_("No mem"));
255 
256  /* For "mem auto", switch back to using a target provided list. */
257  if (strcmp (args, "auto") == 0)
258  {
259  if (mem_use_target ())
260  return;
261 
262  user_mem_clear ();
264 
265  return;
266  }
267 
268  require_user_regions (from_tty);
269 
270  std::string tok = extract_arg (&args);
271  if (tok == "")
272  error (_("no lo address"));
273  lo = parse_and_eval_address (tok.c_str ());
274 
275  tok = extract_arg (&args);
276  if (tok == "")
277  error (_("no hi address"));
278  hi = parse_and_eval_address (tok.c_str ());
279 
281  while ((tok = extract_arg (&args)) != "")
282  {
283  if (tok == "rw")
284  attrib.mode = MEM_RW;
285  else if (tok == "ro")
286  attrib.mode = MEM_RO;
287  else if (tok == "wo")
288  attrib.mode = MEM_WO;
289 
290  else if (tok == "8")
292  else if (tok == "16")
293  {
294  if ((lo % 2 != 0) || (hi % 2 != 0))
295  error (_("region bounds not 16 bit aligned"));
297  }
298  else if (tok == "32")
299  {
300  if ((lo % 4 != 0) || (hi % 4 != 0))
301  error (_("region bounds not 32 bit aligned"));
303  }
304  else if (tok == "64")
305  {
306  if ((lo % 8 != 0) || (hi % 8 != 0))
307  error (_("region bounds not 64 bit aligned"));
309  }
310 
311 #if 0
312  else if (tok == "hwbreak")
313  attrib.hwbreak = 1;
314  else if (tok == "swbreak")
315  attrib.hwbreak = 0;
316 #endif
317 
318  else if (tok == "cache")
319  attrib.cache = 1;
320  else if (tok == "nocache")
321  attrib.cache = 0;
322 
323 #if 0
324  else if (tok == "verify")
325  attrib.verify = 1;
326  else if (tok == "noverify")
327  attrib.verify = 0;
328 #endif
329 
330  else
331  error (_("unknown attribute: %s"), tok.c_str ());
332  }
333 
335 }
336 
337 
338 static void
339 info_mem_command (const char *args, int from_tty)
340 {
341  if (mem_use_target ())
342  printf_filtered (_("Using memory regions provided by the target.\n"));
343  else
344  printf_filtered (_("Using user-defined memory regions.\n"));
345 
347 
348  if (mem_region_list->empty ())
349  {
350  printf_unfiltered (_("There are no memory regions defined.\n"));
351  return;
352  }
353 
354  printf_filtered ("Num ");
355  printf_filtered ("Enb ");
356  printf_filtered ("Low Addr ");
357  if (gdbarch_addr_bit (target_gdbarch ()) > 32)
358  printf_filtered (" ");
359  printf_filtered ("High Addr ");
360  if (gdbarch_addr_bit (target_gdbarch ()) > 32)
361  printf_filtered (" ");
362  printf_filtered ("Attrs ");
363  printf_filtered ("\n");
364 
365  for (const mem_region &m : *mem_region_list)
366  {
367  const char *tmp;
368 
369  printf_filtered ("%-3d %-3c\t",
370  m.number,
371  m.enabled_p ? 'y' : 'n');
372  if (gdbarch_addr_bit (target_gdbarch ()) <= 32)
373  tmp = hex_string_custom (m.lo, 8);
374  else
375  tmp = hex_string_custom (m.lo, 16);
376 
377  printf_filtered ("%s ", tmp);
378 
379  if (gdbarch_addr_bit (target_gdbarch ()) <= 32)
380  {
381  if (m.hi == 0)
382  tmp = "0x100000000";
383  else
384  tmp = hex_string_custom (m.hi, 8);
385  }
386  else
387  {
388  if (m.hi == 0)
389  tmp = "0x10000000000000000";
390  else
391  tmp = hex_string_custom (m.hi, 16);
392  }
393 
394  printf_filtered ("%s ", tmp);
395 
396  /* Print a token for each attribute.
397 
398  * FIXME: Should we output a comma after each token? It may
399  * make it easier for users to read, but we'd lose the ability
400  * to cut-and-paste the list of attributes when defining a new
401  * region. Perhaps that is not important.
402  *
403  * FIXME: If more attributes are added to GDB, the output may
404  * become cluttered and difficult for users to read. At that
405  * time, we may want to consider printing tokens only if they
406  * are different from the default attribute. */
407 
408  switch (m.attrib.mode)
409  {
410  case MEM_RW:
411  printf_filtered ("rw ");
412  break;
413  case MEM_RO:
414  printf_filtered ("ro ");
415  break;
416  case MEM_WO:
417  printf_filtered ("wo ");
418  break;
419  case MEM_FLASH:
420  printf_filtered ("flash blocksize 0x%x ", m.attrib.blocksize);
421  break;
422  }
423 
424  switch (m.attrib.width)
425  {
426  case MEM_WIDTH_8:
427  printf_filtered ("8 ");
428  break;
429  case MEM_WIDTH_16:
430  printf_filtered ("16 ");
431  break;
432  case MEM_WIDTH_32:
433  printf_filtered ("32 ");
434  break;
435  case MEM_WIDTH_64:
436  printf_filtered ("64 ");
437  break;
439  break;
440  }
441 
442 #if 0
443  if (attrib->hwbreak)
444  printf_filtered ("hwbreak");
445  else
446  printf_filtered ("swbreak");
447 #endif
448 
449  if (m.attrib.cache)
450  printf_filtered ("cache ");
451  else
452  printf_filtered ("nocache ");
453 
454 #if 0
455  if (attrib->verify)
456  printf_filtered ("verify ");
457  else
458  printf_filtered ("noverify ");
459 #endif
460 
461  printf_filtered ("\n");
462 
464  }
465 }
466 
467 
468 /* Enable the memory region number NUM. */
469 
470 static void
471 mem_enable (int num)
472 {
473  for (mem_region &m : *mem_region_list)
474  if (m.number == num)
475  {
476  m.enabled_p = 1;
477  return;
478  }
479  printf_unfiltered (_("No memory region number %d.\n"), num);
480 }
481 
482 static void
483 enable_mem_command (const char *args, int from_tty)
484 {
485  require_user_regions (from_tty);
486 
488 
489  if (args == NULL || *args == '\0')
490  { /* Enable all mem regions. */
491  for (mem_region &m : *mem_region_list)
492  m.enabled_p = 1;
493  }
494  else
495  {
496  number_or_range_parser parser (args);
497  while (!parser.finished ())
498  {
499  int num = parser.get_number ();
500  mem_enable (num);
501  }
502  }
503 }
504 
505 
506 /* Disable the memory region number NUM. */
507 
508 static void
509 mem_disable (int num)
510 {
511  for (mem_region &m : *mem_region_list)
512  if (m.number == num)
513  {
514  m.enabled_p = 0;
515  return;
516  }
517  printf_unfiltered (_("No memory region number %d.\n"), num);
518 }
519 
520 static void
521 disable_mem_command (const char *args, int from_tty)
522 {
523  require_user_regions (from_tty);
524 
526 
527  if (args == NULL || *args == '\0')
528  {
529  for (mem_region &m : *mem_region_list)
530  m.enabled_p = false;
531  }
532  else
533  {
534  number_or_range_parser parser (args);
535  while (!parser.finished ())
536  {
537  int num = parser.get_number ();
538  mem_disable (num);
539  }
540  }
541 }
542 
543 /* Delete the memory region number NUM. */
544 
545 static void
546 mem_delete (int num)
547 {
548  if (!mem_region_list)
549  {
550  printf_unfiltered (_("No memory region number %d.\n"), num);
551  return;
552  }
553 
554  auto it = std::remove_if (mem_region_list->begin (), mem_region_list->end (),
555  [num] (const mem_region &m)
556  {
557  return m.number == num;
558  });
559 
560  if (it != mem_region_list->end ())
561  mem_region_list->erase (it);
562  else
563  printf_unfiltered (_("No memory region number %d.\n"), num);
564 }
565 
566 static void
567 delete_mem_command (const char *args, int from_tty)
568 {
569  require_user_regions (from_tty);
570 
572 
573  if (args == NULL || *args == '\0')
574  {
575  if (query (_("Delete all memory regions? ")))
576  user_mem_clear ();
577  dont_repeat ();
578  return;
579  }
580 
581  number_or_range_parser parser (args);
582  while (!parser.finished ())
583  {
584  int num = parser.get_number ();
585  mem_delete (num);
586  }
587 
588  dont_repeat ();
589 }
590 
591 static void
592 dummy_cmd (const char *args, int from_tty)
593 {
594 }
595 
598 
599 void
601 {
602  add_com ("mem", class_vars, mem_command, _("\
603 Define attributes for memory region or reset memory region handling to\n\
604 target-based.\n\
605 Usage: mem auto\n\
606  mem <lo addr> <hi addr> [<mode> <width> <cache>],\n\
607 where <mode> may be rw (read/write), ro (read-only) or wo (write-only),\n\
608  <width> may be 8, 16, 32, or 64, and\n\
609  <cache> may be cache or nocache"));
610 
612 Enable memory region.\n\
613 Arguments are the code numbers of the memory regions to enable.\n\
614 Usage: enable mem <code number>...\n\
615 Do \"info mem\" to see current list of code numbers."), &enablelist);
616 
618 Disable memory region.\n\
619 Arguments are the code numbers of the memory regions to disable.\n\
620 Usage: disable mem <code number>...\n\
621 Do \"info mem\" to see current list of code numbers."), &disablelist);
622 
624 Delete memory region.\n\
625 Arguments are the code numbers of the memory regions to delete.\n\
626 Usage: delete mem <code number>...\n\
627 Do \"info mem\" to see current list of code numbers."), &deletelist);
628 
629  add_info ("mem", info_mem_command,
630  _("Memory region attributes"));
631 
632  add_prefix_cmd ("mem", class_vars, dummy_cmd, _("\
633 Memory regions settings"),
634  &mem_set_cmdlist, "set mem ",
635  0/* allow-unknown */, &setlist);
636  add_prefix_cmd ("mem", class_vars, dummy_cmd, _("\
637 Memory regions settings"),
638  &mem_show_cmdlist, "show mem ",
639  0/* allow-unknown */, &showlist);
640 
641  add_setshow_boolean_cmd ("inaccessible-by-default", no_class,
643 Set handling of unknown memory regions."), _("\
644 Show handling of unknown memory regions."), _("\
645 If on, and some memory map is defined, debugger will emit errors on\n\
646 accesses to memory not defined in the memory map. If off, accesses to all\n\
647 memory addresses will be allowed."),
648  NULL,
652 }
void error_no_arg(const char *why)
Definition: cli-cmds.c:185
struct gdbarch * target_gdbarch(void)
Definition: gdbarch.c:5467
const char * string
Definition: signals.c:50
Definition: memattr.h:27
bfd_vma CORE_ADDR
Definition: common-types.h:41
static void enable_mem_command(const char *args, int from_tty)
Definition: memattr.c:483
static mem_attrib unknown()
Definition: memattr.h:55
static void mem_enable(int num)
Definition: memattr.c:471
struct cmd_list_element * enablelist
Definition: cli-cmds.c:87
void warning(const char *fmt,...)
Definition: errors.c:26
int query(const char *ctlstr,...)
Definition: utils.c:1063
std::string extract_arg(const char **arg)
Definition: cli-utils.c:259
struct cmd_list_element * add_info(const char *name, cmd_const_cfunc_ftype *fun, const char *doc)
Definition: cli-decode.c:886
static void info_mem_command(const char *args, int from_tty)
Definition: memattr.c:339
struct cmd_list_element * deletelist
Definition: cli-cmds.c:99
static void mem_disable(int num)
Definition: memattr.c:509
struct cmd_list_element * add_cmd(const char *name, enum command_class theclass, const char *doc, struct cmd_list_element **list)
Definition: cli-decode.c:262
#define _(String)
Definition: gdb_locale.h:35
static std::vector< mem_region > user_mem_region_list
Definition: memattr.c:33
static void show_inaccessible_by_default(struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value)
Definition: memattr.c:58
static void require_user_regions(int from_tty)
Definition: memattr.c:75
void printf_filtered(const char *format,...)
Definition: utils.c:2045
void _initialize_mem(void)
Definition: memattr.c:600
CORE_ADDR lo
Definition: memattr.h:112
Definition: memattr.h:28
static struct cmd_list_element * mem_show_cmdlist
Definition: memattr.c:597
struct cmd_list_element * add_prefix_cmd(const char *name, enum command_class theclass, cmd_const_cfunc_ftype *fun, const char *doc, struct cmd_list_element **prefixlist, const char *prefixname, int allow_unknown, struct cmd_list_element **list)
Definition: cli-decode.c:367
struct cmd_list_element * setlist
Definition: cli-cmds.c:111
std::vector< mem_region > target_memory_map(void)
Definition: target.c:1483
int cache
Definition: memattr.h:73
static void dummy_cmd(const char *args, int from_tty)
Definition: memattr.c:592
static void create_user_mem_region(CORE_ADDR lo, CORE_ADDR hi, const mem_attrib &attrib)
Definition: memattr.c:118
void target_dcache_invalidate(void)
Definition: target-dcache.c:52
void fprintf_filtered(struct ui_file *stream, const char *format,...)
Definition: utils.c:2008
struct mem_region * lookup_mem_region(CORE_ADDR addr)
Definition: memattr.c:163
mem_attrib attrib
Definition: memattr.h:125
int hwbreak
Definition: memattr.h:70
bool finished() const
Definition: cli-utils.h:78
struct cmd_list_element * showlist
Definition: cli-cmds.c:119
static std::vector< mem_region > target_mem_region_list
Definition: memattr.c:33
static void mem_delete(int num)
Definition: memattr.c:546
static int mem_number
Definition: memattr.c:35
int gdbarch_addr_bit(struct gdbarch *gdbarch)
Definition: gdbarch.c:1848
void printf_unfiltered(const char *format,...)
Definition: utils.c:2056
int number
Definition: memattr.h:118
static struct cmd_list_element * mem_set_cmdlist
Definition: memattr.c:596
Definition: value.c:169
struct cmd_list_element * disablelist
Definition: cli-cmds.c:91
static void delete_mem_command(const char *args, int from_tty)
Definition: memattr.c:567
static std::vector< mem_region > * mem_region_list
Definition: memattr.c:34
CORE_ADDR parse_and_eval_address(const char *exp)
Definition: eval.c:101
static bool mem_use_target()
Definition: memattr.c:42
Definition: memattr.h:26
void add_setshow_boolean_cmd(const char *name, enum command_class theclass, int *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_const_sfunc_ftype *set_func, show_value_ftype *show_func, struct cmd_list_element **set_list, struct cmd_list_element **show_list)
Definition: cli-decode.c:569
int verify
Definition: memattr.h:77
CORE_ADDR hi
Definition: memattr.h:115
static void user_mem_clear(void)
Definition: memattr.c:242
static void disable_mem_command(const char *args, int from_tty)
Definition: memattr.c:521
static bool target_mem_regions_valid
Definition: memattr.c:50
static void mem_command(const char *args, int from_tty)
Definition: memattr.c:249
void dont_repeat(void)
Definition: top.c:695
void gdb_flush(struct ui_file *file)
Definition: ui-file.c:93
struct cmd_list_element * add_com(const char *name, enum command_class theclass, cmd_const_cfunc_ftype *fun, const char *doc)
Definition: cli-decode.c:902
void invalidate_target_mem_regions(void)
Definition: memattr.c:230
enum mem_access_width width
Definition: memattr.h:67
void error(const char *fmt,...)
Definition: errors.c:38
static int inaccessible_by_default
Definition: memattr.c:55
#define gdb_stdout
Definition: utils.h:340
enum mem_access_mode mode
Definition: memattr.h:65
static void require_target_regions(void)
Definition: memattr.c:106