update.
[chise/xemacs-chise.git-] / src / unexelf.c
index ffce626..54c48e1 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992, 1993, 1999, 2000
+/* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992, 1993
    Free Software Foundation, Inc.
 
 This file is part of XEmacs.
@@ -18,7 +18,7 @@ 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 20.6.90. */
+/* Synched up with: FSF 20.4. */
 
 /*
  * unexec.c - Convert a running program into an a.out file.
@@ -49,6 +49,11 @@ Boston, MA 02111-1307, USA.  */
  * The value you specify may be rounded down to a suitable boundary
  * as required by the machine you are using.
  *
+ * Specifying zero for data_start means the boundary between text and data
+ * should not be the same as when the program was loaded.
+ * If NO_REMAP is defined, the argument data_start is ignored and the
+ * segment boundaries are never changed.
+ *
  * 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
@@ -58,6 +63,9 @@ Boston, MA 02111-1307, USA.  */
  *
  * The new file is set up to start at entry_address.
  *
+ * If you make improvements I'd like to get them too.
+ * harpo!utah-cs!thomas, thomas@Utah-20
+ *
  */
 
 /* Even more heavily modified by james@bigtex.cactus.org of Dell Computer Co.
@@ -416,7 +424,7 @@ extern void fatal (const char *, ...);
 #include <errno.h>
 #include <unistd.h>
 #include <fcntl.h>
-#if !defined (__NetBSD__) && !defined (__OpenBSD__)
+#ifdef HAVE_ELF_H
 #include <elf.h>
 #endif
 #include <sys/mman.h>
@@ -425,7 +433,7 @@ extern void fatal (const char *, ...);
 #include <sym.h>
 #endif /* __sony_news && _SYSTYPE_SYSV */
 #ifdef __sgi
-#include <syms.h> /* for HDRR declaration */
+#include <sym.h> /* for HDRR declaration */
 #endif /* __sgi */
 
 #if defined (__alpha__) && !defined (__NetBSD__) && !defined (__OpenBSD__)
