]> code.delx.au - gnu-emacs/blobdiff - src/unexelf.c
(XTmouse_position, x_term_init):
[gnu-emacs] / src / unexelf.c
index 1743e524c468307130cb11f7df5d95028842535e..a832755167e8259ecb498868719704dec7ee87ef 100644 (file)
@@ -423,6 +423,22 @@ Filesz      Memsz       Flags       Align
 #include <elf.h>
 #include <sys/mman.h>
 
+#ifdef __alpha__
+# include <sym.h>      /* get COFF debugging symbol table declaration */
+#endif
+
+#if __GNU_LIBRARY__ - 0 >= 6
+# include <link.h>     /* get ElfW etc */
+#endif
+
+#ifndef ElfW
+# ifdef __STDC__
+#  define ElfW(type)   Elf32_##type
+# else
+#  define ElfW(type)   Elf32_/**/type
+# endif
+#endif
+
 #ifndef emacs
 #define fatal(a, b, c) fprintf (stderr, a, b, c), exit (1)
 #else
@@ -437,15 +453,38 @@ extern void fatal (char *, ...);
 /* Get the address of a particular section or program header entry,
  * accounting for the size of the entries.
  */
+/* 
+   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.
+   Thus, we modify the test from
+      if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
+   to
+      if (NEW_SECTION_H (nn).sh_offset >= 
+               OLD_SECTION_H (old_bss_index-1).sh_offset)
+   This is just a hack. We should put the new data section
+   before the .plt section.
+   And we should not have this routine at all but use
+   the libelf library to read the old file and create the new
+   file.
+   The changed code is minimal and depends on prep set in m/prep.h
+   Erik Deumens
+   Quantum Theory Project
+   University of Florida
+   deumens@qtp.ufl.edu
+   Apr 23, 1996
+   */
 
 #define OLD_SECTION_H(n) \
-     (*(Elf32_Shdr *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))
+     (*(ElfW(Shdr) *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))
 #define NEW_SECTION_H(n) \
-     (*(Elf32_Shdr *) ((byte *) new_section_h + new_file_h->e_shentsize * (n)))
+     (*(ElfW(Shdr) *) ((byte *) new_section_h + new_file_h->e_shentsize * (n)))
 #define OLD_PROGRAM_H(n) \
-     (*(Elf32_Phdr *) ((byte *) old_program_h + old_file_h->e_phentsize * (n)))
+     (*(ElfW(Phdr) *) ((byte *) old_program_h + old_file_h->e_phentsize * (n)))
 #define NEW_PROGRAM_H(n) \
