Blame SOURCES/emacs-0009-ELF-unexec-Don-t-insert-a-new-section.patch

1db854
From 76b336e1655c8eacaf17a362c3c59d6103357c09 Mon Sep 17 00:00:00 2001
1db854
From: Alan Modra <amodra@gmail.com>
1db854
Date: Sun, 8 Nov 2015 09:29:00 -0800
1db854
Subject: [PATCH 09/11] ELF unexec: Don't insert a new section
1db854
1db854
Reuse the .bss section instead, making it SHT_PROGBITS.  This way we
1db854
don't need to mess with symbol st_shndx, or section sh_link and
1db854
sh_info.
1db854
1db854
This does lead to eu-elflint complaints about symbols defined in .bss
1db854
with a needed version, because normally it is undefined symbols that
1db854
have needed versions;  Defined symbols have version definitions.
1db854
The exception is symbols defined by the linker in .dynbss for
1db854
variables copied from a shared library in order to avoid text
1db854
relocations, with copy relocs to copy their initial values from the
1db854
shared library.  These symbols are both defined and have needed
1db854
versions, and eu-elflink only expects to see them in SHT_NOBITS
1db854
sections.  Of course there is no real problem with having such symbols
1db854
in SHT_PROGBITS sections.  glibc ld.so handles them fine.
1db854
1db854
* unexelf.c: Delete outdated comments.
1db854
(PATCH_INDEX): Delete.
1db854
(find_section): Delete.
1db854
(unexec): Don't add a new section.  Instead reuse the last bss
1db854
section, extending it to cover dumped data.  Make bss sections
1db854
SHT_PROGBITS.  Remove all patching of sh_link, sh_info and
1db854
st_shndx.  Rename bss sections.
1db854
---
1db854
 src/unexelf.c | 524 ++++++----------------------------------------------------
1db854
 1 file changed, 50 insertions(+), 474 deletions(-)
1db854
1db854
diff --git a/src/unexelf.c b/src/unexelf.c
1db854
index 4e9c50d..85ed934 100644
1db854
--- a/src/unexelf.c
1db854
+++ b/src/unexelf.c
1db854
@@ -40,347 +40,6 @@ what you give them.   Help stamp out software-hoarding!  */
1db854
  * On some machines, an existing old_name file is required.
1db854
  *
1db854
  */
