(Fuser_full_name): Accept a string (the login name) as
[bpt/emacs.git] / src / unexsgi.c
index b375ee5..3f23859 100644 (file)
@@ -1,19 +1,22 @@
 /* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992
    Free Software Foundation, Inc.
 
-    This program 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.
+This file is part of GNU Emacs.
 
-    This program 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.
+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.
 
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+GNU Emacs 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 GNU Emacs; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
 
 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
@@ -458,6 +461,45 @@ round_up (x, 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;
+     Elf32_Ehdr *old_file_h;
+     Elf32_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 .bss in %s.\n", file_name, 0);
+    }
+
+  return idx;
+}
+
 /* ****************************************************************
  * unexec
  *
@@ -491,6 +533,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
   Elf32_Word old_bss_size, new_data2_size;
   Elf32_Off  new_data2_offset;
   Elf32_Addr new_data2_addr;
+  Elf32_Addr new_offsets_shift;
 
   int n, nn, old_bss_index, old_data_index, new_data2_index;
   int old_mdebug_index;
@@ -525,34 +568,20 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
     = (char *) old_base + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
 
   /* Find the mdebug section, if any.  */
-  for (old_mdebug_index = 1; old_mdebug_index < 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 = -1; /* just means no such section was present */
 
-  /* Find the old .bss section.  Figure out parameters of the new
-     data2 and bss sections.  */
+  old_mdebug_index = find_section (".mdebug", old_section_names,
+                                  old_name, old_file_h, old_section_h, 1);
 
-  for (old_bss_index = 1; old_bss_index < 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,
-                  ".bss"))
-       break;
-    }
-  if (old_bss_index == old_file_h->e_shnum)
-    fatal ("Can't find .bss in %s.\n", old_name, 0);
+  /* Find the old .bss section. */
+
+  old_bss_index = find_section (".bss", old_section_names,
+                               old_name, old_file_h, old_section_h, 0);
+
+  /* Find the old .data section.  Figure out parameters of
+     the new data2 and bss sections.  */
+
+  old_data_index = find_section (".data", old_section_names,
+                                old_name, old_file_h, old_section_h, 0);
 
   old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
   old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
@@ -564,7 +593,10 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
 #endif
   new_data2_addr = old_bss_addr;
   new_data2_size = new_bss_addr - old_bss_addr;
-  new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset;
+  new_data2_offset  = OLD_SECTION_H (old_data_index).sh_offset +
+    (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
+  new_offsets_shift = new_bss_addr -
+    ((old_bss_addr & ~0xfff) + ((old_bss_addr & 0xfff) ? 0x1000 : 0));
 
 #ifdef DEBUG
   fprintf (stderr, "old_bss_index %d\n", old_bss_index);
@@ -574,6 +606,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
   fprintf (stderr, "new_data2_addr %x\n", new_data2_addr);
   fprintf (stderr, "new_data2_size %x\n", new_data2_size);
   fprintf (stderr, "new_data2_offset %x\n", new_data2_offset);
+  fprintf (stderr, "new_offsets_shift %x\n", new_offsets_shift);
 #endif
 
   if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
@@ -587,7 +620,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
   if (new_file < 0)
     fatal ("Can't creat (%s): errno %d\n", new_name, errno);
 
-  new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size;
+  new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_offsets_shift; 
 
   if (ftruncate (new_file, new_file_size))
     fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno);
@@ -602,7 +635,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
   new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff);
   new_section_h
     = (Elf32_Shdr *) ((byte *) new_base + old_file_h->e_shoff
-                     + new_data2_size);
+                     + new_offsets_shift);
 
   /* Make our new file, program and section headers as copies of the
      originals.  */
@@ -617,7 +650,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
   /* Fix up file header.  We'll add one section.  Section header is
      further away now.  */
 
-  new_file_h->e_shoff += new_data2_size;
+  new_file_h->e_shoff += new_offsets_shift;
   new_file_h->e_shnum += 1;
 
 #ifdef DEBUG
@@ -657,18 +690,18 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
   if (n < 0)
     fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0);
 
-  NEW_PROGRAM_H (n).p_filesz += new_data2_size;
+  NEW_PROGRAM_H (n).p_filesz += new_offsets_shift;
   NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz;
 
-#if 1 /* Maybe allow section after data2 - does this ever happen?  */
+#if 1                          /* Maybe allow section after data2 - does this ever happen?  */
   for (n = new_file_h->e_phnum - 1; n >= 0; n--)
     {
       if (NEW_PROGRAM_H (n).p_vaddr
          && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr)
-       NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size;
+       NEW_PROGRAM_H (n).p_vaddr += new_offsets_shift - old_bss_size;
 
       if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset)
-       NEW_PROGRAM_H (n).p_offset += new_data2_size;
+       NEW_PROGRAM_H (n).p_offset += new_offsets_shift;
     }
 #endif
 
@@ -690,6 +723,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
   for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++)
     {
       caddr_t src;
+
       /* If it is bss section, insert the new data2 section before it.  */
       if (n == old_bss_index)
        {
@@ -710,28 +744,28 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
                  (caddr_t) OLD_SECTION_H (n).sh_addr, 
                  new_data2_size);
          nn++;
-       }
+         memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), 
+                 old_file_h->e_shentsize);
       
