struct vmap *map_vmap PARAMS ((bfd *, bfd *));    static void add_to_section_table PARAMS ((bfd *, sec_ptr, PTR));  static void exec_close PARAMS ((int));  static void file_command PARAMS ((char *, int));  static void set_section_command PARAMS ((char *, int));  static void exec_files_info PARAMS ((struct target_ops *));  static void bfdsec_to_vmap PARAMS ((bfd *, sec_ptr, PTR));  static int ignore PARAMS ((CORE_ADDR, char *));  extern int info_verbose;    bfd *exec_bfd = NULL;    int write_files = 0;    #ifdef NEED_TEXT_START_END CORE_ADDR text_start = 0; CORE_ADDR text_end   = 0; #endif  struct vmap *vmap;    extern struct target_ops exec_ops;   static void exec_close (quitting) int quitting; { int need_symtab_cleanup = 0; struct vmap *vp, *nxt;  for (nxt = vmap; nxt != NULL; ) { vp = nxt; nxt = vp->nxt;    if (vp->objfile) { free_objfile (vp->objfile); need_symtab_cleanup = 1; } else if (vp->bfd != exec_bfd)  if (!bfd_close (vp->bfd)) warning ("cannot close \"%s\": %s", vp->name, bfd_errmsg (bfd_get_error ()));   free_named_symtabs (vp->name); free (vp); }  vmap = NULL;  if (exec_bfd) { char *name = bfd_get_filename (exec_bfd);  if (!bfd_close (exec_bfd)) warning ("cannot close \"%s\": %s", name, bfd_errmsg (bfd_get_error ())); free (name); exec_bfd = NULL; }  if (exec_ops.to_sections) { free ((PTR)exec_ops.to_sections); exec_ops.to_sections = NULL; exec_ops.to_sections_end = NULL; } }    void exec_file_command (args, from_tty) char *args; int from_tty; { char **argv; char *filename;  target_preopen (from_tty);   unpush_target (&exec_ops);    if (args) { char *scratch_pathname; int scratch_chan;    argv = buildargv (args); if (argv == NULL) nomem (0);  make_cleanup (freeargv, (char *) argv);  for (; (*argv != NULL) && (**argv == '-'); argv++) {;} if (*argv == NULL) error ("no exec file name was specified");  filename = tilde_expand (*argv); make_cleanup (free, filename);  scratch_chan = openp (getenv ("PATH"), 1, filename, write_files? O_RDWR|O_BINARY: O_RDONLY|O_BINARY, 0, &scratch_pathname); #if defined(__GO32__) || defined(_WIN32) if (scratch_chan < 0) { char *exename = alloca (strlen (filename) + 5); strcat (strcpy (exename, filename), ".exe"); scratch_chan = openp (getenv ("PATH"), 1, exename, write_files ? O_RDWR|O_BINARY : O_RDONLY|O_BINARY, 0, &scratch_pathname); } #endif if (scratch_chan < 0) perror_with_name (filename); exec_bfd = bfd_fdopenr (scratch_pathname, gnutarget, scratch_chan);  if (!exec_bfd) error ("\"%s\": could not open as an executable file: %s", scratch_pathname, bfd_errmsg (bfd_get_error ()));   scratch_pathname = strdup (scratch_pathname); make_cleanup (free, scratch_pathname);  if (!bfd_check_format (exec_bfd, bfd_object)) {  exec_close (0); error ("\"%s\": not in executable format: %s", scratch_pathname, bfd_errmsg (bfd_get_error ())); }   #ifdef IBM6000_TARGET   map_vmap (exec_bfd, 0); if (vmap == NULL) {  exec_close (0); error ("\"%s\": can't find the file sections: %s", scratch_pathname, bfd_errmsg (bfd_get_error ())); } #endif   if (build_section_table (exec_bfd, &exec_ops.to_sections, &exec_ops.to_sections_end)) {  exec_close (0); error ("\"%s\": can't find the file sections: %s", scratch_pathname, bfd_errmsg (bfd_get_error ())); }  #ifdef NEED_TEXT_START_END    { struct section_table *p;     text_start = ~(CORE_ADDR)0; text_end = (CORE_ADDR)0; for (p = exec_ops.to_sections; p < exec_ops.to_sections_end; p++) if (bfd_get_section_flags (p->bfd, p->the_bfd_section) & (SEC_CODE | SEC_READONLY)) { if (text_start > p->addr) text_start = p->addr; if (text_end < p->endaddr) text_end = p->endaddr; } } #endif  validate_files ();  set_endian_from_file (exec_bfd);  push_target (&exec_ops);   if (exec_file_display_hook) (*exec_file_display_hook) (filename); } else if (from_tty) printf_unfiltered ("No exec file now.\n"); }    static void file_command (arg, from_tty) char *arg; int from_tty; {  exec_file_command (arg, from_tty); symbol_file_command (arg, from_tty); }      static void add_to_section_table (abfd, asect, table_pp_char) bfd *abfd; sec_ptr asect; PTR table_pp_char; { struct section_table **table_pp = (struct section_table **)table_pp_char; flagword aflag;  aflag = bfd_get_section_flags (abfd, asect); if (!(aflag & SEC_ALLOC)) return; if (0 == bfd_section_size (abfd, asect)) return; (*table_pp)->bfd = abfd; (*table_pp)->the_bfd_section = asect; (*table_pp)->addr = bfd_section_vma (abfd, asect); (*table_pp)->endaddr = (*table_pp)->addr + bfd_section_size (abfd, asect); (*table_pp)++; }    int build_section_table (some_bfd, start, end) bfd *some_bfd; struct section_table **start, **end; { unsigned count;  count = bfd_count_sections (some_bfd); if (*start) free ((PTR)*start); *start = (struct section_table *) xmalloc (count * sizeof (**start)); *end = *start; bfd_map_over_sections (some_bfd, add_to_section_table, (char *)end); if (*end > *start + count) abort();  return 0; }   static void bfdsec_to_vmap(abfd, sect, arg3) bfd *abfd; sec_ptr sect; PTR arg3; { struct vmap_and_bfd *vmap_bfd = (struct vmap_and_bfd *) arg3; struct vmap *vp;  vp = vmap_bfd->pvmap;  if ((bfd_get_section_flags (abfd, sect) & SEC_LOAD) == 0) return;  if (STREQ (bfd_section_name (abfd, sect), ".text")) { vp->tstart = 0; vp->tend = vp->tstart + bfd_section_size (abfd, sect);    vp->tadj = sect->filepos - bfd_section_vma (abfd, sect); } else if (STREQ (bfd_section_name (abfd, sect), ".data")) { vp->dstart = 0; vp->dend = vp->dstart + bfd_section_size (abfd, sect); }  }    struct vmap * map_vmap (abfd, arch) bfd *abfd; bfd *arch;
map_vmap (bfd *abfd, bfd *arch)
struct vmap *map_vmap PARAMS ((bfd *, bfd *));/* Prototypes for local functions */static void add_to_section_table PARAMS ((bfd *, sec_ptr, PTR));static void exec_close PARAMS ((int));static void file_command PARAMS ((char *, int));static void set_section_command PARAMS ((char *, int));static void exec_files_info PARAMS ((struct target_ops *));static void bfdsec_to_vmap PARAMS ((bfd *, sec_ptr, PTR));static int ignore PARAMS ((CORE_ADDR, char *));extern int info_verbose;/* The Binary File Descriptor handle for the executable file.  */bfd *exec_bfd = NULL;/* Whether to open exec and core files read-only or read-write.  */int write_files = 0;/* Text start and end addresses (KLUDGE) if needed */#ifdef NEED_TEXT_START_ENDCORE_ADDR text_start = 0;CORE_ADDR text_end   = 0;#endifstruct vmap *vmap;/* Forward decl */extern struct target_ops exec_ops;/* ARGSUSED */static voidexec_close (quitting)     int quitting;{  int need_symtab_cleanup = 0;  struct vmap *vp, *nxt;    for (nxt = vmap; nxt != NULL; )    {      vp = nxt;      nxt = vp->nxt;      /* if there is an objfile associated with this bfd,	 free_objfile() will do proper cleanup of objfile *and* bfd. */		         if (vp->objfile)	{	  free_objfile (vp->objfile);	  need_symtab_cleanup = 1;	}      else if (vp->bfd != exec_bfd)	/* FIXME-leak: We should be freeing vp->name too, I think.  */	if (!bfd_close (vp->bfd))	  warning ("cannot close \"%s\": %s",		   vp->name, bfd_errmsg (bfd_get_error ()));      /* FIXME: This routine is #if 0'd in symfile.c.  What should we	 be doing here?  Should we just free everything in	 vp->objfile->symtabs?  Should free_objfile do that?	 FIXME-as-well: free_objfile already free'd vp->name, so it isn't	 valid here.  */      free_named_symtabs (vp->name);      free (vp);    }  vmap = NULL;  if (exec_bfd)    {      char *name = bfd_get_filename (exec_bfd);      if (!bfd_close (exec_bfd))	warning ("cannot close \"%s\": %s",		 name, bfd_errmsg (bfd_get_error ()));      free (name);      exec_bfd = NULL;    }  if (exec_ops.to_sections)    {      free ((PTR)exec_ops.to_sections);      exec_ops.to_sections = NULL;      exec_ops.to_sections_end = NULL;    }}/*  Process the first arg in ARGS as the new exec file.    Note that we have to explicitly ignore additional args, since we can    be called from file_command(), which also calls symbol_file_command()    which can take multiple args. */voidexec_file_command (args, from_tty)     char *args;     int from_tty;{  char **argv;  char *filename;  target_preopen (from_tty);  /* Remove any previous exec file.  */  unpush_target (&exec_ops);  /* Now open and digest the file the user requested, if any.  */  if (args)    {      char *scratch_pathname;      int scratch_chan;            /* Scan through the args and pick up the first non option arg	 as the filename.  */      argv = buildargv (args);      if (argv == NULL)	nomem (0);      make_cleanup (freeargv, (char *) argv);      for (; (*argv != NULL) && (**argv == '-'); argv++) {;}      if (*argv == NULL)	error ("no exec file name was specified");      filename = tilde_expand (*argv);      make_cleanup (free, filename);            scratch_chan = openp (getenv ("PATH"), 1, filename, 			    write_files? O_RDWR|O_BINARY: O_RDONLY|O_BINARY, 0,			    &scratch_pathname);#if defined(__GO32__) || defined(_WIN32)      if (scratch_chan < 0)      {	char *exename = alloca (strlen (filename) + 5);	strcat (strcpy (exename, filename), ".exe");	scratch_chan = openp (getenv ("PATH"), 1, exename, write_files ?		O_RDWR|O_BINARY : O_RDONLY|O_BINARY, 0, &scratch_pathname);      }#endif      if (scratch_chan < 0)	perror_with_name (filename);      exec_bfd = bfd_fdopenr (scratch_pathname, gnutarget, scratch_chan);      if (!exec_bfd)	error ("\"%s\": could not open as an executable file: %s",	       scratch_pathname, bfd_errmsg (bfd_get_error ()));      /* At this point, scratch_pathname and exec_bfd->name both point to the	 same malloc'd string.  However exec_close() will attempt to free it	 via the exec_bfd->name pointer, so we need to make another copy and	 leave exec_bfd as the new owner of the original copy. */      scratch_pathname = strdup (scratch_pathname);      make_cleanup (free, scratch_pathname);            if (!bfd_check_format (exec_bfd, bfd_object))	{	  /* Make sure to close exec_bfd, or else "run" might try to use	     it.  */	  exec_close (0);	  error ("\"%s\": not in executable format: %s",		 scratch_pathname, bfd_errmsg (bfd_get_error ()));	}      /* FIXME - This should only be run for RS6000, but the ifdef is a poor	 way to accomplish.  */#ifdef IBM6000_TARGET      /* Setup initial vmap. */      map_vmap (exec_bfd, 0);      if (vmap == NULL)	{	  /* Make sure to close exec_bfd, or else "run" might try to use	     it.  */	  exec_close (0);	  error ("\"%s\": can't find the file sections: %s",		 scratch_pathname, bfd_errmsg (bfd_get_error ()));	}#endif /* IBM6000_TARGET */      if (build_section_table (exec_bfd, &exec_ops.to_sections,				&exec_ops.to_sections_end))	{	  /* Make sure to close exec_bfd, or else "run" might try to use	     it.  */	  exec_close (0);	  error ("\"%s\": can't find the file sections: %s", 		 scratch_pathname, bfd_errmsg (bfd_get_error ()));	}#ifdef NEED_TEXT_START_END      /* text_end is sometimes used for where to put call dummies.  A	 few ports use these for other purposes too.  */      {	struct section_table *p;	/* Set text_start to the lowest address of the start of any	   readonly code section and set text_end to the highest	   address of the end of any readonly code section.  */	/* FIXME: The comment above does not match the code.  The code	   checks for sections with are either code *or* readonly.  */	text_start = ~(CORE_ADDR)0;	text_end = (CORE_ADDR)0;	for (p = exec_ops.to_sections; p < exec_ops.to_sections_end; p++)	  if (bfd_get_section_flags (p->bfd, p->the_bfd_section)	      & (SEC_CODE | SEC_READONLY))	    {	      if (text_start > p->addr) 		text_start = p->addr;	      if (text_end < p->endaddr)		text_end = p->endaddr;	    }      }#endif      validate_files ();      set_endian_from_file (exec_bfd);      push_target (&exec_ops);      /* Tell display code (if any) about the changed file name.  */      if (exec_file_display_hook)	(*exec_file_display_hook) (filename);    }  else if (from_tty)    printf_unfiltered ("No exec file now.\n");}/* Set both the exec file and the symbol file, in one command.     What a novelty.  Why did GDB go through four major releases before this   command was added?  */static voidfile_command (arg, from_tty)     char *arg;     int from_tty;{  /* FIXME, if we lose on reading the symbol file, we should revert     the exec file, but that's rough.  */  exec_file_command (arg, from_tty);  symbol_file_command (arg, from_tty);}/* Locate all mappable sections of a BFD file.    table_pp_char is a char * to get it through bfd_map_over_sections;   we cast it back to its proper type.  */static voidadd_to_section_table (abfd, asect, table_pp_char)     bfd *abfd;     sec_ptr asect;     PTR table_pp_char;{  struct section_table **table_pp = (struct section_table **)table_pp_char;  flagword aflag;  aflag = bfd_get_section_flags (abfd, asect);  if (!(aflag & SEC_ALLOC))    return;  if (0 == bfd_section_size (abfd, asect))    return;  (*table_pp)->bfd = abfd;  (*table_pp)->the_bfd_section = asect;  (*table_pp)->addr = bfd_section_vma (abfd, asect);  (*table_pp)->endaddr = (*table_pp)->addr + bfd_section_size (abfd, asect);  (*table_pp)++;}/* Builds a section table, given args BFD, SECTABLE_PTR, SECEND_PTR.   Returns 0 if OK, 1 on error.  */intbuild_section_table (some_bfd, start, end)     bfd *some_bfd;     struct section_table **start, **end;{  unsigned count;  count = bfd_count_sections (some_bfd);  if (*start)    free ((PTR)*start);  *start = (struct section_table *) xmalloc (count * sizeof (**start));  *end = *start;  bfd_map_over_sections (some_bfd, add_to_section_table, (char *)end);  if (*end > *start + count)    abort();  /* We could realloc the table, but it probably loses for most files.  */  return 0;}static voidbfdsec_to_vmap(abfd, sect, arg3)      bfd *abfd;     sec_ptr sect;     PTR arg3;{  struct vmap_and_bfd *vmap_bfd = (struct vmap_and_bfd *) arg3;  struct vmap *vp;  vp = vmap_bfd->pvmap;  if ((bfd_get_section_flags (abfd, sect) & SEC_LOAD) == 0)    return;  if (STREQ (bfd_section_name (abfd, sect), ".text"))    {      vp->tstart = 0;      vp->tend = vp->tstart + bfd_section_size (abfd, sect);      /* When it comes to this adjustment value, in contrast to our previous	 belief shared objects should behave the same as the main load segment.	 This is the offset from the beginning of text section to the first	 real instruction. */      vp->tadj = sect->filepos - bfd_section_vma (abfd, sect);    }  else if (STREQ (bfd_section_name (abfd, sect), ".data"))    {      vp->dstart = 0;      vp->dend = vp->dstart + bfd_section_size (abfd, sect);    }  /* Silently ignore other types of sections. (FIXME?)  */}/* Make a vmap for ABFD which might be a member of the archive ARCH.   Return the new vmap.  */struct vmap *map_vmap (abfd, arch)     bfd *abfd;     bfd *arch;{  struct vmap_and_bfd vmap_bfd;  struct vmap *vp, **vpp;  vp = (struct vmap *) xmalloc (sizeof (*vp));  memset ((char *) vp, '\0', sizeof (*vp));  vp->nxt = 0;  vp->bfd = abfd;  vp->name = bfd_get_filename (arch ? arch : abfd);  vp->member = arch ? bfd_get_filename (abfd) : "";    vmap_bfd.pbfd = arch;  vmap_bfd.pvmap = vp;  bfd_map_over_sections (abfd, bfdsec_to_vmap, &vmap_bfd);  /* Find the end of the list and append. */  for (vpp = &vmap; *vpp; vpp = &(*vpp)->nxt)    ;  *vpp = vp;  return vp;}