* coding.c (make_conversion_work_buffer): Disable buffer modification
[bpt/emacs.git] / src / unexelf.c
index b3075f0..8dcce2e 100644 (file)
@@ -1,12 +1,13 @@
-/* Copyright (C) 1985,86,87,88,90,92,1999,2000,01,2003
-   Free Software Foundation, Inc.
+/* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992, 1999, 2000, 2001,
+                 2002, 2003, 2004, 2005, 2006, 2007, 2008
+                 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
@@ -14,10 +15,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., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, 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!  */
@@ -412,7 +412,7 @@ temacs:
 #include <string.h>
 #else
 #include <config.h>
-extern void fatal (char *, ...);
+extern void fatal (const char *msgid, ...);
 #endif
 
 #include <sys/types.h>
@@ -426,10 +426,10 @@ extern void fatal (char *, ...);
 #include <elf.h>
 #endif
 #include <sys/mman.h>
-#if defined (__sony_news) && defined (_SYSTYPE_SYSV)
+#if defined (_SYSTYPE_SYSV)
 #include <sys/elf_mips.h>
 #include <sym.h>
-#endif /* __sony_news && _SYSTYPE_SYSV */
+#endif /* _SYSTYPE_SYSV */
 #if __sgi
 #include <syms.h> /* for HDRR declaration */
 #endif /* __sgi */
@@ -682,7 +682,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
   ElfW(Addr) new_data2_addr;
 
   int n, nn;
-  int old_bss_index, old_sbss_index;
+  int old_bss_index, old_sbss_index, old_plt_index;
   int old_data_index, new_data2_index;
   int old_mdebug_index;
   struct stat stat_buf;
@@ -702,7 +702,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
 #if MAP_ANON == 0
   mmap_fd = open ("/dev/zero", O_RDONLY);
   if (mmap_fd < 0)
