root/src/unexelf.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. entry_address
  2. unexec

     1 /* Copyright (C) 1985-1988, 1990, 1992, 1999-2023 Free Software
     2    Foundation, Inc.
     3 
     4 This file is part of GNU Emacs.
     5 
     6 GNU Emacs is free software: you can redistribute it and/or modify
     7 it under the terms of the GNU General Public License as published by
     8 the Free Software Foundation, either version 3 of the License, or (at
     9 your option) any later version.
    10 
    11 GNU Emacs is distributed in the hope that it will be useful,
    12 but WITHOUT ANY WARRANTY; without even the implied warranty of
    13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14 GNU General Public License for more details.
    15 
    16 You should have received a copy of the GNU General Public License
    17 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    18 
    19 /*
    20 In other words, you are welcome to use, share and improve this program.
    21 You are forbidden to forbid anyone else to use, share and improve
    22 what you give them.   Help stamp out software-hoarding!  */
    23 
    24 
    25 /*
    26  * unexec.c - Convert a running program into an a.out file.
    27  *
    28  * Author:      Spencer W. Thomas
    29  *              Computer Science Dept.
    30  *              University of Utah
    31  * Date:        Tue Mar  2 1982
    32  * Modified heavily since then.
    33  *
    34  * Synopsis:
    35  *      unexec (const char *new_name, const char *old_name);
    36  *
    37  * Takes a snapshot of the program and makes an a.out format file in the
    38  * file named by the string argument new_name.
    39  * If old_name is non-NULL, the symbol table will be taken from the given file.
    40  * On some machines, an existing old_name file is required.
    41  *
    42  */
    43 
    44 /* We do not use mmap because that fails with NFS.
    45    Instead we read the whole file, modify it, and write it out.  */
    46 
    47 #include <config.h>
    48 #include "unexec.h"
    49 #include "lisp.h"
    50 
    51 #include <errno.h>
    52 #include <fcntl.h>
    53 #include <limits.h>
    54 #include <memory.h>
    55 #include <stdint.h>
    56 #include <stdio.h>
    57 #include <sys/stat.h>
    58 #include <sys/types.h>
    59 #include <unistd.h>
    60 
    61 #ifdef __QNX__
    62 # include <sys/elf.h>
    63 #elif !defined __NetBSD__ && !defined __OpenBSD__
    64 # include <elf.h>
    65 #endif
    66 #include <sys/mman.h>
    67 #if defined (_SYSTYPE_SYSV)
    68 #include <sys/elf_mips.h>
    69 #include <sym.h>
    70 #endif /* _SYSTYPE_SYSV */
    71 
    72 #ifndef MAP_ANON
    73 #ifdef MAP_ANONYMOUS
    74 #define MAP_ANON MAP_ANONYMOUS
    75 #else
    76 #define MAP_ANON 0
    77 #endif
    78 #endif
    79 
    80 #ifndef MAP_FAILED
    81 #define MAP_FAILED ((void *) -1)
    82 #endif
    83 
    84 #if defined (__alpha__) && !defined (__NetBSD__) && !defined (__OpenBSD__)
    85 /* Declare COFF debugging symbol table.  This used to be in
    86    /usr/include/sym.h, but this file is no longer included in Red Hat
    87    5.0 and presumably in any other glibc 2.x based distribution.  */
    88 typedef struct {
    89         short magic;
    90         short vstamp;
    91         int ilineMax;
    92         int idnMax;
    93         int ipdMax;
    94         int isymMax;
    95         int ioptMax;
    96         int iauxMax;
    97         int issMax;
    98         int issExtMax;
    99         int ifdMax;
   100         int crfd;
   101         int iextMax;
   102         long cbLine;
   103         long cbLineOffset;
   104         long cbDnOffset;
   105         long cbPdOffset;
   106         long cbSymOffset;
   107         long cbOptOffset;
   108         long cbAuxOffset;
   109         long cbSsOffset;
   110         long cbSsExtOffset;
   111         long cbFdOffset;
   112         long cbRfdOffset;
   113         long cbExtOffset;
   114 } HDRR, *pHDRR;
   115 #define cbHDRR sizeof (HDRR)
   116 #define hdrNil ((pHDRR)0)
   117 #endif
   118 
   119 #ifdef __NetBSD__
   120 /*
   121  * NetBSD does not have normal-looking user-land ELF support.
   122  */
   123 # if defined __alpha__ || defined __sparc_v9__ || defined _LP64
   124 #  define ELFSIZE       64
   125 # else
   126 #  define ELFSIZE       32
   127 # endif
   128 # include <sys/exec_elf.h>
   129 
   130 # ifndef PT_LOAD
   131 #  define PT_LOAD       Elf_pt_load
   132 #  if 0                                         /* was in pkgsrc patches for 20.7 */
   133 #   define SHT_PROGBITS Elf_sht_progbits
   134 #  endif
   135 #  define SHT_SYMTAB    Elf_sht_symtab
   136 #  define SHT_DYNSYM    Elf_sht_dynsym
   137 #  define SHT_NULL      Elf_sht_null
   138 #  define SHT_NOBITS    Elf_sht_nobits
   139 #  define SHT_REL       Elf_sht_rel
   140 #  define SHT_RELA      Elf_sht_rela
   141 
   142 #  define SHN_UNDEF     Elf_eshn_undefined
   143 #  define SHN_ABS       Elf_eshn_absolute
   144 #  define SHN_COMMON    Elf_eshn_common
   145 # endif /* !PT_LOAD */
   146 
   147 # ifdef __alpha__
   148 #  include <sys/exec_ecoff.h>
   149 #  define HDRR          struct ecoff_symhdr
   150 #  define pHDRR         HDRR *
   151 # endif /* __alpha__ */
   152 
   153 #ifdef __mips__                 /* was in pkgsrc patches for 20.7 */
   154 # define SHT_MIPS_DEBUG DT_MIPS_FLAGS
   155 # define HDRR           struct Elf_Shdr
   156 #endif /* __mips__ */
   157 #endif /* __NetBSD__ */
   158 
   159 #ifdef __OpenBSD__
   160 # include <sys/exec_elf.h>
   161 #endif
   162 
   163 #if __GNU_LIBRARY__ - 0 >= 6
   164 # include <link.h>      /* get ElfW etc */
   165 #endif
   166 
   167 #ifndef ElfW
   168 # define ElfBitsW(bits, type) Elf##bits##_##type
   169 # ifndef ELFSIZE
   170 #  ifdef _LP64
   171 #   define ELFSIZE 64
   172 #  else
   173 #   define ELFSIZE 32
   174 #  endif
   175 # endif
   176   /* This macro expands `bits' before invoking ElfBitsW.  */
   177 # define ElfExpandBitsW(bits, type) ElfBitsW (bits, type)
   178 # define ElfW(type) ElfExpandBitsW (ELFSIZE, type)
   179 #endif
   180 
   181 /* The code often converts ElfW (Half) values like e_shentsize to ptrdiff_t;
   182    check that this doesn't lose information.  */
   183 #include <intprops.h>
   184 #include <verify.h>
   185 verify ((! TYPE_SIGNED (ElfW (Half))
   186          || PTRDIFF_MIN <= TYPE_MINIMUM (ElfW (Half)))
   187         && TYPE_MAXIMUM (ElfW (Half)) <= PTRDIFF_MAX);
   188 
   189 #ifdef UNEXELF_DEBUG
   190 # define DEBUG_LOG(expr) fprintf (stderr, #expr " 0x%"PRIxMAX"\n", \
   191                                   (uintmax_t) (expr))
   192 #endif
   193 
   194 /* Get the address of a particular section or program header entry,
   195  * accounting for the size of the entries.
   196  */
   197 
   198 static void *
   199 entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize)
   200 {
   201   char *h = section_h;
   202   return h + idx * entsize;
   203 }
   204 
   205 #define OLD_SECTION_H(n) \
   206   (*(ElfW (Shdr) *) entry_address (old_section_h, n, old_file_h->e_shentsize))
   207 #define NEW_SECTION_H(n) \
   208   (*(ElfW (Shdr) *) entry_address (new_section_h, n, new_file_h->e_shentsize))
   209 #define OLD_PROGRAM_H(n) \
   210   (*(ElfW (Phdr) *) entry_address (old_program_h, n, old_file_h->e_phentsize))
   211 
   212 typedef unsigned char byte;
   213 
   214 /* ****************************************************************
   215  * unexec
   216  *
   217  * driving logic.
   218  *
   219  * In ELF, this works by replacing the old bss SHT_NOBITS section with
   220  * a new, larger, SHT_PROGBITS section.
   221  *
   222  */
   223 void
   224 unexec (const char *new_name, const char *old_name)
   225 {
   226   int new_file, old_file;
   227   off_t new_file_size;
   228 
   229   /* Pointers to the base of the image of the two files.  */
   230   caddr_t old_base, new_base;
   231 
   232 #if MAP_ANON == 0
   233   int mmap_fd;
   234 #else
   235 # define mmap_fd -1
   236 #endif
   237 
   238   /* Pointers to the file, program and section headers for the old and
   239      new files.  */
   240   ElfW (Ehdr) *old_file_h, *new_file_h;
   241   ElfW (Phdr) *old_program_h, *new_program_h;
   242   ElfW (Shdr) *old_section_h, *new_section_h;
   243 
   244   /* Point to the section name table.  */
   245   char *old_section_names, *new_section_names;
   246 
   247   ElfW (Phdr) *old_bss_seg, *new_bss_seg;
   248   ElfW (Addr) old_bss_addr, new_bss_addr;
   249   ElfW (Word) old_bss_size, bss_size_growth, new_data2_size;
   250   ElfW (Off) old_bss_offset, new_data2_offset;
   251 
   252   ptrdiff_t n;
   253   ptrdiff_t old_bss_index;
   254   struct stat stat_buf;
   255   off_t old_file_size;
   256 
   257   /* Open the old file, allocate a buffer of the right size, and read
   258      in the file contents.  */
   259 
   260   old_file = emacs_open (old_name, O_RDONLY, 0);
   261 
   262   if (old_file < 0)
   263     fatal ("Can't open %s for reading: %s", old_name, strerror (errno));
   264 
   265   if (fstat (old_file, &stat_buf) != 0)
   266     fatal ("Can't fstat (%s): %s", old_name, strerror (errno));
   267 
   268 #if MAP_ANON == 0
   269   mmap_fd = emacs_open ("/dev/zero", O_RDONLY, 0);
   270   if (mmap_fd < 0)
   271     fatal ("Can't open /dev/zero for reading: %s", strerror (errno));
   272 #endif
   273 
   274   /* We cannot use malloc here because that may use sbrk.  If it does,
   275      we'd dump our temporary buffers with Emacs, and we'd have to be
   276      extra careful to use the correct value of sbrk(0) after
   277      allocating all buffers in the code below, which we aren't.  */
   278   old_file_size = stat_buf.st_size;
   279   if (! (0 <= old_file_size && old_file_size <= SIZE_MAX))
   280     fatal ("File size out of range");
   281   old_base = mmap (NULL, old_file_size, PROT_READ | PROT_WRITE,
   282                    MAP_ANON | MAP_PRIVATE, mmap_fd, 0);
   283   if (old_base == MAP_FAILED)
   284     fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
   285 
   286   if (read (old_file, old_base, old_file_size) != old_file_size)
   287     fatal ("Didn't read all of %s: %s", old_name, strerror (errno));
   288 
   289   /* Get pointers to headers & section names */
   290 
   291   old_file_h = (ElfW (Ehdr) *) old_base;
   292   old_program_h = (ElfW (Phdr) *) ((byte *) old_base + old_file_h->e_phoff);
   293   old_section_h = (ElfW (Shdr) *) ((byte *) old_base + old_file_h->e_shoff);
   294   old_section_names = (char *) old_base
   295     + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
   296 
   297   /* Find the PT_LOAD header covering the highest address.  This
   298      segment will be where bss sections are located, past p_filesz.  */
   299   old_bss_seg = 0;
   300   for (n = old_file_h->e_phnum; --n >= 0; )
   301     {
   302       ElfW (Phdr) *seg = &OLD_PROGRAM_H (n);
   303       if (seg->p_type == PT_LOAD
   304           && (old_bss_seg == 0
   305               || seg->p_vaddr > old_bss_seg->p_vaddr))
   306         old_bss_seg = seg;
   307     }
   308   eassume (old_bss_seg);
   309 
   310   /* Note that old_bss_addr may be lower than the first bss section
   311      address, since the section may need aligning.  */
   312   old_bss_addr = old_bss_seg->p_vaddr + old_bss_seg->p_filesz;
   313   old_bss_offset = old_bss_seg->p_offset + old_bss_seg->p_filesz;
   314   old_bss_size = old_bss_seg->p_memsz - old_bss_seg->p_filesz;
   315 
   316   /* Find the last bss style section in the bss segment range.  */
   317   old_bss_index = -1;
   318   for (n = old_file_h->e_shnum; --n > 0; )
   319     {
   320       ElfW (Shdr) *shdr = &OLD_SECTION_H (n);
   321       if (shdr->sh_type == SHT_NOBITS
   322           && shdr->sh_addr >= old_bss_addr
   323           && shdr->sh_addr + shdr->sh_size <= old_bss_addr + old_bss_size
   324           && (old_bss_index == -1
   325               || OLD_SECTION_H (old_bss_index).sh_addr < shdr->sh_addr))
   326         old_bss_index = n;
   327     }
   328 
   329   if (old_bss_index == -1)
   330     fatal ("no bss section found");
   331 
   332   void *no_break = (void *) (intptr_t) -1;
   333   void *new_break = no_break;
   334 #ifdef HAVE_SBRK
   335   new_break = sbrk (0);
   336 #endif
   337   if (new_break == no_break)
   338     new_break = (byte *) old_bss_addr + old_bss_size;
   339   new_bss_addr = (ElfW (Addr)) new_break;
   340   bss_size_growth = new_bss_addr - old_bss_addr;
   341   new_data2_size = bss_size_growth;
   342   new_data2_size += alignof (ElfW (Shdr)) - 1;
   343   new_data2_size -= new_data2_size % alignof (ElfW (Shdr));
   344 
   345   new_data2_offset = old_bss_offset;
   346 
   347 #ifdef UNEXELF_DEBUG
   348   fprintf (stderr, "old_bss_index %td\n", old_bss_index);
   349   DEBUG_LOG (old_bss_addr);
   350   DEBUG_LOG (old_bss_size);
   351   DEBUG_LOG (old_bss_offset);
   352   DEBUG_LOG (new_bss_addr);
   353   DEBUG_LOG (new_data2_size);
   354   DEBUG_LOG (new_data2_offset);
   355 #endif
   356 
   357   if (new_bss_addr < old_bss_addr + old_bss_size)
   358     fatal (".bss shrank when undumping");
   359 
   360   /* Set the output file to the right size.  Allocate a buffer to hold
   361      the image of the new file.  Set pointers to various interesting
   362      objects.  */
   363 
   364   new_file = emacs_open (new_name, O_RDWR | O_CREAT, 0777);
   365   if (new_file < 0)
   366     fatal ("Can't creat (%s): %s", new_name, strerror (errno));
   367 
   368   new_file_size = old_file_size + new_data2_size;
   369 
   370   if (ftruncate (new_file, new_file_size))
   371     fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno));
   372 
   373   new_base = mmap (NULL, new_file_size, PROT_READ | PROT_WRITE,
   374                    MAP_ANON | MAP_PRIVATE, mmap_fd, 0);
   375   if (new_base == MAP_FAILED)
   376     fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
   377 
   378   /* Make our new file, program and section headers as copies of the
   379      originals.  */
   380 
   381   new_file_h = (ElfW (Ehdr) *) new_base;
   382   memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
   383 
   384   /* Fix up file header.  Section header is further away now.  */
   385 
   386   if (new_file_h->e_shoff >= old_bss_offset)
   387     new_file_h->e_shoff += new_data2_size;
   388 
   389   new_program_h = (ElfW (Phdr) *) ((byte *) new_base + new_file_h->e_phoff);
   390   new_section_h = (ElfW (Shdr) *) ((byte *) new_base + new_file_h->e_shoff);
   391 
   392   memcpy (new_program_h, old_program_h,
   393           old_file_h->e_phnum * old_file_h->e_phentsize);
   394   memcpy (new_section_h, old_section_h,
   395           old_file_h->e_shnum * old_file_h->e_shentsize);
   396 
   397 #ifdef UNEXELF_DEBUG
   398   DEBUG_LOG (old_file_h->e_shoff);
   399   fprintf (stderr, "Old section count %td\n", (ptrdiff_t) old_file_h->e_shnum);
   400   DEBUG_LOG (new_file_h->e_shoff);
   401   fprintf (stderr, "New section count %td\n", (ptrdiff_t) new_file_h->e_shnum);
   402 #endif
   403 
   404   /* Fix up program header.  Extend the writable data segment so
   405      that the bss area is covered too.  */
   406 
   407   new_bss_seg = new_program_h + (old_bss_seg - old_program_h);
   408   new_bss_seg->p_filesz = new_bss_addr - new_bss_seg->p_vaddr;
   409   new_bss_seg->p_memsz = new_bss_seg->p_filesz;
   410 
   411   /* Copy over what we have in memory now for the bss area. */
   412   memcpy (new_base + new_data2_offset, (caddr_t) old_bss_addr,
   413           bss_size_growth);
   414 
   415   /* Walk through all section headers, copying data and updating.  */
   416   for (n = 1; n < old_file_h->e_shnum; n++)
   417     {
   418       caddr_t src;
   419       ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
   420       ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
   421 
   422       if (new_shdr->sh_type == SHT_NOBITS
   423           && new_shdr->sh_addr >= old_bss_addr
   424           && (new_shdr->sh_addr + new_shdr->sh_size
   425               <= old_bss_addr + old_bss_size))
   426         {
   427           /* This section now has file backing.  */
   428           new_shdr->sh_type = SHT_PROGBITS;
   429 
   430           /* SHT_NOBITS sections do not need a valid sh_offset, so it
   431              might be incorrect.  Write the correct value.  */
   432           new_shdr->sh_offset = (new_shdr->sh_addr - new_bss_seg->p_vaddr
   433                                  + new_bss_seg->p_offset);
   434 
   435           /* If this is was a SHT_NOBITS .plt section, then it is
   436              probably a PowerPC PLT.  If it is PowerPC64 ELFv1 then
   437              glibc ld.so doesn't initialize the toc pointer word.  A
   438              non-zero toc pointer word can defeat Power7 thread safety
   439              during lazy update of a PLT entry.  This only matters if
   440              emacs becomes multi-threaded.  */
   441           if (strcmp (old_section_names + new_shdr->sh_name, ".plt") == 0)
   442             memset (new_shdr->sh_offset + new_base, 0, new_shdr->sh_size);
   443 
   444           /* Extend the size of the last bss section to cover dumped
   445              data.  */
   446           if (n == old_bss_index)
   447             new_shdr->sh_size = new_bss_addr - new_shdr->sh_addr;
   448 
   449           /* We have already copied this section from the current
   450              process.  */
   451           continue;
   452         }
   453 
   454       /* Any section that was originally placed after the .bss
   455          section should now be offset by NEW_DATA2_SIZE.  */
   456       if (new_shdr->sh_offset >= old_bss_offset)
   457         new_shdr->sh_offset += new_data2_size;
   458 
   459       /* Now, start to copy the content of sections.  */
   460       if (new_shdr->sh_type == SHT_NULL
   461           || new_shdr->sh_type == SHT_NOBITS)
   462         continue;
   463 
   464       /* Some sections are copied from the current process instead of
   465          the old file.  */
   466       if (!strcmp (old_section_names + new_shdr->sh_name, ".data")
   467           || !strcmp (old_section_names + new_shdr->sh_name, ".sdata")
   468           || !strcmp (old_section_names + new_shdr->sh_name, ".lit4")
   469           || !strcmp (old_section_names + new_shdr->sh_name, ".lit8")
   470           || !strcmp (old_section_names + new_shdr->sh_name, ".sdata1")
   471           || !strcmp (old_section_names + new_shdr->sh_name, ".data1"))
   472         src = (caddr_t) old_shdr->sh_addr;
   473       else
   474         src = old_base + old_shdr->sh_offset;
   475 
   476       memcpy (new_shdr->sh_offset + new_base, src, new_shdr->sh_size);
   477 
   478 #if (defined __alpha__ && !defined __OpenBSD__) || defined _SYSTYPE_SYSV
   479       /* Update Alpha and MIPS COFF debug symbol table.  */
   480       if (strcmp (old_section_names + new_shdr->sh_name, ".mdebug") == 0
   481           && new_shdr->sh_offset - old_shdr->sh_offset != 0
   482 #if defined _SYSTYPE_SYSV
   483           && new_shdr->sh_type == SHT_MIPS_DEBUG
   484 #endif
   485           )
   486         {
   487           ptrdiff_t diff = new_shdr->sh_offset - old_shdr->sh_offset;
   488           HDRR *phdr = (HDRR *) (new_shdr->sh_offset + new_base);
   489 
   490           phdr->cbLineOffset += diff;
   491           phdr->cbDnOffset += diff;
   492           phdr->cbPdOffset += diff;
   493           phdr->cbSymOffset += diff;
   494           phdr->cbOptOffset += diff;
   495           phdr->cbAuxOffset += diff;
   496           phdr->cbSsOffset += diff;
   497           phdr->cbSsExtOffset += diff;
   498           phdr->cbFdOffset += diff;
   499           phdr->cbRfdOffset += diff;
   500           phdr->cbExtOffset += diff;
   501         }
   502 #endif /* __alpha__ || _SYSTYPE_SYSV */
   503     }
   504 
   505   /* Update the symbol values of _edata and _end.  */
   506   for (n = new_file_h->e_shnum; 0 < --n; )
   507     {
   508       byte *symnames;
   509       ElfW (Sym) *symp, *symendp;
   510       ElfW (Shdr) *sym_shdr = &NEW_SECTION_H (n);
   511 
   512       if (sym_shdr->sh_type != SHT_DYNSYM
   513           && sym_shdr->sh_type != SHT_SYMTAB)
   514         continue;
   515 
   516       symnames = ((byte *) new_base
   517                   + NEW_SECTION_H (sym_shdr->sh_link).sh_offset);
   518       symp = (ElfW (Sym) *) (sym_shdr->sh_offset + new_base);
   519       symendp = (ElfW (Sym) *) ((byte *) symp + sym_shdr->sh_size);
   520 
   521       for (; symp < symendp; symp ++)
   522         {
   523           if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0
   524               || strcmp ((char *) (symnames + symp->st_name), "end") == 0
   525               || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0
   526               || strcmp ((char *) (symnames + symp->st_name), "edata") == 0)
   527             memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr));
   528 
   529           /* Strictly speaking, #ifdef below is not necessary.  But we
   530              keep it to indicate that this kind of change may also be
   531              necessary for other unexecs to support GNUstep.  */
   532 #ifdef NS_IMPL_GNUSTEP
   533           /* ObjC runtime modifies the values of some data structures
   534              such as classes and selectors in the .data section after
   535              loading.  As the dump process copies the .data section
   536              from the current process, that causes problems when the
   537              modified classes are reinitialized in the dumped
   538              executable.  We copy such data from the old file, not
   539              from the current process.  */
   540           if (strncmp ((char *) (symnames + symp->st_name),
   541                        "_OBJC_", sizeof ("_OBJC_") - 1) == 0)
   542             {
   543               ElfW (Shdr) *new_shdr = &NEW_SECTION_H (symp->st_shndx);
   544               if (new_shdr->sh_type != SHT_NOBITS)
   545                 {
   546                   ElfW (Shdr) *old_shdr = &OLD_SECTION_H (symp->st_shndx);
   547                   ptrdiff_t reladdr = symp->st_value - new_shdr->sh_addr;
   548                   ptrdiff_t newoff = reladdr + new_shdr->sh_offset;
   549 
   550                   if (old_shdr->sh_type == SHT_NOBITS)
   551                     memset (new_base + newoff, 0, symp->st_size);
   552                   else
   553                     {
   554                       ptrdiff_t oldoff = reladdr + old_shdr->sh_offset;
   555                       memcpy (new_base + newoff, old_base + oldoff,
   556                               symp->st_size);
   557                     }
   558                 }
   559             }
   560 #endif
   561         }
   562     }
   563 
   564   /* Modify the names of sections we changed from SHT_NOBITS to
   565      SHT_PROGBITS.  This is really just cosmetic, but some tools that
   566      (wrongly) operate on section names rather than types might be
   567      confused by a SHT_PROGBITS .bss section.  */
   568   new_section_names = ((char *) new_base
   569                        + NEW_SECTION_H (new_file_h->e_shstrndx).sh_offset);
   570   for (n = new_file_h->e_shnum; 0 < --n; )
   571     {
   572       ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
   573       ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
   574 
   575       /* Replace the leading '.' with ','.  When .shstrtab is string
   576          merged this will rename both .bss and .rela.bss to ,bss and
   577          .rela,bss.  */
   578       if (old_shdr->sh_type == SHT_NOBITS
   579           && new_shdr->sh_type == SHT_PROGBITS)
   580         *(new_section_names + new_shdr->sh_name) = ',';
   581     }
   582 
   583   /* This loop seeks out relocation sections for the data section, so
   584      that it can undo relocations performed by the runtime loader.
   585 
   586      The following approach does not work on x86 platforms that use
   587      the GNU Gold linker, which can generate .rel.dyn relocation
   588      sections containing R_386_32 entries that the following code does
   589      not grok.  Emacs works around this problem by avoiding C
   590      constructs that generate such entries, which is horrible hack.
   591 
   592      FIXME: Presumably more problems like this will crop up as linkers
   593      get fancier.  We really need to stop assuming that Emacs can grok
   594      arbitrary linker output.  See Bug#27248.  */
   595   for (n = new_file_h->e_shnum; 0 < --n; )
   596     {
   597       ElfW (Shdr) *rel_shdr = &NEW_SECTION_H (n);
   598       ElfW (Shdr) *shdr;
   599 
   600       switch (rel_shdr->sh_type)
   601         {
   602         default:
   603           break;
   604         case SHT_REL:
   605         case SHT_RELA:
   606           /* This code handles two different size structs, but there should
   607              be no harm in that provided that r_offset is always the first
   608              member.  */
   609           shdr = &NEW_SECTION_H (rel_shdr->sh_info);
   610           if (!strcmp (old_section_names + shdr->sh_name, ".data")
   611               || !strcmp (old_section_names + shdr->sh_name, ".sdata")
   612               || !strcmp (old_section_names + shdr->sh_name, ".lit4")
   613               || !strcmp (old_section_names + shdr->sh_name, ".lit8")
   614               || !strcmp (old_section_names + shdr->sh_name, ".sdata1")
   615               || !strcmp (old_section_names + shdr->sh_name, ".data1"))
   616             {
   617               ElfW (Addr) offset = shdr->sh_addr - shdr->sh_offset;
   618               caddr_t reloc = old_base + rel_shdr->sh_offset, end;
   619               for (end = reloc + rel_shdr->sh_size;
   620                    reloc < end;
   621                    reloc += rel_shdr->sh_entsize)
   622                 {
   623                   ElfW (Addr) addr = ((ElfW (Rel) *) reloc)->r_offset - offset;
   624                   /* Ignore R_*_NONE relocs.  */
   625                   if (((ElfW (Rel) *) reloc)->r_offset == 0)
   626                     continue;
   627                   /* Assume reloc applies to a word.
   628                      ??? This is not always true, eg. TLS module/index
   629                      pair in .got which occupies two words.  */
   630                   memcpy (new_base + addr, old_base + addr,
   631                           sizeof (ElfW (Addr)));
   632                 }
   633             }
   634           break;
   635         }
   636     }
   637 
   638   /* Write out new_file, and free the buffers.  */
   639 
   640   if (write (new_file, new_base, new_file_size) != new_file_size)
   641     fatal ("Didn't write %lu bytes to %s: %s",
   642            (unsigned long) new_file_size, new_name, strerror (errno));
   643   munmap (old_base, old_file_size);
   644   munmap (new_base, new_file_size);
   645 
   646   /* Close the files and make the new file executable.  */
   647 
   648 #if MAP_ANON == 0
   649   emacs_close (mmap_fd);
   650 #endif
   651 
   652   if (emacs_close (old_file) != 0)
   653     fatal ("Can't close (%s): %s", old_name, strerror (errno));
   654 
   655   if (emacs_close (new_file) != 0)
   656     fatal ("Can't close (%s): %s", new_name, strerror (errno));
   657 }

/* [<][>][^][v][top][bottom][index][help] */