⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sim-memopt.c

📁 这个是LINUX下的GDB调度工具的源码
💻 C
字号:
/* Simulator memory option handling.   Copyright (C) 1996-1999 Free Software Foundation, Inc.   Contributed by Cygnus Support.This file is part of GDB, the GNU debugger.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public License alongwith this program; if not, write to the Free Software Foundation, Inc.,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */#include "cconfig.h"#include "sim-main.h"#include "sim-assert.h"#include "sim-options.h"#ifdef HAVE_STRING_H#include <string.h>#else#ifdef HAVE_STRINGS_H#include <strings.h>#endif#endif#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef HAVE_ERRNO_H#include <errno.h>#endif#ifdef HAVE_FCNTL_H#include <fcntl.h>#endif#ifdef HAVE_SYS_MMAN_H#include <sys/mman.h>#endif#ifdef HAVE_SYS_STAT_H#include <sys/stat.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif/* Memory fill byte. */static unsigned8 fill_byte_value;static int fill_byte_flag = 0;/* Memory mapping; see OPTION_MEMORY_MAPFILE. */static int mmap_next_fd = -1;/* Memory command line options. */enum {  OPTION_MEMORY_DELETE = OPTION_START,  OPTION_MEMORY_REGION,  OPTION_MEMORY_SIZE,  OPTION_MEMORY_INFO,  OPTION_MEMORY_ALIAS,  OPTION_MEMORY_CLEAR,  OPTION_MEMORY_FILL,  OPTION_MEMORY_MAPFILE};static DECLARE_OPTION_HANDLER (memory_option_handler);static const OPTION memory_options[] ={  { {"memory-delete", required_argument, NULL, OPTION_MEMORY_DELETE },      '\0', "ADDRESS|all", "Delete memory at ADDRESS (all addresses)",      memory_option_handler },  { {"delete-memory", required_argument, NULL, OPTION_MEMORY_DELETE },      '\0', "ADDRESS", NULL,      memory_option_handler },  { {"memory-region", required_argument, NULL, OPTION_MEMORY_REGION },      '\0', "ADDRESS,SIZE[,MODULO]", "Add a memory region",      memory_option_handler },  { {"memory-alias", required_argument, NULL, OPTION_MEMORY_ALIAS },      '\0', "ADDRESS,SIZE{,ADDRESS}", "Add memory shadow",      memory_option_handler },  { {"memory-size", required_argument, NULL, OPTION_MEMORY_SIZE },      '\0', "SIZE", "Add memory at address zero",      memory_option_handler },  { {"memory-fill", required_argument, NULL, OPTION_MEMORY_FILL },      '\0', "VALUE", "Fill subsequently added memory regions",      memory_option_handler },  { {"memory-clear", no_argument, NULL, OPTION_MEMORY_CLEAR },      '\0', NULL, "Clear subsequently added memory regions",      memory_option_handler },#if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)  { {"memory-mapfile", required_argument, NULL, OPTION_MEMORY_MAPFILE },      '\0', "FILE", "Memory-map next memory region from file",      memory_option_handler },#endif  { {"memory-info", no_argument, NULL, OPTION_MEMORY_INFO },      '\0', NULL, "List configurable memory regions",      memory_option_handler },  { {"info-memory", no_argument, NULL, OPTION_MEMORY_INFO },      '\0', NULL, NULL,      memory_option_handler },  { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }};static sim_memopt *do_memopt_add (SIM_DESC sd,	       int level,	       int space,	       address_word addr,	       address_word nr_bytes,	       unsigned modulo,	       sim_memopt **entry,	       void *buffer){  void *fill_buffer;  unsigned fill_length;  void *free_buffer;  unsigned long free_length;  if (buffer != NULL)    {      /* Buffer already given.  sim_memory_uninstall will free it. */      sim_core_attach (sd, NULL,		       level, access_read_write_exec, space,		       addr, nr_bytes, modulo, NULL, buffer);      free_buffer = buffer;      free_length = 0;      fill_buffer = buffer;      fill_length = (modulo == 0) ? nr_bytes : modulo;    }  else    {      /* Allocate new well-aligned buffer, just as sim_core_attach(). */      void *aligned_buffer;      int padding = (addr % sizeof (unsigned64));      unsigned long bytes = (modulo == 0 ? nr_bytes : modulo) + padding;      free_buffer = NULL;      free_length = bytes;#ifdef HAVE_MMAP      /* Memory map or malloc(). */      if (mmap_next_fd >= 0)	{	  /* Check that given file is big enough. */	  struct stat s;	  int rc;	  /* Some kernels will SIGBUS the application if mmap'd file	     is not large enough.  */ 	  rc = fstat (mmap_next_fd, &s);	  if (rc < 0 || s.st_size < bytes)	    {	      sim_io_error (sd,			    "Error, cannot confirm that mmap file is large enough "			    "(>= %ld bytes)\n", bytes);	    }	  free_buffer = mmap (0, bytes, PROT_READ|PROT_WRITE, MAP_SHARED, mmap_next_fd, 0);	  if (free_buffer == 0 || free_buffer == (char*)-1) /* MAP_FAILED */	    {	      sim_io_error (sd, "Error, cannot mmap file (%s).\n",			    strerror(errno));	    }	}#endif       /* Need heap allocation? */       if (free_buffer == NULL)	{	  /* If filling with non-zero value, do not use clearing allocator. */	  if (fill_byte_flag && fill_byte_value != 0)	    free_buffer = xmalloc (bytes); /* don't clear */	  else	    free_buffer = zalloc (bytes); /* clear */	}      aligned_buffer = (char*) free_buffer + padding;      sim_core_attach (sd, NULL,		       level, access_read_write_exec, space,		       addr, nr_bytes, modulo, NULL, aligned_buffer);      fill_buffer = aligned_buffer;      fill_length = (modulo == 0) ? nr_bytes : modulo;      /* If we just used a clearing allocator, and are about to fill with         zero, truncate the redundant fill operation. */      if (fill_byte_flag && fill_byte_value == 0)         fill_length = 1; /* avoid boundary length=0 case */    }  if (fill_byte_flag)    {      ASSERT (fill_buffer != 0);      memset ((char*) fill_buffer, fill_byte_value, fill_length);    }  while ((*entry) != NULL)    entry = &(*entry)->next;  (*entry) = ZALLOC (sim_memopt);  (*entry)->level = level;  (*entry)->space = space;  (*entry)->addr = addr;  (*entry)->nr_bytes = nr_bytes;  (*entry)->modulo = modulo;  (*entry)->buffer = free_buffer;  /* Record memory unmapping info.  */  if (mmap_next_fd >= 0)    {      (*entry)->munmap_length = free_length;      close (mmap_next_fd);      mmap_next_fd = -1;    }  else    (*entry)->munmap_length = 0;  return (*entry);}static SIM_RCdo_memopt_delete (SIM_DESC sd,		  int level,		  int space,		  address_word addr){  sim_memopt **entry = &STATE_MEMOPT (sd);  sim_memopt *alias;  while ((*entry) != NULL	 && ((*entry)->level != level	      || (*entry)->space != space	      || (*entry)->addr != addr))    entry = &(*entry)->next;  if ((*entry) == NULL)    {      sim_io_eprintf (sd, "Memory at 0x%lx not found, not deleted\n",		      (long) addr);      return SIM_RC_FAIL;    }  /* delete any buffer */  if ((*entry)->buffer != NULL)    {#ifdef HAVE_MUNMAP      if ((*entry)->munmap_length > 0)	munmap ((*entry)->buffer, (*entry)->munmap_length);      else#endif	zfree ((*entry)->buffer);    }  /* delete it and its aliases */  alias = *entry;  *entry = (*entry)->next;  while (alias != NULL)    {      sim_memopt *dead = alias;      alias = alias->alias;      sim_core_detach (sd, NULL, dead->level, dead->space, dead->addr);      zfree (dead);    }  return SIM_RC_OK;}static char *parse_size (char *chp,	    address_word *nr_bytes,	    unsigned *modulo){  /* <nr_bytes> [ "%" <modulo> ] */  *nr_bytes = strtoul (chp, &chp, 0);  if (*chp == '%')    {      *modulo = strtoul (chp + 1, &chp, 0);    }  return chp;}static char *parse_ulong_value (char *chp,		     unsigned long *value){  *value = strtoul (chp, &chp, 0);  return chp;}static char *parse_addr (char *chp,	    int *level,	    int *space,	    address_word *addr){  /* [ <space> ": " ] <addr> [ "@" <level> ] */  *addr = (unsigned long) strtoul (chp, &chp, 0);  if (*chp == ':')    {      *space = *addr;      *addr = (unsigned long) strtoul (chp + 1, &chp, 0);    }  if (*chp == '@')    {      *level = strtoul (chp + 1, &chp, 0);    }  return chp;}static SIM_RCmemory_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt,		       char *arg, int is_command){  switch (opt)    {    case OPTION_MEMORY_DELETE:      if (strcasecmp (arg, "all") == 0)	{	  while (STATE_MEMOPT (sd) != NULL)	    do_memopt_delete (sd,			      STATE_MEMOPT (sd)->level,			      STATE_MEMOPT (sd)->space,			      STATE_MEMOPT (sd)->addr);	  return SIM_RC_OK;	}      else	{	  int level = 0;	  int space = 0;	  address_word addr = 0;	  parse_addr (arg, &level, &space, &addr);	  return do_memopt_delete (sd, level, space, addr);	}        case OPTION_MEMORY_REGION:      {	char *chp = arg;	int level = 0;	int space = 0;	address_word addr = 0;	address_word nr_bytes = 0;	unsigned modulo = 0;	/* parse the arguments */	chp = parse_addr (chp, &level, &space, &addr);	if (*chp != ',')	  {	    sim_io_eprintf (sd, "Missing size for memory-region\n");	    return SIM_RC_FAIL;	  }	chp = parse_size (chp + 1, &nr_bytes, &modulo);	/* old style */	if (*chp == ',')	  modulo = strtoul (chp + 1, &chp, 0);	/* try to attach/insert it */	do_memopt_add (sd, level, space, addr, nr_bytes, modulo,		       &STATE_MEMOPT (sd), NULL);	return SIM_RC_OK;      }    case OPTION_MEMORY_ALIAS:      {	char *chp = arg;	int level = 0;	int space = 0;	address_word addr = 0;	address_word nr_bytes = 0;	unsigned modulo = 0;	sim_memopt *entry;	/* parse the arguments */	chp = parse_addr (chp, &level, &space, &addr);	if (*chp != ',')	  {	    sim_io_eprintf (sd, "Missing size for memory-region\n");	    return SIM_RC_FAIL;	  }	chp = parse_size (chp + 1, &nr_bytes, &modulo);	/* try to attach/insert the main record */	entry = do_memopt_add (sd, level, space, addr, nr_bytes, modulo,			       &STATE_MEMOPT (sd),			       NULL);	/* now attach all the aliases */	while (*chp == ',')	  {	    int a_level = level;	    int a_space = space;	    address_word a_addr = addr;	    chp = parse_addr (chp + 1, &a_level, &a_space, &a_addr);	    do_memopt_add (sd, a_level, a_space, a_addr, nr_bytes, modulo,			   &entry->alias, entry->buffer);	  }	return SIM_RC_OK;      }    case OPTION_MEMORY_SIZE:      {	int level = 0;	int space = 0;	address_word addr = 0;	address_word nr_bytes = 0;	unsigned modulo = 0;	/* parse the arguments */	parse_size (arg, &nr_bytes, &modulo);	/* try to attach/insert it */	do_memopt_add (sd, level, space, addr, nr_bytes, modulo,		       &STATE_MEMOPT (sd), NULL);	return SIM_RC_OK;      }    case OPTION_MEMORY_CLEAR:      {	fill_byte_value = (unsigned8) 0;	fill_byte_flag = 1;	return SIM_RC_OK;	break;      }    case OPTION_MEMORY_FILL:      {	unsigned long fill_value;	parse_ulong_value (arg, &fill_value);	if (fill_value > 255)	  {	    sim_io_eprintf (sd, "Missing fill value between 0 and 255\n");	    return SIM_RC_FAIL;	  }	fill_byte_value = (unsigned8) fill_value;	fill_byte_flag = 1;	return SIM_RC_OK;	break;      }    case OPTION_MEMORY_MAPFILE:      {	if (mmap_next_fd >= 0)	  {	    sim_io_eprintf (sd, "Duplicate memory-mapfile option\n");	    return SIM_RC_FAIL;	  }	mmap_next_fd = open (arg, O_RDWR);	if (mmap_next_fd < 0)	  {	    sim_io_eprintf (sd, "Cannot open file `%s': %s\n",			    arg, strerror(errno));	    return SIM_RC_FAIL;	  }	return SIM_RC_OK;      }    case OPTION_MEMORY_INFO:      {	sim_memopt *entry;	sim_io_printf (sd, "Memory maps:\n");	for (entry = STATE_MEMOPT (sd); entry != NULL; entry = entry->next)	  {	    sim_memopt *alias;	    sim_io_printf (sd, " memory");	    if (entry->alias == NULL)	      sim_io_printf (sd, " region ");	    else	      sim_io_printf (sd, " alias ");	    if (entry->space != 0)	      sim_io_printf (sd, "0x%lx:", (long) entry->space);	    sim_io_printf (sd, "0x%08lx", (long) entry->addr);	    if (entry->level != 0)	      sim_io_printf (sd, "@0x%lx", (long) entry->level);	    sim_io_printf (sd, ",0x%lx",			   (long) entry->nr_bytes);	    if (entry->modulo != 0)	      sim_io_printf (sd, "%%0x%lx", (long) entry->modulo);	    for (alias = entry->alias;		 alias != NULL;		 alias = alias->next)	      {		if (alias->space != 0)		  sim_io_printf (sd, "0x%lx:", (long) alias->space);		sim_io_printf (sd, ",0x%08lx", (long) alias->addr);		if (alias->level != 0)		  sim_io_printf (sd, "@0x%lx", (long) alias->level);	      }	    sim_io_printf (sd, "\n");	  }	return SIM_RC_OK;	break;      }    default:      sim_io_eprintf (sd, "Unknown memory option %d\n", opt);      return SIM_RC_FAIL;    }  return SIM_RC_FAIL;}/* "memory" module install handler.   This is called via sim_module_install to install the "memory" subsystem   into the simulator.  */static MODULE_INIT_FN sim_memory_init;static MODULE_UNINSTALL_FN sim_memory_uninstall;SIM_RCsim_memopt_install (SIM_DESC sd){  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);  sim_add_option_table (sd, NULL, memory_options);  sim_module_add_uninstall_fn (sd, sim_memory_uninstall);  sim_module_add_init_fn (sd, sim_memory_init);  return SIM_RC_OK;}/* Uninstall the "memory" subsystem from the simulator.  */static voidsim_memory_uninstall (SIM_DESC sd){  sim_memopt **entry = &STATE_MEMOPT (sd);  sim_memopt *alias;  while ((*entry) != NULL)    {      /* delete any buffer */      if ((*entry)->buffer != NULL)	{#ifdef HAVE_MUNMAP	  if ((*entry)->munmap_length > 0)	    munmap ((*entry)->buffer, (*entry)->munmap_length);	  else#endif	    zfree ((*entry)->buffer);	}      /* delete it and its aliases */      alias = *entry;      /* next victim */      *entry = (*entry)->next;      while (alias != NULL)	{	  sim_memopt *dead = alias;	  alias = alias->alias;	  sim_core_detach (sd, NULL, dead->level, dead->space, dead->addr);	  zfree (dead);	}    }}static SIM_RCsim_memory_init (SIM_DESC sd){  /* Reinitialize option modifier flags, in case they were left     over from a previous sim startup event.  */  fill_byte_flag = 0;  mmap_next_fd = -1;  return SIM_RC_OK;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -