view src/unexalpha.c @ 1330:4542b72c005e

[xemacs-hg @ 2003-03-01 07:25:26 by ben] build patch Makefile.in.in: Move src deletions to src/Makefile.in.in. dump-paths.el, dumped-lisp.el: Delete. Combine stuff into setup-paths.el. find-paths.el: Removed. Make this file contain generic routines only. Move stuff to compute Emacs roots to setup-paths.el. startup.el: Removed. Move these variables into setup-paths.el. setup-paths.el, startup.el: Removed. Combine all high-level code for computing the paths into setup-paths.el. Create new function startup-find-load-path to encapsulate all logic for computing `load-path'. Eliminate invocation-directory and invocation-name parameters since there is no point (false generality) -- the code references other globals, which cannot be specified. Eliminate some code duplicated between setup-paths.el and startup.el. Clean up the debug-paths code and output load-path in addition. Add logic to paths-emacs-root-p to support separated source and build trees. loadup.el, make-docfile.el, update-elc-2.el, update-elc.el: Rewrite to allow for separated source and build trees, as may occur in MS Windows. NOTE TO BUILD HACKERS: loadup.el, make-docfile.el, update-elc.el and update-elc-2.el made two assumptions that are no longer correct: (1) The source and build trees are in the same place. (2) They can make assumptions about where `.' is. These files now compute the locations of the source and build roots at the top of the file. *ALL* constant file names or path snippets must now be made absolute using expand-file-name and one of these roots. dumped-lisp.el, packages.el: Removed. Remove some unused lists of Lisp files. packages-hardcoded-lisp (empty, in any case) moved to dumped-lisp.el. startup.el: When a compiled init file is out-of-date wrt the uncompiled version, load the uncompiled version and issue a nasty warning. update-elc-2.el: Force touching of auto-autoloads files when REBUILD_AUTOLOADS was set. update-elc.el: Fix code that checks whether dumping is necessary to check against xemacs.dmp, not xemacs.exe, when Unix and pdump. lwlib-Xm.c: Fix compile warning. README, config.inc.samp, xemacs.mak: -- Major reorganization and cleanup. -- Add support for separated build tree and source tree. -- Delete all support for X Windows building, since it's totally bit-rotten and will never be fixed up. Instruct people to use Cygwin if they want such support. make-build-dir: New script to create a skeleton build tree for use with separated build and source tree compilation. m/acorn.h, m/alliant-2800.h, m/alliant.h, m/altos.h, m/amdahl.h, m/arm.h, m/att3b.h, m/aviion.h, m/clipper.h, m/cnvrgnt.h, m/convex.h, m/cydra5.h, m/delta.h, m/delta88k.h, m/dpx2.h, m/elxsi.h, m/ews4800r.h, m/gould.h, m/hp800.h, m/hp9000s300.h, m/i860.h, m/ibmps2-aix.h, m/ibmrs6000.h, m/ibmrt-aix.h, m/ibmrt.h, m/intel386.h, m/iris4d.h, m/iris5d.h, m/iris6d.h, m/irist.h, m/m68k.h, m/masscomp.h, m/mg1.h, m/mips-nec.h, m/mips-siemens.h, m/mips.h, m/nh3000.h, m/nh4000.h, m/ns32000.h, m/plexus.h, m/powerpc.h, m/sequent-ptx.h, m/sequent.h, m/sgi-challenge.h, m/stride.h, m/tad68k.h, m/targon31.h, m/tekxd88.h, m/template.h, m/tower32.h, m/tower32v3.h, m/ustation.h, m/wicat.h, m/xps100.h, data.c, doc.c, editfns.c, emacs.c, lrecord.h, ntheap.c, process-unix.c, sysdep.c, unexec.c: Delete all support for bit-rotten CANNOT_DUMP. Just use pdump. Makefile.in.in: Lots o' cleanup. Use names like LISP, SRC instead of lispdir, srcdir, for consistency with xemacs.mak and the conventions in the rest of the file. Eliminate use of ${...} in favor of $(...), to make it easier to move code between this file and xemacs.mak. Fix dependency handling wrt NEEDTODUMP to eliminate problems some people (e.g. Vin) have been seeing with non-GNU makes. Write a long section about the subtle but oh-so-important differences in dependency processing between nmake, make, and GNU make. Add unicode-encapsulate target, from xemacs.mak. chartab.c, lrecord.h: Fix crash due to attempt to free objects across dump/undump.
author ben
date Sat, 01 Mar 2003 07:25:56 +0000
parents 023b83f4e54b
children 04bc9d2f42c7
line wrap: on
line source