1db854
-
1db854
-/* Even more heavily modified by james@bigtex.cactus.org of Dell Computer Co.
1db854
- * ELF support added.
1db854
- *
1db854
- * Basic theory: the data space of the running process needs to be
1db854
- * dumped to the output file.  Normally we would just enlarge the size
1db854
- * of .data, scooting everything down.  But we can't do that in ELF,
1db854
- * because there is often something between the .data space and the
1db854
- * .bss space.
1db854
- *
1db854
- * In the temacs dump below, notice that the Global Offset Table
1db854
- * (.got) and the Dynamic link data (.dynamic) come between .data1 and
1db854
- * .bss.  It does not work to overlap .data with these fields.
1db854
- *
1db854
- * The solution is to create a new .data segment.  This segment is
1db854
- * filled with data from the current process.  Since the contents of
1db854
- * various sections refer to sections by index, the new .data segment
1db854
- * is made the last in the table to avoid changing any existing index.
1db854
-
1db854
- * This is an example of how the section headers are changed.  "Addr"
1db854
- * is a process virtual address.  "Offset" is a file offset.
1db854
-
1db854
-raid:/nfs/raid/src/dist-18.56/src> dump -h temacs
1db854
-
1db854
-temacs:
1db854
-
1db854
-           **** SECTION HEADER TABLE ****
1db854
- [No]    Type    Flags   Addr         Offset       Size          Name
1db854
-         Link    Info    Adralgn      Entsize
1db854
-
1db854
- [1]     1       2       0x80480d4    0xd4         0x13          .interp
1db854
-         0       0       0x1          0
1db854
-
1db854
- [2]     5       2       0x80480e8    0xe8         0x388         .hash
1db854
-         3       0       0x4          0x4
1db854
-
1db854
- [3]     11      2       0x8048470    0x470        0x7f0         .dynsym
1db854
-         4       1       0x4          0x10
1db854
-
1db854
- [4]     3       2       0x8048c60    0xc60        0x3ad         .dynstr
1db854
-         0       0       0x1          0
1db854
-
1db854
- [5]     9       2       0x8049010    0x1010       0x338         .rel.plt
1db854
-         3       7       0x4          0x8
1db854
-
1db854
- [6]     1       6       0x8049348    0x1348       0x3           .init
1db854
-         0       0       0x4          0
1db854
-
1db854
- [7]     1       6       0x804934c    0x134c       0x680         .plt
1db854
-         0       0       0x4          0x4
1db854
-
1db854
- [8]     1       6       0x80499cc    0x19cc       0x3c56f       .text
1db854
-         0       0       0x4          0
1db854
-
1db854
- [9]     1       6       0x8085f3c    0x3df3c      0x3           .fini
1db854
-         0       0       0x4          0
1db854
-
1db854
- [10]    1       2       0x8085f40    0x3df40      0x69c         .rodata
1db854
-         0       0       0x4          0
1db854
-
1db854
- [11]    1       2       0x80865dc    0x3e5dc      0xd51         .rodata1
1db854
-         0       0       0x4          0
1db854
-
1db854
- [12]    1       3       0x8088330    0x3f330      0x20afc       .data
1db854
-         0       0       0x4          0
1db854
-
1db854
- [13]    1       3       0x80a8e2c    0x5fe2c      0x89d         .data1
1db854
-         0       0       0x4          0
1db854
-
1db854
- [14]    1       3       0x80a96cc    0x606cc      0x1a8         .got
1db854
-         0       0       0x4          0x4
1db854
-
1db854
- [15]    6       3       0x80a9874    0x60874      0x80          .dynamic
1db854
-         4       0       0x4          0x8
1db854
-
1db854
- [16]    8       3       0x80a98f4    0x608f4      0x449c        .bss
1db854
-         0       0       0x4          0
1db854
-
1db854
- [17]    2       0       0            0x608f4      0x9b90        .symtab
1db854
-         18      371     0x4          0x10
1db854
-
1db854
- [18]    3       0       0            0x6a484      0x8526        .strtab
1db854
-         0       0       0x1          0
1db854
-
1db854
- [19]    3       0       0            0x729aa      0x93          .shstrtab
1db854
-         0       0       0x1          0
1db854
-
1db854
- [20]    1       0       0            0x72a3d      0x68b7        .comment
1db854
-         0       0       0x1          0
1db854
-
1db854
- raid:/nfs/raid/src/dist-18.56/src> dump -h xemacs
1db854
-
1db854
- xemacs:
1db854
-
1db854
-            **** SECTION HEADER TABLE ****
1db854
- [No]    Type    Flags   Addr         Offset       Size          Name
1db854
-         Link    Info    Adralgn      Entsize
1db854
-
1db854
- [1]     1       2       0x80480d4    0xd4         0x13          .interp
1db854
-         0       0       0x1          0
1db854
-
1db854
- [2]     5       2       0x80480e8    0xe8         0x388         .hash
1db854
-         3       0       0x4          0x4
1db854
-
1db854
- [3]     11      2       0x8048470    0x470        0x7f0         .dynsym
1db854
-         4       1       0x4          0x10
1db854
-
1db854
- [4]     3       2       0x8048c60    0xc60        0x3ad         .dynstr
1db854
-         0       0       0x1          0
1db854
-
1db854
- [5]     9       2       0x8049010    0x1010       0x338         .rel.plt
1db854
-         3       7       0x4          0x8
1db854
-
1db854
- [6]     1       6       0x8049348    0x1348       0x3           .init
1db854
-         0       0       0x4          0
1db854
-
1db854
- [7]     1       6       0x804934c    0x134c       0x680         .plt
1db854
-         0       0       0x4          0x4
1db854
-
1db854
- [8]     1       6       0x80499cc    0x19cc       0x3c56f       .text
1db854
-         0       0       0x4          0
1db854
-
1db854
- [9]     1       6       0x8085f3c    0x3df3c      0x3           .fini
1db854
-         0       0       0x4          0
1db854
-
1db854
- [10]    1       2       0x8085f40    0x3df40      0x69c         .rodata
1db854
-         0       0       0x4          0
1db854
-
1db854
- [11]    1       2       0x80865dc    0x3e5dc      0xd51         .rodata1
1db854
-         0       0       0x4          0
1db854
-
1db854
- [12]    1       3       0x8088330    0x3f330      0x20afc       .data
1db854
-         0       0       0x4          0
1db854
-
1db854
- [13]    1       3       0x80a8e2c    0x5fe2c      0x89d         .data1
1db854
-         0       0       0x4          0
1db854
-
1db854
- [14]    1       3       0x80a96cc    0x606cc      0x1a8         .got
1db854
-         0       0       0x4          0x4
1db854
-
1db854
- [15]    6       3       0x80a9874    0x60874      0x80          .dynamic
1db854
-         4       0       0x4          0x8
1db854
-
1db854
- [16]    8       3       0x80c6800    0x7d800      0             .bss
1db854
-         0       0       0x4          0
1db854
-
1db854
- [17]    2       0       0            0x7d800      0x9b90        .symtab
1db854
-         18      371     0x4          0x10
1db854
-
1db854
- [18]    3       0       0            0x87390      0x8526        .strtab
1db854
-         0       0       0x1          0
1db854
-
1db854
- [19]    3       0       0            0x8f8b6      0x93          .shstrtab
1db854
-         0       0       0x1          0
1db854
-
1db854
- [20]    1       0       0            0x8f949      0x68b7        .comment
1db854
-         0       0       0x1          0
1db854
-
1db854
- [21]    1       3       0x80a98f4    0x608f4      0x1cf0c       .data
1db854
-         0       0       0x4          0
1db854
-
1db854
-  * This is an example of how the file header is changed.  "Shoff" is
1db854
-  * the section header offset within the file.  Since that table is
1db854
-  * after the new .data section, it is moved.  "Shnum" is the number of
1db854
-  * sections, which we increment.
1db854
-  *
1db854
-  * "Phoff" is the file offset to the program header.  "Phentsize" and
1db854
-  * "Shentsz" are the program and section header entries sizes respectively.
1db854
-  * These can be larger than the apparent struct sizes.
1db854
-
1db854
- raid:/nfs/raid/src/dist-18.56/src> dump -f temacs
1db854
-
1db854
- temacs:
1db854
-
1db854
-                     **** ELF HEADER ****
1db854
- Class        Data       Type         Machine     Version
1db854
- Entry        Phoff      Shoff        Flags       Ehsize
1db854
- Phentsize    Phnum      Shentsz      Shnum       Shstrndx
1db854
-
1db854
- 1            1          2            3           1
1db854
- 0x80499cc    0x34       0x792f4      0           0x34
1db854
- 0x20         5          0x28         21          19
1db854
-
1db854
- raid:/nfs/raid/src/dist-18.56/src> dump -f xemacs
1db854
-
1db854
- xemacs:
1db854
-
1db854
-                     **** ELF HEADER ****
1db854
- Class        Data       Type         Machine     Version
1db854
- Entry        Phoff      Shoff        Flags       Ehsize
1db854
- Phentsize    Phnum      Shentsz      Shnum       Shstrndx
1db854
-
1db854
- 1            1          2            3           1
1db854
- 0x80499cc    0x34       0x96200      0           0x34
1db854
- 0x20         5          0x28         22          19
1db854
-
1db854
-  * These are the program headers.  "Offset" is the file offset to the
1db854
-  * segment.  "Vaddr" is the memory load address.  "Filesz" is the
1db854
-  * segment size as it appears in the file, and "Memsz" is the size in
1db854
-  * memory.  Below, the third segment is the code and the fourth is the
1db854
-  * data: the difference between Filesz and Memsz is .bss
1db854
-
1db854
- raid:/nfs/raid/src/dist-18.56/src> dump -o temacs
1db854
-
1db854
- temacs:
1db854
-  ***** PROGRAM EXECUTION HEADER *****
1db854
- Type        Offset      Vaddr       Paddr
1db854
- Filesz      Memsz       Flags       Align
1db854
-
1db854
- 6           0x34        0x8048034   0
1db854
- 0xa0        0xa0        5           0
1db854
-
1db854
- 3           0xd4        0           0
1db854
- 0x13        0           4           0
1db854
-
1db854
- 1           0x34        0x8048034   0
1db854
- 0x3f2f9     0x3f2f9     5           0x1000
1db854
-
1db854
- 1           0x3f330     0x8088330   0
1db854
- 0x215c4     0x25a60     7           0x1000
1db854
-
1db854
- 2           0x60874     0x80a9874   0
1db854
- 0x80        0           7           0
1db854
-
1db854
- raid:/nfs/raid/src/dist-18.56/src> dump -o xemacs
1db854
-
1db854
- xemacs:
1db854
-  ***** PROGRAM EXECUTION HEADER *****
1db854
- Type        Offset      Vaddr       Paddr
1db854
- Filesz      Memsz       Flags       Align
1db854
-
1db854
- 6           0x34        0x8048034   0
1db854
- 0xa0        0xa0        5           0
1db854
-
1db854
- 3           0xd4        0           0
1db854
- 0x13        0           4           0
1db854
-
1db854
- 1           0x34        0x8048034   0
1db854
- 0x3f2f9     0x3f2f9     5           0x1000
1db854
-
1db854
- 1           0x3f330     0x8088330   0
1db854
- 0x3e4d0     0x3e4d0     7           0x1000
1db854
-
1db854
- 2           0x60874     0x80a9874   0
1db854
- 0x80        0           7           0
1db854
-
1db854
-
1db854
- */
1db854
-
1db854
-/* Modified by wtien@urbana.mcd.mot.com of Motorola Inc.
1db854
- *
1db854
- * The above mechanism does not work if the unexeced ELF file is being
1db854
- * re-layout by other applications (such as `strip'). All the applications
1db854
- * that re-layout the internal of ELF will layout all sections in ascending
1db854
- * order of their file offsets. After the re-layout, the data2 section will
1db854
- * still be the LAST section in the section header vector, but its file offset
1db854
- * is now being pushed far away down, and causes part of it not to be mapped
1db854
- * in (ie. not covered by the load segment entry in PHDR vector), therefore
1db854
- * causes the new binary to fail.
1db854
- *
1db854
- * The solution is to modify the unexec algorithm to insert the new data2
1db854
- * section header right before the new bss section header, so their file
1db854
- * offsets will be in the ascending order. Since some of the section's (all
1db854
- * sections AFTER the bss section) indexes are now changed, we also need to
1db854
- * modify some fields to make them point to the right sections. This is done
1db854
- * by macro PATCH_INDEX. All the fields that need to be patched are:
1db854
- *
1db854
- * 1. ELF header e_shstrndx field.
1db854
- * 2. section header sh_link and sh_info field.
1db854
- * 3. symbol table entry st_shndx field.
1db854
- *
1db854
- * The above example now should look like:
1db854
-
1db854
-           **** SECTION HEADER TABLE ****
1db854
- [No]    Type    Flags   Addr         Offset       Size          Name
1db854
-         Link    Info    Adralgn      Entsize
1db854
-
1db854
- [1]     1       2       0x80480d4    0xd4         0x13          .interp
1db854
-         0       0       0x1          0
1db854
-
1db854
- [2]     5       2       0x80480e8    0xe8         0x388         .hash
1db854
-         3       0       0x4          0x4
1db854
-
1db854
- [3]     11      2       0x8048470    0x470        0x7f0         .dynsym
1db854
-         4       1       0x4          0x10
1db854
-
1db854
- [4]     3       2       0x8048c60    0xc60        0x3ad         .dynstr
1db854
-         0       0       0x1          0
1db854
-
1db854
- [5]     9       2       0x8049010    0x1010       0x338         .rel.plt
1db854
-         3       7       0x4          0x8
1db854
-
1db854
- [6]     1       6       0x8049348    0x1348       0x3           .init
1db854
-         0       0       0x4          0
1db854
-
1db854
- [7]     1       6       0x804934c    0x134c       0x680         .plt
1db854
-         0       0       0x4          0x4
1db854
-
1db854
- [8]     1       6       0x80499cc    0x19cc       0x3c56f       .text
1db854
-         0       0       0x4          0
1db854
-
1db854
- [9]     1       6       0x8085f3c    0x3df3c      0x3           .fini
1db854
-         0       0       0x4          0
1db854
-
1db854
- [10]    1       2       0x8085f40    0x3df40      0x69c         .rodata
1db854
-         0       0       0x4          0
1db854
-
1db854
- [11]    1       2       0x80865dc    0x3e5dc      0xd51         .rodata1
1db854
-         0       0       0x4          0
1db854
-
1db854
- [12]    1       3       0x8088330    0x3f330      0x20afc       .data
1db854
-         0       0       0x4          0
1db854
-
1db854
- [13]    1       3       0x80a8e2c    0x5fe2c      0x89d         .data1
1db854
-         0       0       0x4          0
1db854
-
1db854
- [14]    1       3       0x80a96cc    0x606cc      0x1a8         .got
1db854
-         0       0       0x4          0x4
1db854
-
1db854
- [15]    6       3       0x80a9874    0x60874      0x80          .dynamic
1db854
-         4       0       0x4          0x8
1db854
-
1db854
- [16]    1       3       0x80a98f4    0x608f4      0x1cf0c       .data
1db854
-         0       0       0x4          0
1db854
-
1db854
- [17]    8       3       0x80c6800    0x7d800      0             .bss
1db854
-         0       0       0x4          0
1db854
-
1db854
- [18]    2       0       0            0x7d800      0x9b90        .symtab
1db854
-         19      371     0x4          0x10
1db854
-
1db854
- [19]    3       0       0            0x87390      0x8526        .strtab
1db854
-         0       0       0x1          0
1db854
-
1db854
- [20]    3       0       0            0x8f8b6      0x93          .shstrtab
1db854
-         0       0       0x1          0
1db854
-
1db854
- [21]    1       0       0            0x8f949      0x68b7        .comment
1db854
-         0       0       0x1          0
1db854
-
1db854
- */
1db854
 
