|
|
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 |
|