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