1db854
 /* We do not use mmap because that fails with NFS.
1db854
    Instead we read the whole file, modify it, and write it out.  */
1db854
@@ -552,45 +211,15 @@ entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize)
1db854
 #define NEW_PROGRAM_H(n) \
1db854
   (*(ElfW (Phdr) *) entry_address (new_program_h, n, new_file_h->e_phentsize))
1db854
 
1db854
-#define PATCH_INDEX(n) ((n) += old_bss_index <= (n))
1db854
 typedef unsigned char byte;
1db854
 
1db854
-/* Return the index of the section named NAME.
1db854
-   SECTION_NAMES, FILE_NAME and FILE_H give information
1db854
-   about the file we are looking in.
1db854
-
1db854
-   If we don't find the section NAME, that is a fatal error
1db854
-   if NOERROR is false; return -1 if NOERROR is true.  */
1db854
-
1db854
-static ptrdiff_t
1db854
-find_section (const char *name, const char *section_names, const char *file_name,
1db854
-	      ElfW (Ehdr) *old_file_h, ElfW (Shdr) *old_section_h,
1db854
-	      bool noerror)
1db854
-{
1db854
-  ptrdiff_t idx;
1db854
-
1db854
-  for (idx = 1; idx < old_file_h->e_shnum; idx++)
1db854
-    {
1db854
-      char const *found_name = section_names + OLD_SECTION_H (idx).sh_name;
1db854
-#ifdef UNEXELF_DEBUG
1db854
-      fprintf (stderr, "Looking for %s - found %s\n", name, found_name);
1db854
-#endif
1db854
-      if (strcmp (name, found_name) == 0)
1db854
-	return idx;
1db854
-    }
1db854
-
1db854
-  if (! noerror)
1db854
-    fatal ("Can't find %s in %s", name, file_name);
1db854
-  return -1;
1db854
-}
1db854
-
1db854
 /* ****************************************************************
1db854
  * unexec
1db854
  *
1db854
  * driving logic.
1db854
  *
1db854
- * In ELF, this works by replacing the old .bss section with a new
1db854
- * .data section, and inserting an empty .bss immediately afterwards.
1db854
+ * In ELF, this works by replacing the old bss SHT_NOBITS section with
1db854
+ * a new, larger, SHT_PROGBITS section.
1db854
  *
1db854
  */