-     (*(Elf32_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))
+     (*(ElfW(Phdr) *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))
 
 #define PATCH_INDEX(n) \
   do { \
@@ -487,17 +526,17 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
   /* Pointers to the file, program and section headers for the old and new
    * files.
    */
-  Elf32_Ehdr *old_file_h, *new_file_h;
-  Elf32_Phdr *old_program_h, *new_program_h;
-  Elf32_Shdr *old_section_h, *new_section_h;
+  ElfW(Ehdr) *old_file_h, *new_file_h;
+  ElfW(Phdr) *old_program_h, *new_program_h;
+  ElfW(Shdr) *old_section_h, *new_section_h;
 
   /* Point to the section name table in the old file */
   char *old_section_names;
 
-  Elf32_Addr old_bss_addr, new_bss_addr;
-  Elf32_Word old_bss_size, new_data2_size;
-  Elf32_Off  new_data2_offset;
-  Elf32_Addr new_data2_addr;
+  ElfW(Addr) old_bss_addr, new_bss_addr;
+  ElfW(Word) old_bss_size, new_data2_size;
+  ElfW(Off)  new_data2_offset;
+  ElfW(Addr) new_data2_addr;
 
   int n, nn, old_bss_index, old_data_index, new_data2_index;
   struct stat stat_buf;
@@ -524,9 +563,9 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
 
   /* Get pointers to headers & section names */
 
-  old_file_h = (Elf32_Ehdr *) old_base;
-  old_program_h = (Elf32_Phdr *) ((byte *) old_base + old_file_h->e_phoff);
-  old_section_h = (Elf32_Shdr *) ((byte *) old_base + old_file_h->e_shoff);
+  old_file_h = (ElfW(Ehdr) *) old_base;
+  old_program_h = (ElfW(Phdr) *) ((byte *) old_base + old_file_h->e_phoff);
+  old_section_h = (ElfW(Shdr) *) ((byte *) old_base + old_file_h->e_shoff);
   old_section_names = (char *) old_base
     + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
 
@@ -551,7 +590,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
   old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
   old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
 #if defined(emacs) || !defined(DEBUG)
-  new_bss_addr = (Elf32_Addr) sbrk (0);
+  new_bss_addr = (ElfW(Addr)) sbrk (0);
 #else
   new_bss_addr = old_bss_addr + old_bss_size + 0x1234;
 #endif
@@ -597,9 +636,9 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
   if (new_base == (caddr_t) -1)
     fatal ("Can't mmap (%s): errno %d\n", new_name, errno);
 
-  new_file_h = (Elf32_Ehdr *) new_base;
-  new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff);
-  new_section_h = (Elf32_Shdr *)
+  new_file_h = (ElfW(Ehdr) *) new_base;
+  new_program_h = (ElfW(Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
+  new_section_h = (ElfW(Shdr) *)
     ((byte *) new_base + old_file_h->e_shoff + new_data2_size);
 
   /* Make our new file, program and section headers as copies of the
@@ -731,8 +770,24 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
        {
          /* Any section that was original placed AFTER the bss
             section should now be off by NEW_DATA2_SIZE. */
-         if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
+#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)
+           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.  */
@@ -769,13 +824,34 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
       memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src,
              NEW_SECTION_H (nn).sh_size);
 
+#ifdef __alpha__
+      /* Update Alpha COFF symbol table: */
+      if (strcmp (old_section_names + OLD_SECTION_H (n).sh_name, ".mdebug")
+         == 0)
+       {
+         pHDRR symhdr = (pHDRR) (NEW_SECTION_H (nn).sh_offset + new_base);
+
+         symhdr->cbLineOffset += new_data2_size;
+         symhdr->cbDnOffset += new_data2_size;
+         symhdr->cbPdOffset += new_data2_size;
+         symhdr->cbSymOffset += new_data2_size;
+         symhdr->cbOptOffset += new_data2_size;
+         symhdr->cbAuxOffset += new_data2_size;
+         symhdr->cbSsOffset += new_data2_size;
+         symhdr->cbSsExtOffset += new_data2_size;
+         symhdr->cbFdOffset += new_data2_size;
+         symhdr->cbRfdOffset += new_data2_size;
+         symhdr->cbExtOffset += new_data2_size;
+       }
+#endif /* __alpha__ */
+
       /* If it is the symbol table, its st_shndx field needs to be patched.  */
       if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB
          || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)
        {
-         Elf32_Shdr *spt = &NEW_SECTION_H (nn);
+         ElfW(Shdr) *spt = &NEW_SECTION_H (nn);
          unsigned int num = spt->sh_size / spt->sh_entsize;
-         Elf32_Sym * sym = (Elf32_Sym *) (NEW_SECTION_H (nn).sh_offset +
+         ElfW(Sym) * sym = (ElfW(Sym) *) (NEW_SECTION_H (nn).sh_offset +
                                           new_base);
          for (; num--; sym++)
            {
@@ -793,7 +869,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
   for (n = new_file_h->e_shnum - 1; n; n--)
     {
       byte *symnames;
-      Elf32_Sym *symp, *symendp;
+      ElfW(Sym) *symp, *symendp;
 
       if (NEW_SECTION_H (n).sh_type != SHT_DYNSYM
          && NEW_SECTION_H (n).sh_type != SHT_SYMTAB)
@@ -801,8 +877,8 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
 
       symnames = ((byte *) new_base
                  + NEW_SECTION_H (NEW_SECTION_H (n).sh_link).sh_offset);
-      symp = (Elf32_Sym *) (NEW_SECTION_H (n).sh_offset + new_base);
-      symendp = (Elf32_Sym *) ((byte *)symp + NEW_SECTION_H (n).sh_size);
+      symp = (ElfW(Sym) *) (NEW_SECTION_H (n).sh_offset + new_base);
+      symendp = (ElfW(Sym) *) ((byte *)symp + NEW_SECTION_H (n).sh_size);
 
       for (; symp < symendp; symp ++)
        if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0
@@ -814,7 +890,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
      that it can undo relocations performed by the runtime linker.  */
   for (n = new_file_h->e_shnum - 1; n; n--)
     {
-      Elf32_Shdr section = NEW_SECTION_H (n);
+      ElfW(Shdr) section = NEW_SECTION_H (n);
       switch (section.sh_type) {
       default:
        break;
@@ -828,14 +904,21 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
            || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
                        ".data1"))
          {
-           Elf32_Addr offset = NEW_SECTION_H (nn).sh_addr -
+           ElfW(Addr) offset = NEW_SECTION_H (nn).sh_addr -
              NEW_SECTION_H (nn).sh_offset;
            caddr_t reloc = old_base + section.sh_offset, end;
            for (end = reloc + section.sh_size; reloc < end;
                 reloc += section.sh_entsize)
              {
-               Elf32_Addr addr = ((Elf32_Rel *) reloc)->r_offset - offset;
-               memcpy (new_base + addr, old_base + addr, 4);
+               ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset;
+#ifdef __alpha__
+               /* The Alpha ELF binutils currently have a bug that
+                  sometimes results in relocs that contain all
+                  zeroes.  Work around this for now...  */
+               if (((ElfW(Rel) *) reloc)->r_offset == 0)
+                   continue;
+#endif
+               memcpy (new_base + addr, old_base + addr, sizeof(ElfW(Addr)));
              }
          }
        break;