/* Unexec for DEC alpha.  schoepf@sc.ZIB-Berlin.DE (Rainer Schoepf).

   Copyright (C) 1994 Free Software Foundation, Inc.

This file is part of XEmacs.

XEmacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

XEmacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with XEmacs; see the file COPYING.  If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.  */

/* Synched up with: FSF 19.31. */


#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <stdio.h>
#include <errno.h>
#include <varargs.h>
#include <filehdr.h>
#include <aouthdr.h>
#include <scnhdr.h>
#include <syms.h>

static void fatal_unexec (char *, char *);
static void mark_x (char *);

#define READ(_fd, _buffer, _size, _error_message, _error_arg) \
	errno = EEOF; \
	if (read (_fd, _buffer, _size) != _size) \
	  fatal_unexec (_error_message, _error_arg);

#define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \
	if (write (_fd, _buffer, _size) != _size) \
	  fatal_unexec (_error_message, _error_arg);

#define SEEK(_fd, _position, _error_message, _error_arg) \
	errno = EEOF; \
	if (lseek (_fd, _position, L_SET) != _position) \
	  fatal_unexec (_error_message, _error_arg);

#define EEOF -1

static struct scnhdr *text_section;
static struct scnhdr *init_section;
static struct scnhdr *finit_section;
static struct scnhdr *rdata_section;
static struct scnhdr *rconst_section;
static struct scnhdr *data_section;
static struct scnhdr *pdata_section;
static struct scnhdr *xdata_section;
static struct scnhdr *got_section;
static struct scnhdr *lit8_section;
static struct scnhdr *lit4_section;
static struct scnhdr *sdata_section;
static struct scnhdr *sbss_section;
static struct scnhdr *bss_section;

static unsigned long Brk;

struct headers {
    struct filehdr fhdr;
    struct aouthdr aout;
    struct scnhdr section[_MIPS_NSCNS_MAX];
};


/* Define name of label for entry point for the dumped executable.  */

#ifndef DEFAULT_ENTRY_ADDRESS
#define DEFAULT_ENTRY_ADDRESS __start
#endif
EXTERN_C int DEFAULT_ENTRY_ADDRESS (void);