1db854
 void
1db854
@@ -615,18 +244,16 @@ unexec (const char *new_name, const char *old_name)
1db854
   ElfW (Phdr) *old_program_h, *new_program_h;
1db854
   ElfW (Shdr) *old_section_h, *new_section_h;
1db854
 
1db854
-  /* Point to the section name table in the old file.  */
1db854
-  char *old_section_names;
1db854
+  /* Point to the section name table.  */
1db854
+  char *old_section_names, *new_section_names;
1db854
 
1db854
   ElfW (Phdr) *old_bss_seg, *new_bss_seg;
1db854
   ElfW (Addr) old_bss_addr, new_bss_addr;
1db854
   ElfW (Word) old_bss_size, new_data2_size;
1db854
-  ElfW (Off)  new_data2_offset;
1db854
-  ElfW (Addr) new_data2_addr;
1db854
-  ElfW (Off)  old_bss_offset;
1db854
+  ElfW (Off)  old_bss_offset, new_data2_offset;
1db854
 
1db854
-  ptrdiff_t n, nn;
1db854
-  ptrdiff_t old_bss_index, old_data_index;
1db854
+  ptrdiff_t n;
1db854
+  ptrdiff_t old_bss_index;
1db854
   struct stat stat_buf;
1db854
   off_t old_file_size;
