1/* Simulator memory option handling.
2   Copyright (C) 1996-1999, 2007, 2008, 2009, 2010, 2011
3   Free Software Foundation, Inc.
4   Contributed by Cygnus Support.
5
6This file is part of GDB, the GNU debugger.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 3 of the License, or
11(at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21#include "cconfig.h"
22
23#include "sim-main.h"
24#include "sim-assert.h"
25#include "sim-options.h"
26
27#ifdef HAVE_STRING_H
28#include <string.h>
29#else
30#ifdef HAVE_STRINGS_H
31#include <strings.h>
32#endif
33#endif
34#ifdef HAVE_STDLIB_H
35#include <stdlib.h>
36#endif
37#ifdef HAVE_ERRNO_H
38#include <errno.h>
39#endif
40#ifdef HAVE_FCNTL_H
41#include <fcntl.h>
42#endif
43#ifdef HAVE_SYS_MMAN_H
44#include <sys/mman.h>
45#endif
46#ifdef HAVE_SYS_STAT_H
47#include <sys/stat.h>
48#endif
49#ifdef HAVE_UNISTD_H
50#include <unistd.h>
51#endif
52
53/* Memory fill byte. */
54static unsigned8 fill_byte_value;
55static int fill_byte_flag = 0;
56
57/* Memory mapping; see OPTION_MEMORY_MAPFILE. */
58static int mmap_next_fd = -1;
59
60/* Memory command line options. */
61
62enum {
63  OPTION_MEMORY_DELETE = OPTION_START,
64  OPTION_MEMORY_REGION,
65  OPTION_MEMORY_SIZE,
66  OPTION_MEMORY_INFO,
67  OPTION_MEMORY_ALIAS,
68  OPTION_MEMORY_CLEAR,
69  OPTION_MEMORY_FILL,
70  OPTION_MEMORY_MAPFILE,
71  OPTION_MAP_INFO
72};
73
74static DECLARE_OPTION_HANDLER (memory_option_handler);
75
76static const OPTION memory_options[] =
77{
78  { {"memory-delete", required_argument, NULL, OPTION_MEMORY_DELETE },
79      '\0', "ADDRESS|all", "Delete memory at ADDRESS (all addresses)",
80      memory_option_handler },
81  { {"delete-memory", required_argument, NULL, OPTION_MEMORY_DELETE },
82      '\0', "ADDRESS", NULL,
83      memory_option_handler },
84
85  { {"memory-region", required_argument, NULL, OPTION_MEMORY_REGION },
86      '\0', "ADDRESS,SIZE[,MODULO]", "Add a memory region",
87      memory_option_handler },
88
89  { {"memory-alias", required_argument, NULL, OPTION_MEMORY_ALIAS },
90      '\0', "ADDRESS,SIZE{,ADDRESS}", "Add memory shadow",
91      memory_option_handler },
92
93  { {"memory-size", required_argument, NULL, OPTION_MEMORY_SIZE },
94      '\0', "<size>[in bytes, Kb (k suffix), Mb (m suffix) or Gb (g suffix)]",
95     "Add memory at address zero", memory_option_handler },
96
97  { {"memory-fill", required_argument, NULL, OPTION_MEMORY_FILL },
98      '\0', "VALUE", "Fill subsequently added memory regions",
99      memory_option_handler },
100
101  { {"memory-clear", no_argument, NULL, OPTION_MEMORY_CLEAR },
102      '\0', NULL, "Clear subsequently added memory regions",
103      memory_option_handler },
104
105#if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
106  { {"memory-mapfile", required_argument, NULL, OPTION_MEMORY_MAPFILE },
107      '\0', "FILE", "Memory-map next memory region from file",
108      memory_option_handler },
109#endif
110
111  { {"memory-info", no_argument, NULL, OPTION_MEMORY_INFO },
112      '\0', NULL, "List configurable memory regions",
113      memory_option_handler },
114  { {"info-memory", no_argument, NULL, OPTION_MEMORY_INFO },
115      '\0', NULL, NULL,
116      memory_option_handler },
117  { {"map-info", no_argument, NULL, OPTION_MAP_INFO },
118      '\0', NULL, "List mapped regions",
119      memory_option_handler },
120
121  { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
122};
123
124
125static sim_memopt *
126do_memopt_add (SIM_DESC sd,
127	       int level,
128	       int space,
129	       address_word addr,
130	       address_word nr_bytes,
131	       unsigned modulo,
132	       sim_memopt **entry,
133	       void *buffer)
134{
135  void *fill_buffer;
136  unsigned fill_length;
137  void *free_buffer;
138  unsigned long free_length;
139
140  if (buffer != NULL)
141    {
142      /* Buffer already given.  sim_memory_uninstall will free it. */
143      sim_core_attach (sd, NULL,
144		       level, access_read_write_exec, space,
145		       addr, nr_bytes, modulo, NULL, buffer);
146
147      free_buffer = buffer;
148      free_length = 0;
149      fill_buffer = buffer;
150      fill_length = (modulo == 0) ? nr_bytes : modulo;
151    }
152  else
153    {
154      /* Allocate new well-aligned buffer, just as sim_core_attach(). */
155      void *aligned_buffer;
156      int padding = (addr % sizeof (unsigned64));
157      unsigned long bytes;
158
159#ifdef HAVE_MMAP
160      struct stat s;
161
162      if (mmap_next_fd >= 0)
163	{
164	  /* Check that given file is big enough. */
165	  int rc = fstat (mmap_next_fd, &s);
166
167	  if (rc < 0)
168	    sim_io_error (sd, "Error, unable to stat file: %s\n",
169			  strerror (errno));
170
171	  /* Autosize the mapping to the file length.  */
172	  if (nr_bytes == 0)
173	    nr_bytes = s.st_size;
174	}
175#endif
176
177      bytes = (modulo == 0 ? nr_bytes : modulo) + padding;
178
179      free_buffer = NULL;
180      free_length = bytes;
181
182#ifdef HAVE_MMAP
183      /* Memory map or malloc(). */
184      if (mmap_next_fd >= 0)
185	{
186	  /* Some kernels will SIGBUS the application if mmap'd file
187	     is not large enough.  */
188	  if (s.st_size < bytes)
189	    {
190	      sim_io_error (sd,
191			    "Error, cannot confirm that mmap file is large enough "
192			    "(>= %ld bytes)\n", bytes);
193	    }
194
195	  free_buffer = mmap (0, bytes, PROT_READ|PROT_WRITE, MAP_SHARED, mmap_next_fd, 0);
196	  if (free_buffer == 0 || free_buffer == (char*)-1) /* MAP_FAILED */
197	    {
198	      sim_io_error (sd, "Error, cannot mmap file (%s).\n",
199			    strerror(errno));
200	    }
201	}
202#endif
203
204      /* Need heap allocation? */
205      if (free_buffer == NULL)
206	{
207	  /* If filling with non-zero value, do not use clearing allocator. */
208	  if (fill_byte_flag && fill_byte_value != 0)
209	    free_buffer = xmalloc (bytes); /* don't clear */
210	  else
211	    free_buffer = zalloc (bytes); /* clear */
212	}
213
214      aligned_buffer = (char*) free_buffer + padding;
215
216      sim_core_attach (sd, NULL,
217		       level, access_read_write_exec, space,
218		       addr, nr_bytes, modulo, NULL, aligned_buffer);
219
220      fill_buffer = aligned_buffer;
221      fill_length = (modulo == 0) ? nr_bytes : modulo;
222
223      /* If we just used a clearing allocator, and are about to fill with
224         zero, truncate the redundant fill operation. */
225
226      if (fill_byte_flag && fill_byte_value == 0)
227         fill_length = 1; /* avoid boundary length=0 case */
228    }
229
230  if (fill_byte_flag)
231    {
232      ASSERT (fill_buffer != 0);
233      memset ((char*) fill_buffer, fill_byte_value, fill_length);
234    }
235
236  while ((*entry) != NULL)
237    entry = &(*entry)->next;
238  (*entry) = ZALLOC (sim_memopt);
239  (*entry)->level = level;
240  (*entry)->space = space;
241  (*entry)->addr = addr;
242  (*entry)->nr_bytes = nr_bytes;
243  (*entry)->modulo = modulo;
244  (*entry)->buffer = free_buffer;
245
246  /* Record memory unmapping info.  */
247  if (mmap_next_fd >= 0)
248    {
249      (*entry)->munmap_length = free_length;
250      close (mmap_next_fd);
251      mmap_next_fd = -1;
252    }
253  else
254    (*entry)->munmap_length = 0;
255
256  return (*entry);
257}
258
259static SIM_RC
260do_memopt_delete (SIM_DESC sd,
261		  int level,
262		  int space,
263		  address_word addr)
264{
265  sim_memopt **entry = &STATE_MEMOPT (sd);
266  sim_memopt *alias;
267  while ((*entry) != NULL
268	 && ((*entry)->level != level
269	      || (*entry)->space != space
270	      || (*entry)->addr != addr))
271    entry = &(*entry)->next;
272  if ((*entry) == NULL)
273    {
274      sim_io_eprintf (sd, "Memory at 0x%lx not found, not deleted\n",
275		      (long) addr);
276      return SIM_RC_FAIL;
277    }
278  /* delete any buffer */
279  if ((*entry)->buffer != NULL)
280    {
281#ifdef HAVE_MUNMAP
282      if ((*entry)->munmap_length > 0)
283	munmap ((*entry)->buffer, (*entry)->munmap_length);
284      else
285#endif
286	free ((*entry)->buffer);
287    }
288
289  /* delete it and its aliases */
290  alias = *entry;
291  *entry = (*entry)->next;
292  while (alias != NULL)
293    {
294      sim_memopt *dead = alias;
295      alias = alias->alias;
296      sim_core_detach (sd, NULL, dead->level, dead->space, dead->addr);
297      free (dead);
298    }
299  return SIM_RC_OK;
300}
301
302
303static char *
304parse_size (char *chp,
305	    address_word *nr_bytes,
306	    unsigned *modulo)
307{
308  /* <nr_bytes>[K|M|G] [ "%" <modulo> ] */
309  *nr_bytes = strtoul (chp, &chp, 0);
310  switch (*chp)
311    {
312    case '%':
313      *modulo = strtoul (chp + 1, &chp, 0);
314      break;
315    case 'g': case 'G': /* Gigabyte suffix.  */
316      *nr_bytes <<= 10;
317      /* Fall through.  */
318    case 'm': case 'M': /* Megabyte suffix.  */
319      *nr_bytes <<= 10;
320      /* Fall through.  */
321    case 'k': case 'K': /* Kilobyte suffix.  */
322      *nr_bytes <<= 10;
323      /* Check for a modulo specifier after the suffix.  */
324      ++ chp;
325      if (* chp == 'b' || * chp == 'B')
326	++ chp;
327      if (* chp == '%')
328	*modulo = strtoul (chp + 1, &chp, 0);
329      break;
330    }
331  return chp;
332}
333
334static char *
335parse_ulong_value (char *chp,
336		     unsigned long *value)
337{
338  *value = strtoul (chp, &chp, 0);
339  return chp;
340}
341
342static char *
343parse_addr (char *chp,
344	    int *level,
345	    int *space,
346	    address_word *addr)
347{
348  /* [ <space> ": " ] <addr> [ "@" <level> ] */
349  *addr = (unsigned long) strtoul (chp, &chp, 0);
350  if (*chp == ':')
351    {
352      *space = *addr;
353      *addr = (unsigned long) strtoul (chp + 1, &chp, 0);
354    }
355  if (*chp == '@')
356    {
357      *level = strtoul (chp + 1, &chp, 0);
358    }
359  return chp;
360}
361
362
363static SIM_RC
364memory_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt,
365		       char *arg, int is_command)
366{
367  switch (opt)
368    {
369
370    case OPTION_MEMORY_DELETE:
371      if (strcasecmp (arg, "all") == 0)
372	{
373	  while (STATE_MEMOPT (sd) != NULL)
374	    do_memopt_delete (sd,
375			      STATE_MEMOPT (sd)->level,
376			      STATE_MEMOPT (sd)->space,
377			      STATE_MEMOPT (sd)->addr);
378	  return SIM_RC_OK;
379	}
380      else
381	{
382	  int level = 0;
383	  int space = 0;
384	  address_word addr = 0;
385	  parse_addr (arg, &level, &space, &addr);
386	  return do_memopt_delete (sd, level, space, addr);
387	}
388
389    case OPTION_MEMORY_REGION:
390      {
391	char *chp = arg;
392	int level = 0;
393	int space = 0;
394	address_word addr = 0;
395	address_word nr_bytes = 0;
396	unsigned modulo = 0;
397	/* parse the arguments */
398	chp = parse_addr (chp, &level, &space, &addr);
399	if (*chp != ',')
400	  {
401	    /* let the file autosize */
402	    if (mmap_next_fd == -1)
403	      {
404		sim_io_eprintf (sd, "Missing size for memory-region\n");
405		return SIM_RC_FAIL;
406	      }
407	  }
408	else
409	  chp = parse_size (chp + 1, &nr_bytes, &modulo);
410	/* old style */
411	if (*chp == ',')
412	  modulo = strtoul (chp + 1, &chp, 0);
413	/* try to attach/insert it */
414	do_memopt_add (sd, level, space, addr, nr_bytes, modulo,
415		       &STATE_MEMOPT (sd), NULL);
416	return SIM_RC_OK;
417      }
418
419    case OPTION_MEMORY_ALIAS:
420      {
421	char *chp = arg;
422	int level = 0;
423	int space = 0;
424	address_word addr = 0;
425	address_word nr_bytes = 0;
426	unsigned modulo = 0;
427	sim_memopt *entry;
428	/* parse the arguments */
429	chp = parse_addr (chp, &level, &space, &addr);
430	if (*chp != ',')
431	  {
432	    sim_io_eprintf (sd, "Missing size for memory-region\n");
433	    return SIM_RC_FAIL;
434	  }
435	chp = parse_size (chp + 1, &nr_bytes, &modulo);
436	/* try to attach/insert the main record */
437	entry = do_memopt_add (sd, level, space, addr, nr_bytes, modulo,
438			       &STATE_MEMOPT (sd),
439			       NULL);
440	/* now attach all the aliases */
441	while (*chp == ',')
442	  {
443	    int a_level = level;
444	    int a_space = space;
445	    address_word a_addr = addr;
446	    chp = parse_addr (chp + 1, &a_level, &a_space, &a_addr);
447	    do_memopt_add (sd, a_level, a_space, a_addr, nr_bytes, modulo,
448			   &entry->alias, entry->buffer);
449	  }
450	return SIM_RC_OK;
451      }
452
453    case OPTION_MEMORY_SIZE:
454      {
455	int level = 0;
456	int space = 0;
457	address_word addr = 0;
458	address_word nr_bytes = 0;
459	unsigned modulo = 0;
460	/* parse the arguments */
461	parse_size (arg, &nr_bytes, &modulo);
462	/* try to attach/insert it */
463	do_memopt_add (sd, level, space, addr, nr_bytes, modulo,
464		       &STATE_MEMOPT (sd), NULL);
465	return SIM_RC_OK;
466      }
467
468    case OPTION_MEMORY_CLEAR:
469      {
470	fill_byte_value = (unsigned8) 0;
471	fill_byte_flag = 1;
472	return SIM_RC_OK;
473	break;
474      }
475
476    case OPTION_MEMORY_FILL:
477      {
478	unsigned long fill_value;
479	parse_ulong_value (arg, &fill_value);
480	if (fill_value > 255)
481	  {
482	    sim_io_eprintf (sd, "Missing fill value between 0 and 255\n");
483	    return SIM_RC_FAIL;
484	  }
485	fill_byte_value = (unsigned8) fill_value;
486	fill_byte_flag = 1;
487	return SIM_RC_OK;
488	break;
489      }
490
491    case OPTION_MEMORY_MAPFILE:
492      {
493	if (mmap_next_fd >= 0)
494	  {
495	    sim_io_eprintf (sd, "Duplicate memory-mapfile option\n");
496	    return SIM_RC_FAIL;
497	  }
498
499	mmap_next_fd = open (arg, O_RDWR);
500	if (mmap_next_fd < 0)
501	  {
502	    sim_io_eprintf (sd, "Cannot open file `%s': %s\n",
503			    arg, strerror(errno));
504	    return SIM_RC_FAIL;
505	  }
506
507	return SIM_RC_OK;
508      }
509
510    case OPTION_MEMORY_INFO:
511      {
512	sim_memopt *entry;
513	sim_io_printf (sd, "Memory maps:\n");
514	for (entry = STATE_MEMOPT (sd); entry != NULL; entry = entry->next)
515	  {
516	    sim_memopt *alias;
517	    sim_io_printf (sd, " memory");
518	    if (entry->alias == NULL)
519	      sim_io_printf (sd, " region ");
520	    else
521	      sim_io_printf (sd, " alias ");
522	    if (entry->space != 0)
523	      sim_io_printf (sd, "0x%lx:", (long) entry->space);
524	    sim_io_printf (sd, "0x%08lx", (long) entry->addr);
525	    if (entry->level != 0)
526	      sim_io_printf (sd, "@0x%lx", (long) entry->level);
527	    sim_io_printf (sd, ",0x%lx",
528			   (long) entry->nr_bytes);
529	    if (entry->modulo != 0)
530	      sim_io_printf (sd, "%%0x%lx", (long) entry->modulo);
531	    for (alias = entry->alias;
532		 alias != NULL;
533		 alias = alias->next)
534	      {
535		if (alias->space != 0)
536		  sim_io_printf (sd, "0x%lx:", (long) alias->space);
537		sim_io_printf (sd, ",0x%08lx", (long) alias->addr);
538		if (alias->level != 0)
539		  sim_io_printf (sd, "@0x%lx", (long) alias->level);
540	      }
541	    sim_io_printf (sd, "\n");
542	  }
543	return SIM_RC_OK;
544	break;
545      }
546
547    case OPTION_MAP_INFO:
548      {
549	sim_core *memory = STATE_CORE (sd);
550	unsigned nr_map;
551
552	for (nr_map = 0; nr_map < nr_maps; ++nr_map)
553	  {
554	    sim_core_map *map = &memory->common.map[nr_map];
555	    sim_core_mapping *mapping = map->first;
556
557	    if (!mapping)
558	      continue;
559
560	    sim_io_printf (sd, "%s maps:\n", map_to_str (nr_map));
561	    do
562	      {
563		unsigned modulo;
564
565		sim_io_printf (sd, " map ");
566		if (mapping->space != 0)
567		  sim_io_printf (sd, "0x%x:", mapping->space);
568		sim_io_printf (sd, "0x%08lx", (long) mapping->base);
569		if (mapping->level != 0)
570		  sim_io_printf (sd, "@0x%x", mapping->level);
571		sim_io_printf (sd, ",0x%lx", (long) mapping->nr_bytes);
572		modulo = mapping->mask + 1;
573		if (modulo != 0)
574		  sim_io_printf (sd, "%%0x%x", modulo);
575		sim_io_printf (sd, "\n");
576
577		mapping = mapping->next;
578	      }
579	    while (mapping);
580	  }
581
582	return SIM_RC_OK;
583	break;
584      }
585
586    default:
587      sim_io_eprintf (sd, "Unknown memory option %d\n", opt);
588      return SIM_RC_FAIL;
589
590    }
591
592  return SIM_RC_FAIL;
593}
594
595
596/* "memory" module install handler.
597
598   This is called via sim_module_install to install the "memory" subsystem
599   into the simulator.  */
600
601static MODULE_INIT_FN sim_memory_init;
602static MODULE_UNINSTALL_FN sim_memory_uninstall;
603
604SIM_RC
605sim_memopt_install (SIM_DESC sd)
606{
607  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
608  sim_add_option_table (sd, NULL, memory_options);
609  sim_module_add_uninstall_fn (sd, sim_memory_uninstall);
610  sim_module_add_init_fn (sd, sim_memory_init);
611  return SIM_RC_OK;
612}
613
614
615/* Uninstall the "memory" subsystem from the simulator.  */
616
617static void
618sim_memory_uninstall (SIM_DESC sd)
619{
620  sim_memopt **entry = &STATE_MEMOPT (sd);
621  sim_memopt *alias;
622
623  while ((*entry) != NULL)
624    {
625      /* delete any buffer */
626      if ((*entry)->buffer != NULL)
627	{
628#ifdef HAVE_MUNMAP
629	  if ((*entry)->munmap_length > 0)
630	    munmap ((*entry)->buffer, (*entry)->munmap_length);
631	  else
632#endif
633	    free ((*entry)->buffer);
634	}
635
636      /* delete it and its aliases */
637      alias = *entry;
638
639      /* next victim */
640      *entry = (*entry)->next;
641
642      while (alias != NULL)
643	{
644	  sim_memopt *dead = alias;
645	  alias = alias->alias;
646	  sim_core_detach (sd, NULL, dead->level, dead->space, dead->addr);
647	  free (dead);
648	}
649    }
650}
651
652
653static SIM_RC
654sim_memory_init (SIM_DESC sd)
655{
656  /* Reinitialize option modifier flags, in case they were left
657     over from a previous sim startup event.  */
658  fill_byte_flag = 0;
659  mmap_next_fd = -1;
660
661  return SIM_RC_OK;
662}
663