-    fatal ("Can't open /dev/zero for reading: errno %d\n", errno);
+    fatal ("Can't open /dev/zero for reading: errno %d\n", errno, 0);
 #endif
 
   /* We cannot use malloc here because that may use sbrk.  If it does,
@@ -713,7 +713,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
   old_base = mmap (NULL, old_file_size, PROT_READ | PROT_WRITE,
                   MAP_ANON | MAP_PRIVATE, mmap_fd, 0);
   if (old_base == MAP_FAILED)
-    fatal ("Can't allocate buffer for %s\n", old_name);
+    fatal ("Can't allocate buffer for %s\n", old_name, 0);
 
   if (read (old_file, old_base, stat_buf.st_size) != stat_buf.st_size)
     fatal ("Didn't read all of %s: errno %d\n", old_name, errno);
@@ -740,15 +740,34 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
   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)
+    if (OLD_SECTION_H (old_sbss_index).sh_type != SHT_NOBITS)
       old_sbss_index = -1;
 
-  if (old_sbss_index == -1)
+  /* PowerPC64 has .plt in the BSS section.  */
+  old_plt_index = find_section (".plt", old_section_names,
+                               old_name, old_file_h, old_section_h, 1);
+  if (old_plt_index != -1)
+    if (OLD_SECTION_H (old_plt_index).sh_type != SHT_NOBITS)
+      old_plt_index = -1;
+
+  if (old_sbss_index == -1 && old_plt_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 if (old_plt_index != -1
+          && (old_sbss_index == -1
+              || (OLD_SECTION_H (old_sbss_index).sh_addr
+                  > OLD_SECTION_H (old_plt_index).sh_addr)))
+    {
+      old_bss_addr = OLD_SECTION_H (old_plt_index).sh_addr;
+      old_bss_size = OLD_SECTION_H (old_bss_index).sh_size
+       + OLD_SECTION_H (old_plt_index).sh_size;
+      if (old_sbss_index != -1)
+       old_bss_size += OLD_SECTION_H (old_sbss_index).sh_size;
+      new_data2_index = old_plt_index;
+    }
   else
     {
       old_bss_addr = OLD_SECTION_H (old_sbss_index).sh_addr;
@@ -802,7 +821,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
   new_base = mmap (NULL, new_file_size, PROT_READ | PROT_WRITE,
                   MAP_ANON | MAP_PRIVATE, mmap_fd, 0);
   if (new_base == MAP_FAILED)
-    fatal ("Can't allocate buffer for %s\n", old_name);
+    fatal ("Can't allocate buffer for %s\n", old_name, 0);
 
   new_file_h = (ElfW(Ehdr) *) new_base;
   new_program_h = (ElfW(Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
@@ -934,7 +953,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
       if (n == old_bss_index
          /* The new bss and sbss section's size is zero, and its file offset
             and virtual address should be off by NEW_DATA2_SIZE.  */
-         || n == old_sbss_index
+         || n == old_sbss_index || n == old_plt_index
          )
        {
          /* NN should be `old_s?bss_index + 1' at this point. */
@@ -950,26 +969,18 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
        }
       else
        {
-         /* Any section that was original placed AFTER the bss
-            section should now be off by NEW_DATA2_SIZE. */
-#ifdef SOLARIS_POWERPC
-         /* On PPC Reference Platform running Solaris 2.5.1
-            the plt section is also of type NOBI like the bss section.
-            (not really stored) and therefore sections after the bss
-            section start at the plt offset. The plt section is always
-            the one just before the bss section.
-            It would be better to put the new data section before
-            the .plt section, or use libelf instead.
-            Erik Deumens, deumens@qtp.ufl.edu.  */
-         if (NEW_SECTION_H (nn).sh_offset
-             >= OLD_SECTION_H (old_bss_index-1).sh_offset)
-           NEW_SECTION_H (nn).sh_offset += new_data2_size;
-#else
-         if (round_up (NEW_SECTION_H (nn).sh_offset,
-                       OLD_SECTION_H (old_bss_index).sh_addralign)
-             >= new_data2_offset)
+         /* Any section that was originally placed after the .bss
+            section should now be off by NEW_DATA2_SIZE.  If a
+            section overlaps the .bss section, consider it to be
+            placed after the .bss section.  Overlap can occur if the
+            section just before .bss has less-strict alignment; this
+            was observed between .symtab and .bss on Solaris 2.5.1
+            (sparc) with GCC snapshot 960602.  */
+
+         if (NEW_SECTION_H (nn).sh_offset + NEW_SECTION_H (nn).sh_size
+             > new_data2_offset)
            NEW_SECTION_H (nn).sh_offset += new_data2_size;
-#endif
+
          /* Any section that was originally placed after the section
             header table should now be off by the size of one section
             header table entry.  */
@@ -1070,12 +1081,12 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
        }
 #endif /* __alpha__ */
 
-#if defined (__sony_news) && defined (_SYSTYPE_SYSV)
+#if defined (_SYSTYPE_SYSV)
       if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG
          && old_mdebug_index != -1)
         {
          int diff = NEW_SECTION_H(nn).sh_offset
-               - OLD_SECTION_H(old_mdebug_index).sh_offset;
+               - OLD_SECTION_H(old_mdebug_index).sh_offset;
          HDRR *phdr = (HDRR *)(NEW_SECTION_H (nn).sh_offset + new_base);
 
          if (diff)
@@ -1093,7 +1104,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
              phdr->cbExtOffset  += diff;
            }
        }
-#endif /* __sony_news && _SYSTYPE_SYSV */
+#endif /* _SYSTYPE_SYSV */
 
 #if __sgi
       /* Adjust  the HDRR offsets in .mdebug and copy the
@@ -1253,9 +1264,13 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
   /* Write out new_file, and free the buffers.  */
 
   if (write (new_file, new_base, new_file_size) != new_file_size)
+#ifndef emacs
+    fatal ("Didn't write %d bytes: errno %d\n",
+          new_file_size, errno);
+#else
     fatal ("Didn't write %d bytes to %s: errno %d\n",
           new_file_size, new_base, errno);
-
+#endif
   munmap (old_base, old_file_size);
   munmap (new_base, new_file_size);
 
@@ -1280,3 +1295,6 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
   if (chmod (new_name, stat_buf.st_mode) == -1)
     fatal ("Can't chmod (%s): errno %d\n", new_name, errno);
 }
+
+/* arch-tag: e02e1512-95e2-4ef0-bba7-b6bce658f1e3
+   (do not change this comment) */