1db854
 
1db854
@@ -688,7 +315,7 @@ unexec (const char *new_name, const char *old_name)
1db854
   old_bss_offset = old_bss_seg->p_offset + old_bss_seg->p_filesz;
1db854
   old_bss_size = old_bss_seg->p_memsz - old_bss_seg->p_filesz;
1db854
 
1db854
-  /* Find the first bss style section in the bss segment range.  */
1db854
+  /* Find the last bss style section in the bss segment range.  */
1db854
   old_bss_index = -1;
1db854
   for (n = old_file_h->e_shnum; --n > 0; )
1db854
     {
1db854
@@ -697,22 +324,15 @@ unexec (const char *new_name, const char *old_name)
1db854
 	  && shdr->sh_addr >= old_bss_addr
1db854
 	  && shdr->sh_addr + shdr->sh_size <= old_bss_addr + old_bss_size
1db854
 	  && (old_bss_index == -1
1db854
-	      || OLD_SECTION_H (old_bss_index).sh_addr > shdr->sh_addr))
1db854
+	      || OLD_SECTION_H (old_bss_index).sh_addr < shdr->sh_addr))
1db854
 	old_bss_index = n;
1db854
     }
1db854
 
1db854
   if (old_bss_index == -1)
1db854
     fatal ("no bss section found");