@@ -474,19 +482,17 @@ typedef struct {
 # endif
 # include <sys/exec_elf.h>
 
-# ifndef PT_LOAD
-#  define PT_LOAD      Elf_pt_load
-#  define SHT_SYMTAB   Elf_sht_symtab
-#  define SHT_DYNSYM   Elf_sht_dynsym
-#  define SHT_NULL     Elf_sht_null
-#  define SHT_NOBITS   Elf_sht_nobits
-#  define SHT_REL      Elf_sht_rel
-#  define SHT_RELA     Elf_sht_rela
-
-#  define SHN_UNDEF    Elf_eshn_undefined
-#  define SHN_ABS      Elf_eshn_absolute
-#  define SHN_COMMON   Elf_eshn_common
-# endif
+# define PT_LOAD       Elf_pt_load
+# define SHT_SYMTAB    Elf_sht_symtab
+# define SHT_DYNSYM    Elf_sht_dynsym
+# define SHT_NULL      Elf_sht_null
+# define SHT_NOBITS    Elf_sht_nobits
+# define SHT_REL       Elf_sht_rel
+# define SHT_RELA      Elf_sht_rela
+
+# define SHN_UNDEF     Elf_eshn_undefined
+# define SHN_ABS       Elf_eshn_absolute
+# define SHN_COMMON    Elf_eshn_common
 
 # ifdef __alpha__
 #  include <sys/exec_ecoff.h>
@@ -505,18 +511,10 @@ typedef struct {
 
 #ifndef ElfW
 # ifdef __STDC__
-#  define ElfBitsW(bits, type) Elf##bits##_##type
+#  define ElfW(type)   Elf32_##type
 # else
-#  define ElfBitsW(bits, type) Elf/**/bits/**/_/**/type
+#  define ElfW(type)   Elf32_/**/type
 # endif
-# ifdef _LP64
-#  define ELFSIZE 64
-# else
-#  define ELFSIZE 32
-# endif
-  /* This macro expands `bits' before invoking ElfBitsW.  */
-# define ElfExpandBitsW(bits, type) ElfBitsW (bits, type)
-# define ElfW(type) ElfExpandBitsW (ELFSIZE, type)
 #endif
 
 #ifndef ELF_BSS_SECTION_NAME
@@ -576,45 +574,6 @@ round_up (ElfW(Addr) x, ElfW(Addr) y)
   return x - rem + y;
 }
 
-/* Return the index of the section named NAME.
-   SECTION_NAMES, FILE_NAME and FILE_H give information
-   about the file we are looking in.
-
-   If we don't find the section NAME, that is a fatal error
-   if NOERROR is 0; we return -1 if NOERROR is nonzero.  */
-
-static int
-find_section (name, section_names, file_name, old_file_h, old_section_h, noerror)
-     char *name;
-     char *section_names;
-     char *file_name;
-     ElfW(Ehdr) *old_file_h;
-     ElfW(Shdr) *old_section_h;
-     int noerror;
-{
-  int idx;
-
-  for (idx = 1; idx < old_file_h->e_shnum; idx++)
-    {
-#ifdef DEBUG
-      fprintf (stderr, "Looking for %s - found %s\n", name,
-              section_names + OLD_SECTION_H (idx).sh_name);
-#endif
-      if (!strcmp (section_names + OLD_SECTION_H (idx).sh_name,
-                  name))
-       break;
-    }
-  if (idx == old_file_h->e_shnum)
-    {
-      if (noerror)
-       return -1;
-      else
-       fatal ("Can't find %s in %s.\n", name, file_name, 0);
-    }
-
-  return idx;
-}
-
 /* ****************************************************************
  * unexec
  *
@@ -650,10 +609,8 @@ unexec (char *new_name, char *old_name, unsigned int data_start,
   ElfW(Off)  new_data2_offset;
   ElfW(Addr) new_data2_addr;
 
-  int n, nn;
-  int old_bss_index, old_sbss_index;
-  int old_data_index, new_data2_index;
-  int old_mdebug_index;
+  int n, nn, old_bss_index, old_data_index, new_data2_index;
+  int old_sbss_index, old_mdebug_index;
   struct stat stat_buf;
 
   /* Open the old file & map it into the address space. */
@@ -684,43 +641,77 @@ unexec (char *new_name, char *old_name, unsigned int data_start,
   old_section_names = (char *) old_base
     + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
 
-  /* Find the mdebug section, if any.  */
-
-  old_mdebug_index = find_section (".mdebug", old_section_names,
-                                  old_name, old_file_h, old_section_h, 1);
-
   /* Find the old .bss section.  Figure out parameters of the new
    * data2 and bss sections.
    */
 
-  old_bss_index = find_section (".bss", old_section_names,
-                               old_name, old_file_h, old_section_h, 0);
-
-  old_sbss_index = find_section (".sbss", old_section_names,
-                                old_name, old_file_h, old_section_h, 1);
-  if (old_sbss_index != -1)
-    if (OLD_SECTION_H (old_sbss_index).sh_type == SHT_PROGBITS)
-      old_sbss_index = -1;
+  for (old_bss_index = 1; old_bss_index < (int) old_file_h->e_shnum;
+       old_bss_index++)
+    {
+#ifdef DEBUG
+      fprintf (stderr, "Looking for .bss - found %s\n",
+              old_section_names + OLD_SECTION_H (old_bss_index).sh_name);
+#endif
+      if (!strcmp (old_section_names + OLD_SECTION_H (old_bss_index).sh_name,
+                  ELF_BSS_SECTION_NAME))
+       break;
+    }
+  if (old_bss_index == old_file_h->e_shnum)
+    fatal ("Can't find .bss in %s.\n", old_name, 0);
 
-  if (old_sbss_index == -1)
+  for (old_sbss_index = 1; old_sbss_index < (int) old_file_h->e_shnum;
+       old_sbss_index++)
     {
-      old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
-      old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
+#ifdef DEBUG
+      fprintf (stderr, "Looking for .sbss - found %s\n",
+              old_section_names + OLD_SECTION_H (old_sbss_index).sh_name);
+#endif
+      if (!strcmp (old_section_names + OLD_SECTION_H (old_sbss_index).sh_name,
+                  ".sbss"))
+       break;
+    }
+  if (old_sbss_index == old_file_h->e_shnum)
+    {
+      old_sbss_index = -1;
+      old_bss_addr = OLD_SECTION_H(old_bss_index).sh_addr;
+      old_bss_size = OLD_SECTION_H(old_bss_index).sh_size;
       new_data2_index = old_bss_index;
     }
   else
     {
-      old_bss_addr = OLD_SECTION_H (old_sbss_index).sh_addr;
-      old_bss_size = OLD_SECTION_H (old_bss_index).sh_size
-       + OLD_SECTION_H (old_sbss_index).sh_size;
+      old_bss_addr = OLD_SECTION_H(old_sbss_index).sh_addr;
+      old_bss_size = OLD_SECTION_H(old_bss_index).sh_size
+       + OLD_SECTION_H(old_sbss_index).sh_size;
       new_data2_index = old_sbss_index;
     }
 
-  /* Find the old .data section.  Figure out parameters of
-     the new data2 and bss sections.  */
+  for (old_mdebug_index = 1; old_mdebug_index < (int) old_file_h->e_shnum;
+       old_mdebug_index++)
+    {
+#ifdef DEBUG
+      fprintf (stderr, "Looking for .mdebug - found %s\n",
+              old_section_names + OLD_SECTION_H (old_mdebug_index).sh_name);
+#endif
+      if (!strcmp (old_section_names + OLD_SECTION_H (old_mdebug_index).sh_name,
+                  ".mdebug"))
+       break;
+    }
+    if (old_mdebug_index == old_file_h->e_shnum)
+       old_mdebug_index = 0;
 
-  old_data_index = find_section (".data", old_section_names,
-                                old_name, old_file_h, old_section_h, 0);
+  for (old_data_index = 1; old_data_index < (int) old_file_h->e_shnum;
+       old_data_index++)
+    {
+#ifdef DEBUG
+      fprintf (stderr, "Looking for .data - found %s\n",
+              old_section_names + OLD_SECTION_H (old_data_index).sh_name);
+#endif
+      if (!strcmp (old_section_names + OLD_SECTION_H (old_data_index).sh_name,
+                  ".data"))
+       break;
+    }
+    if (old_data_index == old_file_h->e_shnum)
+       old_data_index = 0;
 
 #if defined (emacs) || !defined (DEBUG)
   new_bss_addr = (ElfW(Addr)) sbrk (0);
@@ -815,13 +806,13 @@ unexec (char *new_name, char *old_name, unsigned int data_start,
       if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
        alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
 
-#ifdef __sgi
+#ifdef __mips
          /* According to r02kar@x4u2.desy.de (Karsten Kuenne)
             and oliva@gnu.org (Alexandre Oliva), on IRIX 5.2, we
             always get "Program segment above .bss" when dumping
             when the executable doesn't have an sbss section.  */
       if (old_sbss_index != -1)
-#endif /* __sgi */
+#endif /* __mips */
       if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz
          > (old_sbss_index == -1
             ? old_bss_addr
@@ -957,15 +948,6 @@ unexec (char *new_name, char *old_name, unsigned int data_start,
       if (NEW_SECTION_H (nn).sh_type != SHT_SYMTAB
          && NEW_SECTION_H (nn).sh_type != SHT_DYNSYM)
        PATCH_INDEX (NEW_SECTION_H (nn).sh_info);
-      
-      if (old_sbss_index != -1)
-       if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".sbss"))
-         {
-           NEW_SECTION_H (nn).sh_offset = 
-             round_up (NEW_SECTION_H (nn).sh_offset,
-                       NEW_SECTION_H (nn).sh_addralign);
-           NEW_SECTION_H (nn).sh_type = SHT_PROGBITS;
-         }
 
       /* Now, start to copy the content of sections.  */
       if (NEW_SECTION_H (nn).sh_type == SHT_NULL
@@ -981,18 +963,18 @@ unexec (char *new_name, char *old_name, unsigned int data_start,
           /* Taking these sections from the current process, breaks
              Linux in a subtle way. Binaries only run on the
              architecture (e.g. i586 vs i686) of the dumping machine */
+#ifdef __sgi
          || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
                      ".lit4")
          || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
                      ".lit8")
          || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
                      ".got")
+#endif
          || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
                      ".sdata1")
          || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
-                     ".data1")
-         || !strcmp (old_section_names + NEW_SECTION_H (nn).sh_name,
-                     ".sbss"))
+                     ".data1"))
        src = (caddr_t) OLD_SECTION_H (n).sh_addr;
       else
        src = old_base + OLD_SECTION_H (n).sh_offset;
@@ -1022,8 +1004,7 @@ unexec (char *new_name, char *old_name, unsigned int data_start,
 #endif /* __alpha__ */
 
 #if defined (__sony_news) && defined (_SYSTYPE_SYSV)
-      if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG
-         && old_mdebug_index != -1) 
+      if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG && old_mdebug_index) 
         {
          int diff = NEW_SECTION_H(nn).sh_offset 
                - OLD_SECTION_H(old_mdebug_index).sh_offset;
@@ -1161,12 +1142,14 @@ unexec (char *new_name, char *old_name, unsigned int data_start,
        if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data")
            || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
                        ".sdata")
+#ifdef __sgi
            || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
                        ".lit4")
            || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
                        ".lit8")
            || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
                        ".got")
+#endif
            || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
                        ".sdata1")
            || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),