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

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