1db854
 
1db854
-  /* Find the old .data section.  Figure out parameters of
1db854
-     the new data2 and bss sections.  */
1db854
-
1db854
-  old_data_index = find_section (".data", old_section_names,
1db854
-				 old_name, old_file_h, old_section_h, 0);
1db854
-
1db854
   new_break = sbrk (0);
1db854
   new_bss_addr = (ElfW (Addr)) new_break;
1db854
-  new_data2_addr = old_bss_addr;
1db854
   new_data2_size = new_bss_addr - old_bss_addr;
1db854
   new_data2_offset = old_bss_offset;
1db854
 
1db854
@@ -722,7 +342,6 @@ unexec (const char *new_name, const char *old_name)
1db854
   DEBUG_LOG (old_bss_size);
1db854
   DEBUG_LOG (old_bss_offset);
1db854
   DEBUG_LOG (new_bss_addr);
1db854
-  DEBUG_LOG (new_data2_addr);
1db854
   DEBUG_LOG (new_data2_size);
1db854
   DEBUG_LOG (new_data2_offset);
1db854
 #endif
1db854
@@ -738,7 +357,7 @@ unexec (const char *new_name, const char *old_name)
1db854
   if (new_file < 0)
1db854
     fatal ("Can't creat (%s): %s", new_name, strerror (errno));
1db854
 
1db854
-  new_file_size = old_file_size + old_file_h->e_shentsize + new_data2_size;
1db854
+  new_file_size = old_file_size + new_data2_size;
1db854
 
1db854
   if (ftruncate (new_file, new_file_size))
1db854
     fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno));
1db854
@@ -754,21 +373,18 @@ unexec (const char *new_name, const char *old_name)
1db854
   new_file_h = (ElfW (Ehdr) *) new_base;
1db854
   memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
1db854
 
1db854
-  /* Fix up file header.  We'll add one section.  Section header is
1db854
-     further away now.  */
1db854
+  /* Fix up file header.  Section header is further away now.  */
1db854
 
1db854
   if (new_file_h->e_shoff >= old_bss_offset)
1db854
     new_file_h->e_shoff += new_data2_size;
1db854
-  new_file_h->e_shnum += 1;
1db854
-
1db854
-  /* Modify the e_shstrndx if necessary. */
1db854
-  PATCH_INDEX (new_file_h->e_shstrndx);
1db854
 
1db854
   new_program_h = (ElfW (Phdr) *) ((byte *) new_base + new_file_h->e_phoff);
1db854
   new_section_h = (ElfW (Shdr) *) ((byte *) new_base + new_file_h->e_shoff);
1db854
 
1db854
   memcpy (new_program_h, old_program_h,
1db854
 	  old_file_h->e_phnum * old_file_h->e_phentsize);
1db854
+  memcpy (new_section_h, old_section_h,
1db854
+	  old_file_h->e_shnum * old_file_h->e_shentsize);
1db854
 
1db854
 #ifdef UNEXELF_DEBUG
1db854
   DEBUG_LOG (old_file_h->e_shoff);
1db854
@@ -787,42 +403,21 @@ unexec (const char *new_name, const char *old_name)
1db854
   /* Copy over what we have in memory now for the bss area. */
