Merge from trunk + rename the event. Not tested yet.
[bpt/emacs.git] / src / unexaix.c
index 41324ac..c01a22a 100644 (file)
@@ -1,13 +1,12 @@
 /* Dump an executable image.
-   Copyright (C) 1985, 1986, 1987, 1988, 1999, 2001, 2002, 2003, 2004,
-                 2005, 2006, 2007  Free Software Foundation, Inc.
+   Copyright (C) 1985-1988, 1999, 2001-2012  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs 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.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,10 +14,9 @@ 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 GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
+/*
 In other words, you are welcome to use, share and improve this program.
 You are forbidden to forbid anyone else to use, share and improve
 what you give them.   Help stamp out software-hoarding!  */
@@ -32,33 +30,19 @@ what you give them.   Help stamp out software-hoarding!  */
  * Mike Sperber <sperber@informatik.uni-tuebingen.de>
  *
  * Synopsis:
- *     unexec (new_name, a_name, data_start, bss_start, entry_address)
- *     char *new_name, *a_name;
- *     unsigned data_start, bss_start, entry_address;
+ *     unexec (const char *new_name, const *old_name);
  *
  * Takes a snapshot of the program and makes an a.out format file in the
  * file named by the string argument new_name.
  * If a_name is non-NULL, the symbol table will be taken from the given file.
  * On some machines, an existing a_name file is required.
  *
- * data_start and entry_address are ignored.
- *
- * bss_start indicates how much of the data segment is to be saved in the
- * a.out file and restored when the program is executed.  It gives the lowest
- * unsaved address, and is rounded up to a page boundary.  The default when 0
- * is given assumes that the entire data segment is to be stored, including
- * the previous data and bss as well as any additional storage allocated with
- * sbrk(2).
- *
  */
 
-#ifndef emacs
-#define PERROR(arg) perror (arg); return -1
-#else
 #include <config.h>
-#define PERROR(file) report_error (file, new)
-#endif
+#include "unexec.h"
 
+#define PERROR(file) report_error (file, new)
 #include <a.out.h>
 /* Define getpagesize () if the system does not.
    Note that this may depend on symbols defined in a.out.h
@@ -72,8 +56,9 @@ what you give them.   Help stamp out software-hoarding!  */
 #include <unistd.h>
 #include <fcntl.h>
 
-extern char *start_of_text (void);             /* Start of text */
-extern char *start_of_data (void);             /* Start of initialized data */
+#include "mem-limits.h"
+
+char *start_of_text (void);                    /* Start of text */
 
 extern int _data;
 extern int _text;
@@ -94,56 +79,41 @@ static long data_scnptr;
 static long load_scnptr;
 static long orig_load_scnptr;
 static long orig_data_scnptr;
-static int unrelocate_symbols (int, int, char *, char *);
+static int unrelocate_symbols (int, int, const char *, const char *);
 
 #ifndef MAX_SECTIONS
 #define MAX_SECTIONS   10
 #endif
 
-static int adjust_lnnoptrs (int, int, char *);
+static int adjust_lnnoptrs (int, int, const char *);
 
 static int pagemask;
 
-/* Correct an int which is the bit pattern of a pointer to a byte
-   into an int which is the number of a byte.
-   This is a no-op on ordinary machines, but not on all.  */
-
-#ifndef ADDR_CORRECT   /* Let m-*.h files override this definition */
-#define ADDR_CORRECT(x) ((char *)(x) - (char*)0)
-#endif
-
-#ifdef emacs
 #include "lisp.h"
 
 static void
-report_error (char *file, int fd)
+report_error (const char *file, int fd)
 {
   if (fd)
     close (fd);
   report_file_error ("Cannot unexec", Fcons (build_string (file), Qnil));
 }
-#endif /* emacs */
 
 #define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1
 #define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1
 #define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1
 
 static void
-report_error_1 (int fd, char *msg, int a1, int a2)
+report_error_1 (int fd, const char *msg, int a1, int a2)
 {
   close (fd);
-#ifdef emacs
   error (msg, a1, a2);
-#else
-  fprintf (stderr, msg, a1, a2);
-  fprintf (stderr, "\n");
-#endif
 }
 
