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