int
unexec (char *new_name, char *a_name,
	unsigned long data_start,
	unsigned long bss_start,
	unsigned long entry_address)
{
  int new, old;
  char * oldptr;
  struct headers ohdr, nhdr;
  struct stat stat;
  long pagesize, brk;
  long newsyms, symrel;
  int i;
  long vaddr, scnptr;
#define BUFSIZE 8192
  char buffer[BUFSIZE];

  if ((old = open (a_name, O_RDONLY)) < 0)
    fatal_unexec ("opening %s", a_name);

  new = creat (new_name, 0666);
  if (new < 0) fatal_unexec ("creating %s", new_name);

  if ((fstat (old, &stat) == -1))
    fatal_unexec ("fstat %s", a_name);

  oldptr = (char *)mmap (0, stat.st_size, PROT_READ, MAP_FILE|MAP_SHARED, old, 0);

  if (oldptr == (char *)-1)
    fatal_unexec ("mmap %s", a_name);

  close (old);

  /* This is a copy of the a.out header of the original executable */

  ohdr = (*(struct headers *)oldptr);

  /* This is where we build the new header from the in-memory copy */

  nhdr = *((struct headers *)TEXT_START);

  /* First do some consistency checks */

  if (nhdr.fhdr.f_magic != ALPHAMAGIC
      && nhdr.fhdr.f_magic != ALPHAUMAGIC)
    {
      fprintf (stderr, "unexec: input file magic number is %x, not %x or %x.\n",
	       nhdr.fhdr.f_magic, ALPHAMAGIC, ALPHAUMAGIC);
      exit (1);
    }

  if (nhdr.fhdr.f_opthdr != sizeof (nhdr.aout))
    {
      fprintf (stderr, "unexec: input a.out header is %d bytes, not %ld.\n",
	       nhdr.fhdr.f_opthdr, (long) (sizeof (nhdr.aout)));
      exit (1);
    }
  if (nhdr.aout.magic != ZMAGIC)
    {
      fprintf (stderr, "unexec: input file a.out magic number is %o, not %o.\n",
	       nhdr.aout.magic, ZMAGIC);
      exit (1);
    }


  /* Now check the existence of certain header section and grab
     their addresses. */

#define CHECK_SCNHDR(ptr, name, flags)					\
  ptr = NULL;								\
  for (i = 0; i < nhdr.fhdr.f_nscns && !ptr; i++)			\
    if (strcmp (nhdr.section[i].s_name, name) == 0)			\
      {									\
	if (nhdr.section[i].s_flags != flags)				\
	  fprintf (stderr, "unexec: %x flags (%x expected) in %s section.\n", \
		   nhdr.section[i].s_flags, flags, name);		\
	ptr = nhdr.section + i;						\
      }									\

  CHECK_SCNHDR (text_section,  _TEXT,  STYP_TEXT);
  CHECK_SCNHDR (init_section,  _INIT,  STYP_INIT);
#ifdef _FINI
  CHECK_SCNHDR (finit_section, _FINI,  STYP_FINI);
#endif /* _FINI */
  CHECK_SCNHDR (rdata_section, _RDATA, STYP_RDATA);
#ifdef _RCONST
  CHECK_SCNHDR (rconst_section, _RCONST, STYP_RCONST);
#endif
#ifdef _PDATA
  CHECK_SCNHDR (pdata_section, _PDATA, STYP_PDATA);
#endif /* _PDATA */
#ifdef _GOT
  CHECK_SCNHDR (got_section,   _GOT,   STYP_GOT);
#endif /* _GOT */
  CHECK_SCNHDR (data_section,  _DATA,  STYP_DATA);
#ifdef _XDATA
  CHECK_SCNHDR (xdata_section, _XDATA, STYP_XDATA);
#endif /* _XDATA */
#ifdef _LIT8
  CHECK_SCNHDR (lit8_section,  _LIT8,  STYP_LIT8);
  CHECK_SCNHDR (lit4_section,  _LIT4,  STYP_LIT4);
#endif /* _LIT8 */
  CHECK_SCNHDR (sdata_section, _SDATA, STYP_SDATA);
  CHECK_SCNHDR (sbss_section,  _SBSS,  STYP_SBSS);
  CHECK_SCNHDR (bss_section,   _BSS,   STYP_BSS);


  pagesize = getpagesize ();
  brk = (((long) (sbrk (0))) + pagesize - 1) & (-pagesize);

  /* Remember the current break */

  Brk = brk;

  nhdr.aout.dsize = brk - DATA_START;
  nhdr.aout.bsize = 0;
  if (entry_address == 0)
    {
      nhdr.aout.entry = (unsigned long)DEFAULT_ENTRY_ADDRESS;
    }
  else
    nhdr.aout.entry = entry_address;

  nhdr.aout.bss_start = nhdr.aout.data_start + nhdr.aout.dsize;

  if (rdata_section != NULL)
    {
      rdata_section->s_size = data_start - DATA_START;

      /* Adjust start and virtual addresses of rdata_section, too.  */
      rdata_section->s_vaddr = DATA_START;
      rdata_section->s_paddr = DATA_START;
      rdata_section->s_scnptr = text_section->s_scnptr + nhdr.aout.tsize;
    }

  data_section->s_vaddr = data_start;
  data_section->s_paddr = data_start;
  data_section->s_size = brk - data_start;

  if (rdata_section != NULL)
    {
      data_section->s_scnptr = rdata_section->s_scnptr + rdata_section->s_size;
    }

  vaddr = data_section->s_vaddr + data_section->s_size;
  scnptr = data_section->s_scnptr + data_section->s_size;
  if (lit8_section != NULL)
    {
      lit8_section->s_vaddr = vaddr;
      lit8_section->s_paddr = vaddr;
      lit8_section->s_size = 0;
      lit8_section->s_scnptr = scnptr;
    }
  if (lit4_section != NULL)
    {
      lit4_section->s_vaddr = vaddr;
      lit4_section->s_paddr = vaddr;
      lit4_section->s_size = 0;
      lit4_section->s_scnptr = scnptr;
    }
  if (sdata_section != NULL)
    {
      sdata_section->s_vaddr = vaddr;
      sdata_section->s_paddr = vaddr;
      sdata_section->s_size = 0;
      sdata_section->s_scnptr = scnptr;
    }
#ifdef _XDATA
  if (xdata_section != NULL)
    {
      xdata_section->s_vaddr = vaddr;
      xdata_section->s_paddr = vaddr;
      xdata_section->s_size = 0;
      xdata_section->s_scnptr = scnptr;
    }
#endif
#ifdef _GOT
  if (got_section != NULL)
    {
      got_section->s_vaddr = vaddr;
      got_section->s_paddr = vaddr;
      got_section->s_size = 0;
      got_section->s_scnptr = scnptr;
    }
#endif /*_GOT */
  if (sbss_section != NULL)
    {
      sbss_section->s_vaddr = vaddr;
      sbss_section->s_paddr = vaddr;
      sbss_section->s_size = 0;
      sbss_section->s_scnptr = scnptr;
    }
  if (bss_section != NULL)
    {
      bss_section->s_vaddr = vaddr;
      bss_section->s_paddr = vaddr;
      bss_section->s_size = 0;
      bss_section->s_scnptr = scnptr;
    }

  WRITE (new, (char *)TEXT_START, nhdr.aout.tsize,
	 "writing text section to %s", new_name);
  WRITE (new, (char *)DATA_START, nhdr.aout.dsize,
	 "writing data section to %s", new_name);


  /*
   * Construct new symbol table header
   */

  memcpy (buffer, oldptr + nhdr.fhdr.f_symptr, cbHDRR);

#define symhdr ((pHDRR)buffer)
  newsyms = nhdr.aout.tsize + nhdr.aout.dsize;
  symrel = newsyms - nhdr.fhdr.f_symptr;
  nhdr.fhdr.f_symptr = newsyms;
  symhdr->cbLineOffset += symrel;
  symhdr->cbDnOffset += symrel;
  symhdr->cbPdOffset += symrel;
  symhdr->cbSymOffset += symrel;
  symhdr->cbOptOffset += symrel;
  symhdr->cbAuxOffset += symrel;
  symhdr->cbSsOffset += symrel;
  symhdr->cbSsExtOffset += symrel;
  symhdr->cbFdOffset += symrel;
  symhdr->cbRfdOffset += symrel;
  symhdr->cbExtOffset += symrel;

  WRITE (new, buffer, cbHDRR, "writing symbol table header of %s", new_name);

  /*
   * Copy the symbol table and line numbers
   */
  WRITE (new, oldptr + ohdr.fhdr.f_symptr + cbHDRR,
	 stat.st_size - ohdr.fhdr.f_symptr - cbHDRR,
	 "writing symbol table of %s", new_name);

#if 0

/* Not needed for now */

  update_dynamic_symbols (oldptr, new_name, new, newsyms,
			  ((pHDRR) (oldptr + ohdr.fhdr.f_symptr))->issExtMax,
                          ((pHDRR) (oldptr + ohdr.fhdr.f_symptr))->cbExtOffset,
                          ((pHDRR) (oldptr + ohdr.fhdr.f_symptr))->cbSsExtOffset);

#endif

#undef symhdr

  SEEK (new, 0, "seeking to start of header in %s", new_name);
  WRITE (new, &nhdr, sizeof (nhdr),
	 "writing header of %s", new_name);

  close (old);
  close (new);
  mark_x (new_name);
  return 0;
}