-static int make_hdr (int, int, unsigned, unsigned, unsigned, char *, char *);
-static void mark_x (char *);
+static int make_hdr (int, int, const char *, const char *);
+static void mark_x (const char *);
 static int copy_text_and_data (int);
-static int copy_sym (int, int, char *, char *);
+static int copy_sym (int, int, const char *, const char *);
 static void write_segment (int, char *, char *);
 \f
 /* ****************************************************************
@@ -151,10 +121,8 @@ static void write_segment (int, char *, char *);
  *
  * driving logic.
  */
-int unexec (char *new_name, char *a_name,
-           unsigned data_start,
-           unsigned bss_start,
-           unsigned entry_address)
+void
+unexec (const char *new_name, const char *a_name)
 {
   int new = -1, a_out = -1;
 
@@ -167,8 +135,6 @@ int unexec (char *new_name, char *a_name,
       PERROR (new_name);
     }
   if (make_hdr (new, a_out,
-               data_start, bss_start,
-               entry_address,
                a_name, new_name) < 0
       || copy_text_and_data (new) < 0
       || copy_sym (new, a_out, a_name, new_name) < 0
@@ -176,14 +142,13 @@ int unexec (char *new_name, char *a_name,
       || unrelocate_symbols (new, a_out, a_name, new_name) < 0)
     {
       close (new);
-      return -1;
+      return;
     }
 
   close (new);
   if (a_out >= 0)
     close (a_out);
   mark_x (new_name);
-  return 0;
 }
 
 /* ****************************************************************
@@ -194,12 +159,11 @@ int unexec (char *new_name, char *a_name,
  */
 static int
 make_hdr (int new, int a_out,
-         unsigned data_start, unsigned bss_start,
-         unsigned entry_address,
-         char *a_name, char *new_name)
+         const char *a_name, const char *new_name)
 {
   int scns;
-  unsigned int bss_end;
+  unsigned int bss_start;
+  unsigned int data_start;
 
   struct scnhdr section[MAX_SECTIONS];
   struct scnhdr * f_thdr;              /* Text section header */
@@ -219,22 +183,8 @@ make_hdr (int new, int a_out,
 
   data_start = data_start & ~pagemask; /* (Down) to page boundary. */
 
-  bss_end = ADDR_CORRECT (sbrk (0)) + pagemask;
-  bss_end &= ~ pagemask;
-  /* Adjust data/bss boundary. */
-  if (bss_start != 0)
-    {
-      bss_start = (ADDR_CORRECT (bss_start) + pagemask);
-      /* (Up) to page bdry. */
-      bss_start &= ~ pagemask;
-      if (bss_start > bss_end)
-       {
-         ERROR1 ("unexec: Specified bss_start (%u) is past end of program",
-                 bss_start);
-       }
-    }
-  else
-    bss_start = bss_end;
+  bss_start = ADDR_CORRECT (sbrk (0)) + pagemask;
+  bss_start &= ~ pagemask;
 
   if (data_start > bss_start)  /* Can't have negative data size. */
     {
@@ -271,24 +221,24 @@ make_hdr (int new, int a_out,
          }
 
 #define CHECK_SCNHDR(ptr, name, flags) \
-  if (strcmp(s->s_name, name) == 0) { \
+  if (strcmp (s->s_name, name) == 0) { \
     if (s->s_flags != flags) { \
-      fprintf(stderr, "unexec: %lx flags where %x expected in %s section.\n", \
-             (unsigned long)s->s_flags, flags, name); \
+      fprintf (stderr, "unexec: %lx flags where %x expected in %s section.\n", \
+               (unsigned long)s->s_flags, flags, name);                 \
     } \
     if (ptr) { \
-      fprintf(stderr, "unexec: duplicate section header for section %s.\n", \
-             name); \
+      fprintf (stderr, "unexec: duplicate section header for section %s.\n", \
+               name);                                                   \
     } \
     ptr = s; \
   }
-       CHECK_SCNHDR(f_thdr, _TEXT, STYP_TEXT);
-       CHECK_SCNHDR(f_dhdr, _DATA, STYP_DATA);
-       CHECK_SCNHDR(f_bhdr, _BSS, STYP_BSS);
-       CHECK_SCNHDR(f_lhdr, _LOADER, STYP_LOADER);
-       CHECK_SCNHDR(f_dbhdr, _DEBUG,  STYP_DEBUG);
-       CHECK_SCNHDR(f_tchdr, _TYPCHK,  STYP_TYPCHK);
-       CHECK_SCNHDR(f_xhdr, _EXCEPT,  STYP_EXCEPT);
+       CHECK_SCNHDR (f_thdr, _TEXT, STYP_TEXT);
+       CHECK_SCNHDR (f_dhdr, _DATA, STYP_DATA);
+       CHECK_SCNHDR (f_bhdr, _BSS, STYP_BSS);
+       CHECK_SCNHDR (f_lhdr, _LOADER, STYP_LOADER);
+       CHECK_SCNHDR (f_dbhdr, _DEBUG,  STYP_DEBUG);
+       CHECK_SCNHDR (f_tchdr, _TYPCHK,  STYP_TYPCHK);
+       CHECK_SCNHDR (f_xhdr, _EXCEPT,  STYP_EXCEPT);
       }
 
       if (f_thdr == 0)
@@ -319,7 +269,7 @@ make_hdr (int new, int a_out,
   f_hdr.f_flags |= (F_RELFLG | F_EXEC);
 
   f_ohdr.dsize = bss_start - f_ohdr.data_start;
-  f_ohdr.bsize = bss_end - bss_start;
+  f_ohdr.bsize = 0;
 
   f_dhdr->s_size = f_ohdr.dsize;
   f_bhdr->s_size = f_ohdr.bsize;
@@ -443,7 +393,6 @@ write_segment (int new, char *ptr, char *end)
 {
   int i, nwrite, ret;
   char buf[80];
-  extern int errno;
   char zeros[UnexBlockSz];
 
   for (i = 0; ptr < end;)
@@ -480,7 +429,7 @@ write_segment (int new, char *ptr, char *end)
  * Copy the relocation information and symbol table from the a.out to the new
  */
 static int
-copy_sym (int new, int a_out, char *a_name, char *new_name)
+copy_sym (int new, int a_out, const char *a_name, const char *new_name)
 {
   char page[UnexBlockSz];
   int n;
@@ -516,7 +465,7 @@ copy_sym (int new, int a_out, char *a_name, char *new_name)
  * After successfully building the new a.out, mark it executable
  */
 static void
-mark_x (char *name)
+mark_x (const char *name)
 {
   struct stat sbuf;
   int um;
@@ -534,7 +483,7 @@ mark_x (char *name)
 }
 \f
 static int
-adjust_lnnoptrs (int writedesc, int readdesc, char *new_name)
+adjust_lnnoptrs (int writedesc, int readdesc, const char *new_name)
 {
   int nsyms;
   int naux;
@@ -581,7 +530,8 @@ adjust_lnnoptrs (int writedesc, int readdesc, char *new_name)
 }
 
 static int
-unrelocate_symbols (int new, int a_out, char *a_name, char *new_name)
+unrelocate_symbols (int new, int a_out,
+                   const char *a_name, const char *new_name)
 {
   int i;
   LDHDR ldhdr;
@@ -592,7 +542,7 @@ unrelocate_symbols (int new, int a_out, char *a_name, char *new_name)
 #else
   /* This worked (and was needed) before AIX 4.2.
      I have no idea why. -- Mike */
-  ulong d_reloc = (ulong) &_data - ALIGN(f_ohdr.data_start, 2);
+  ulong d_reloc = (ulong) &_data - ALIGN (f_ohdr.data_start, 2);
 #endif
   int * p;
 
@@ -678,5 +628,15 @@ unrelocate_symbols (int new, int a_out, char *a_name, char *new_name)
   return 0;
 }
 
-/* arch-tag: 0783857a-7c2d-456f-a426-58b722d69fd0
-   (do not change this comment) */
+/*
+ *     Return the address of the start of the text segment prior to
+ *     doing an unexec.  After unexec the return value is undefined.
+ *     See crt0.c for further explanation and _start.
+ *
+ */
+
+char *
+start_of_text (void)
+{
+  return ((char *) 0x10000000);
+}