1db854
   memcpy (new_base + new_data2_offset, (caddr_t) old_bss_addr, new_data2_size);
1db854
 
1db854
-  /* Fix up section headers based on new .data2 section.  Any section
1db854
-     whose offset or virtual address is after the new .data2 section
1db854
-     gets its value adjusted.  .bss size becomes zero.  data2 section
1db854
-     header gets added by copying the existing .data header and
1db854
-     modifying the offset, address and size.  */
1db854
-
1db854
-  /* Walk through all section headers, insert the new data2 section right
1db854
-     before the new bss section. */
1db854
-  for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++)
1db854
+  /* Walk through all section headers, copying data and updating.  */
1db854
+  for (n = 1; n < old_file_h->e_shnum; n++)
1db854
     {
1db854
       caddr_t src;
1db854
       ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
1db854
-      ElfW (Shdr) *new_shdr = &NEW_SECTION_H (nn);
1db854
-
1db854
-      /* If it is (s)bss section, insert the new data2 section before it.  */
1db854
-      if (n == old_bss_index)
1db854
-	{
1db854
-	  /* Steal the data section header for this data2 section. */
1db854
-	  memcpy (new_shdr, &OLD_SECTION_H (old_data_index),
1db854
-		  new_file_h->e_shentsize);
1db854
-
1db854
-	  new_shdr->sh_addr = new_data2_addr;
1db854
-	  new_shdr->sh_offset = new_data2_offset;
1db854
-	  new_shdr->sh_size = new_data2_size;
1db854
-	  new_shdr->sh_addralign = 1;
1db854
-	  nn++;
1db854
-	  new_shdr++;
1db854
-	}
1db854
-
1db854
-      memcpy (new_shdr, old_shdr, old_file_h->e_shentsize);
1db854
+      ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
1db854
 
1db854
       if (new_shdr->sh_type == SHT_NOBITS
1db854
 	  && new_shdr->sh_addr >= old_bss_addr
1db854
 	  && (new_shdr->sh_addr + new_shdr->sh_size
1db854
 	      <= old_bss_addr + old_bss_size))
1db854
 	{
1db854
+	  /* This section now has file backing.  */
1db854
+	  new_shdr->sh_type = SHT_PROGBITS;
1db854
+
1db854
 	  /* SHT_NOBITS sections do not need a valid sh_offset, so it
1db854
 	     might be incorrect.  Write the correct value.  */
1db854
 	  new_shdr->sh_offset = (new_shdr->sh_addr - new_bss_seg->p_vaddr
1db854
@@ -837,35 +432,20 @@ unexec (const char *new_name, const char *old_name)
1db854
 	  if (strcmp (old_section_names + new_shdr->sh_name, ".plt") == 0)
1db854
 	    memset (new_shdr->sh_offset + new_base, 0, new_shdr->sh_size);
1db854
 
1db854
-	  /* Set the new bss and sbss section's size to zero, because
1db854
-	     we've already covered this address range by .data2.  */
1db854
-	  new_shdr->sh_size = 0;
1db854
-	}
1db854
-      else
1db854
-	{
1db854
-	  /* Any section that was originally placed after the .bss
1db854
-	     section should now be off by NEW_DATA2_SIZE.  */
1db854
+	  /* Extend the size of the last bss section to cover dumped
1db854
+	     data.  */
1db854
+	  if (n == old_bss_index)
1db854
+	    new_shdr->sh_size = new_bss_addr - new_shdr->sh_addr;
1db854
 
1db854
-	  if (new_shdr->sh_offset >= old_bss_offset)
1db854
-	    new_shdr->sh_offset += new_data2_size;
1db854
-
1db854
-	  /* Any section that was originally placed after the section
1db854
-	     header table should now be off by the size of one section
1db854
-	     header table entry.  */
1db854
-	  if (new_shdr->sh_offset > new_file_h->e_shoff)
1db854
-	    new_shdr->sh_offset += new_file_h->e_shentsize;
1db854
+	  /* We have already copied this section from the current
1db854
+	     process.  */
1db854
+	  continue;
1db854
 	}
1db854
 
1db854
-      /* If any section hdr refers to the section after the new .data
1db854
-	 section, make it refer to next one because we have inserted
1db854
-	 a new section in between.  */
1db854
-
1db854
-      PATCH_INDEX (new_shdr->sh_link);
1db854
-      /* For symbol tables, info is a symbol table index,
1db854
-	 so don't change it.  */
1db854
-      if (new_shdr->sh_type != SHT_SYMTAB
1db854
-	  && new_shdr->sh_type != SHT_DYNSYM)
1db854
-	PATCH_INDEX (new_shdr->sh_info);
1db854
+      /* Any section that was originally placed after the .bss
1db854
+	 section should now be offset by NEW_DATA2_SIZE.  */
1db854
+      if (new_shdr->sh_offset >= old_bss_offset)
1db854
+	new_shdr->sh_offset += new_data2_size;
1db854
 
1db854
       /* Now, start to copy the content of sections.  */
1db854
       if (new_shdr->sh_type == SHT_NULL
1db854
@@ -981,24 +561,6 @@ unexec (const char *new_name, const char *old_name)
1db854
 	    }
1db854
 	}
1db854
 #endif /* __sgi */
1db854
-
1db854
-      /* Patch st_shndx field of symbol table.  */
1db854
-      if (new_shdr->sh_type == SHT_SYMTAB
1db854
-	  || new_shdr->sh_type == SHT_DYNSYM)
1db854
-	{
1db854
-	  ptrdiff_t num = new_shdr->sh_size / new_shdr->sh_entsize;
1db854
-	  ElfW (Sym) *sym = (ElfW (Sym) *) (new_shdr->sh_offset + new_base);
1db854
-	  for (; num--; sym++)
1db854
-	    {
1db854
-	      if (sym->st_shndx == SHN_XINDEX)
1db854
-		fatal ("SHT_SYMTAB_SHNDX unsupported");
1db854
-	      if (sym->st_shndx == SHN_UNDEF
1db854
-		  || sym->st_shndx >= SHN_LORESERVE)
1db854
-		continue;
1db854
-
1db854
-	      PATCH_INDEX (sym->st_shndx);
1db854
-	    }
1db854
-	}
1db854
     }
1db854
 
1db854
   /* Update the symbol values of _edata and _end.  */
1db854
@@ -1042,15 +604,10 @@ unexec (const char *new_name, const char *old_name)
1db854
 	      ElfW (Shdr) *new_shdr = &NEW_SECTION_H (symp->st_shndx);
1db854
 	      if (new_shdr->sh_type != SHT_NOBITS)
1db854
 		{
1db854
-		  ElfW (Shdr) *old_shdr;
1db854
+		  ElfW (Shdr) *old_shdr = &OLD_SECTION_H (symp->st_shndx);
1db854
 		  ptrdiff_t reladdr = symp->st_value - new_shdr->sh_addr;
1db854
 		  ptrdiff_t newoff = reladdr + new_shdr->sh_offset;
1db854
 
1db854
-		  /* "Unpatch" index.  */
1db854
-		  nn = symp->st_shndx;
1db854
-		  if (nn > old_bss_index)
1db854
-		    nn--;
1db854
-		  old_shdr = &OLD_SECTION_H (nn);
1db854
 		  if (old_shdr->sh_type == SHT_NOBITS)
1db854
 		    memset (new_base + newoff, 0, symp->st_size);
1db854
 		  else
1db854
@@ -1065,6 +622,25 @@ unexec (const char *new_name, const char *old_name)
1db854
 	}
1db854
     }
1db854
 
1db854
+  /* Modify the names of sections we changed from SHT_NOBITS to
1db854
+     SHT_PROGBITS.  This is really just cosmetic, but some tools that
1db854
+     (wrongly) operate on section names rather than types might be
1db854
+     confused by a SHT_PROGBITS .bss section.  */
1db854
+  new_section_names = ((char *) new_base
1db854
+		       + NEW_SECTION_H (new_file_h->e_shstrndx).sh_offset);
1db854
+  for (n = new_file_h->e_shnum; 0 < --n; )
1db854
+    {
1db854
+      ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
1db854
+      ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
1db854
+
1db854
+      /* Replace the leading '.' with ','.  When .shstrtab is string
1db854
+	 merged this will rename both .bss and .rela.bss to ,bss and
1db854
+	 .rela,bss.  */
1db854
+      if (old_shdr->sh_type == SHT_NOBITS
1db854
+	  && new_shdr->sh_type == SHT_PROGBITS)
1db854
+	*(new_section_names + new_shdr->sh_name) = ',';
1db854
+    }
1db854
+
1db854
   /* This loop seeks out relocation sections for the data section, so
1db854
      that it can undo relocations performed by the runtime loader.  */
1db854
   for (n = new_file_h->e_shnum; 0 < --n; )
1db854
-- 
1db854
2.7.4
1db854