#if 0

/* Not needed for now */

/* The following function updates the values of some symbols
   that are used by the dynamic loader:

   _edata
   _end

*/

int
update_dynamic_symbols (
     char *old,			/* Pointer to old executable */
     char *new_name,            /* Name of new executable */
     int new,			/* File descriptor for new executable */
     long newsyms,		/* Offset of Symbol table in new executable */
     int nsyms,			/* Number of symbol table entries */
     long symoff,		/* Offset of External Symbols in old file */
     long stroff)		/* Offset of string table in old file */
{
  long i;
  int found = 0;
  EXTR n_end, n_edata;

  /* We go through the symbol table entries until we have found the two
     symbols. */

  /* cbEXTR is the size of an external symbol table entry */

  for (i = 0; i < nsyms && found < 2; i += cbEXTR)
    {
      REGISTER pEXTR x = (pEXTR) (old + symoff + i);
      char *s;
  
      s = old + stroff + x->asym.iss; /* name of the symbol */

      if (!strcmp(s,"_edata"))
	{
	  found++;
          memcpy (&n_edata, x, cbEXTR);
	  n_edata.asym.value = Brk;
	  SEEK (new, newsyms + cbHDRR + i,
		"seeking to symbol _edata in %s", new_name);
	  WRITE (new, &n_edata, cbEXTR,
		 "writing symbol table entry for _edata into %s", new_name);
	}
      else if (!strcmp(s,"_end"))
	{
	  found++;
          memcpy (&n_end, x, cbEXTR);
	  n_end.asym.value = Brk;
	  SEEK (new, newsyms + cbHDRR + i,
		"seeking to symbol _end in %s", new_name);
	  WRITE (new, &n_end, cbEXTR,
		 "writing symbol table entry for _end into %s", new_name);
	}
    }

}

#endif


/*
 * mark_x
 *
 * After successfully building the new a.out, mark it executable
 */

static void
mark_x (char *name)
{
  struct stat sbuf;
  int um = umask (777);
  umask (um);
  if (stat (name, &sbuf) < 0)
    fatal_unexec ("getting protection on %s", name);
  sbuf.st_mode |= 0111 & ~um;
  if (chmod (name, sbuf.st_mode) < 0)
    fatal_unexec ("setting protection on %s", name);
}

static void
fatal_unexec (char *s, char *arg)
{
  if (errno == EEOF)
    fputs ("unexec: unexpected end of file, ", stderr);
  else
    fprintf (stderr, "unexec: %s, ", strerror (errno));
  fprintf (stderr, s, arg);
  fputs (".\n", stderr);
  exit (1);
}