-      memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), 
-             old_file_h->e_shentsize);
-      
-      /* The new bss section's size is zero, and its file offset and virtual
-        address should be off by NEW_DATA2_SIZE.  */
-      if (n == old_bss_index)
-       {
-         /* NN should be `old_bss_index + 1' at this point. */
-         NEW_SECTION_H (nn).sh_offset += new_data2_size;
-         NEW_SECTION_H (nn).sh_addr += new_data2_size;
+         /* The new bss section's size is zero, and its file offset and virtual
+            address should be off by NEW_OFFSETS_SHIFT.  */
+         NEW_SECTION_H (nn).sh_offset += new_offsets_shift;
+         NEW_SECTION_H (nn).sh_addr    = new_bss_addr;
          /* Let the new bss section address alignment be the same as the
             section address alignment followed the old bss section, so 
             this section will be placed in exactly the same place.  */
          NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign;
          NEW_SECTION_H (nn).sh_size = 0;
        }
-      /* Any section that was original placed AFTER the bss section should now
-        be off by NEW_DATA2_SIZE.  */
-      else if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
-       NEW_SECTION_H (nn).sh_offset += new_data2_size;
+      else
+       memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), 
+               old_file_h->e_shentsize);
+
+      /* Any section that was original placed AFTER the bss
+        section must now be adjusted by NEW_OFFSETS_SHIFT.  */
+
+      if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
+       NEW_SECTION_H (nn).sh_offset += new_offsets_shift;
       
       /* If any section hdr refers to the section after the new .data
         section, make it refer to next one because we have inserted 
@@ -753,8 +787,8 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
         ".data" in the strings table) get copied from the current process
         instead of the old file.  */
       if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data")
-         || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
-                     ".data1"))
+         || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data1")
+         || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".got"))
        src = (caddr_t) OLD_SECTION_H (n).sh_addr;
       else
        src = old_base + OLD_SECTION_H (n).sh_offset;
@@ -778,42 +812,42 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
       n_phdrr->__fileaddr += movement;         \
     }
 
-       HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset);
-       HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset);
-       unsigned movement = new_data2_size;
-
-       MDEBUGADJUST (idnMax, cbDnOffset);
-       MDEBUGADJUST (ipdMax, cbPdOffset);
-       MDEBUGADJUST (isymMax, cbSymOffset);
-       MDEBUGADJUST (ioptMax, cbOptOffset);
-       MDEBUGADJUST (iauxMax, cbAuxOffset);
-       MDEBUGADJUST (issMax, cbSsOffset);
-       MDEBUGADJUST (issExtMax, cbSsExtOffset);
-       MDEBUGADJUST (ifdMax, cbFdOffset);
-       MDEBUGADJUST (crfd, cbRfdOffset);
-       MDEBUGADJUST (iextMax, cbExtOffset);
-       /* The Line Section, being possible off in a hole of the object,
-          requires special handling.  */
-       if (n_phdrr->cbLine > 0)
-         {
-           if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset
-                                        + OLD_SECTION_H (n).sh_size))
-             {
-               /* line data is in a hole in elf. do special copy and adjust
-                  for this ld mistake.
-                  */
-               n_phdrr->cbLineOffset += movement;
-
-               memcpy (n_phdrr->cbLineOffset + new_base,
-                       o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
-             }
-           else
-             {
-               /* somehow line data is in .mdebug as it is supposed to be.  */
-               MDEBUGADJUST (cbLine, cbLineOffset);
-             }
-         }
-      }
+         HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset);
+         HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset);
+         unsigned movement = new_offsets_shift;
+
+         MDEBUGADJUST (idnMax, cbDnOffset);
+         MDEBUGADJUST (ipdMax, cbPdOffset);
+         MDEBUGADJUST (isymMax, cbSymOffset);
+         MDEBUGADJUST (ioptMax, cbOptOffset);
+         MDEBUGADJUST (iauxMax, cbAuxOffset);
+         MDEBUGADJUST (issMax, cbSsOffset);
+         MDEBUGADJUST (issExtMax, cbSsExtOffset);
+         MDEBUGADJUST (ifdMax, cbFdOffset);
+         MDEBUGADJUST (crfd, cbRfdOffset);
+         MDEBUGADJUST (iextMax, cbExtOffset);
+         /* The Line Section, being possible off in a hole of the object,
+            requires special handling.  */
+         if (n_phdrr->cbLine > 0)
+           {
+             if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset
+                                          + OLD_SECTION_H (n).sh_size))
+               {
+                 /* line data is in a hole in elf. do special copy and adjust
+                    for this ld mistake.
+                    */
+                 n_phdrr->cbLineOffset += movement;
+
+                 memcpy (n_phdrr->cbLineOffset + new_base,
+                         o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
+               }
+             else
+               {
+                 /* somehow line data is in .mdebug as it is supposed to be.  */
+                 MDEBUGADJUST (cbLine, cbLineOffset);
+               }
+           }
+       }
 
       /* If it is the symbol table, its st_shndx field needs to be patched. */
       if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB