|
|
1db854 |
From a2085a540975a1e6660dbc3b0c092789f002703e 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 08/11] ELF unexec: Drive from PT_LOAD header rather than
|
|
|
1db854 |
sections
|
|
|
1db854 |
|
|
|
1db854 |
This rewrites bss handling in the ELF unexec code. Finding bss
|
|
|
1db854 |
sections by name results in complicated code that
|
|
|
1db854 |
- does not account for all names of possible bss sections,
|
|
|
1db854 |
- assumes specific ordering of bss sections,
|
|
|
1db854 |
- can wrongly choose a SHT_NOBITS section not in the bss segment,
|
|
|
1db854 |
- incorrectly calculates bss size (no accounting for alignment gaps),
|
|
|
1db854 |
- assumes .data and .bss are in the same segment.
|
|
|
1db854 |
|
|
|
1db854 |
All of these problems and more are solved by finding the bss segment
|
|
|
1db854 |
in PT_LOAD headers, ie. the address range included in p_memsz but not
|
|
|
1db854 |
p_filesz of the last PT_LOAD header, then matching SHT_NOBITS sections
|
|
|
1db854 |
in that address range.
|
|
|
1db854 |
|
|
|
1db854 |
* unexelf.c: Delete old ppc comment.
|
|
|
1db854 |
(OLD_PROGRAM_H): Define.
|
|
|
1db854 |
(round_up): Delete.
|
|
|
1db854 |
(unexec): Don't search for bss style sections by name. Instead,
|
|
|
1db854 |
use the last PT_LOAD header address range covered by p_memsz
|
|
|
1db854 |
but not p_filesz and match any SHT_NOBITS section in that
|
|
|
1db854 |
address range. Simplify initialisation of section header vars.
|
|
|
1db854 |
Don't assume that section headers are above bss segment. Move
|
|
|
1db854 |
copying of bss area out of section loop. Align .data2 section
|
|
|
1db854 |
to 1, since it now covers the entire bss area. For SHT_NOBITS
|
|
|
1db854 |
sections in the bss segment, leave sh_addr and sh_addralign
|
|
|
1db854 |
unchanged, but correct sh_offset. Clear memory corresponding
|
|
|
1db854 |
to SHT_NOBITS .plt section. Delete comment and hacks for
|
|
|
1db854 |
sections partly overlapping bss range now that the full range
|
|
|
1db854 |
is properly calculated. Delete now dead .sbss code.
|
|
|
1db854 |
(Bug#20614)
|
|
|
1db854 |
---
|
|
|
1db854 |
src/unexelf.c | 290 ++++++++++++++++------------------------------------------
|
|
|
1db854 |
1 file changed, 77 insertions(+), 213 deletions(-)
|
|
|
1db854 |
|
|
|
1db854 |
diff --git a/src/unexelf.c b/src/unexelf.c
|
|
|
1db854 |
index 15a4cde..4e9c50d 100644
|
|
|
1db854 |
--- a/src/unexelf.c
|
|
|
1db854 |
+++ b/src/unexelf.c
|
|
|
1db854 |
@@ -535,29 +535,6 @@ verify ((! TYPE_SIGNED (ElfW (Half))
|
|
|
1db854 |
/* Get the address of a particular section or program header entry,
|
|
|
1db854 |
* accounting for the size of the entries.
|
|
|
1db854 |
*/
|
|
|
1db854 |
-/*
|
|
|
1db854 |
- On PPC Reference Platform running Solaris 2.5.1
|
|
|
1db854 |
- the plt section is also of type NOBI like the bss section.
|
|
|
1db854 |
- (not really stored) and therefore sections after the bss
|
|
|
1db854 |
- section start at the plt offset. The plt section is always
|
|
|
1db854 |
- the one just before the bss section.
|
|
|
1db854 |
- Thus, we modify the test from
|
|
|
1db854 |
- if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
|
|
|
1db854 |
- to
|
|
|
1db854 |
- if (NEW_SECTION_H (nn).sh_offset >=
|
|
|
1db854 |
- OLD_SECTION_H (old_bss_index-1).sh_offset)
|
|
|
1db854 |
- This is just a hack. We should put the new data section
|
|
|
1db854 |
- before the .plt section.
|
|
|
1db854 |
- And we should not have this routine at all but use
|
|
|
1db854 |
- the libelf library to read the old file and create the new
|
|
|
1db854 |
- file.
|
|
|
1db854 |
- The changed code is minimal and depends on prep set in m/prep.h
|
|
|
1db854 |
- Erik Deumens
|
|
|
1db854 |
- Quantum Theory Project
|
|
|
1db854 |
- University of Florida
|
|
|
1db854 |
- deumens@qtp.ufl.edu
|
|
|
1db854 |
- Apr 23, 1996
|
|
|
1db854 |
- */
|
|
|
1db854 |
|
|
|
1db854 |
static void *
|
|
|
1db854 |
entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize)
|
|
|
1db854 |
@@ -570,23 +547,14 @@ entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize)
|
|
|
1db854 |
(*(ElfW (Shdr) *) entry_address (old_section_h, n, old_file_h->e_shentsize))
|
|
|
1db854 |
#define NEW_SECTION_H(n) \
|
|
|
1db854 |
(*(ElfW (Shdr) *) entry_address (new_section_h, n, new_file_h->e_shentsize))
|
|
|
1db854 |
+#define OLD_PROGRAM_H(n) \
|
|
|
1db854 |
+ (*(ElfW (Phdr) *) entry_address (old_program_h, n, old_file_h->e_phentsize))
|
|
|
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 |
-/* Round X up to a multiple of Y. */
|
|
|
1db854 |
-
|
|
|
1db854 |
-static ElfW (Addr)
|
|
|
1db854 |
-round_up (ElfW (Addr) x, ElfW (Addr) y)
|
|
|
1db854 |
-{
|
|
|
1db854 |
- ElfW (Addr) rem = x % y;
|
|
|
1db854 |
- if (rem == 0)
|
|
|
1db854 |
- return x;
|
|
|
1db854 |
- return x - rem + y;
|
|
|
1db854 |
-}
|
|
|
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 |
@@ -650,16 +618,15 @@ unexec (const char *new_name, const char *old_name)
|
|
|
1db854 |
/* Point to the section name table in the old file. */
|
|
|
1db854 |
char *old_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 (Word) new_data2_incr;
|
|
|
1db854 |
|
|
|
1db854 |
ptrdiff_t n, nn;
|
|
|
1db854 |
- ptrdiff_t old_bss_index, old_sbss_index, old_plt_index;
|
|
|
1db854 |
- ptrdiff_t old_data_index, new_data2_index;
|
|
|
1db854 |
+ ptrdiff_t old_bss_index, old_data_index;
|
|
|
1db854 |
struct stat stat_buf;
|
|
|
1db854 |
off_t old_file_size;
|
|
|
1db854 |
|
|
|
1db854 |
@@ -703,54 +670,40 @@ unexec (const char *new_name, const char *old_name)
|
|
|
1db854 |
old_section_names = (char *) old_base
|
|
|
1db854 |
+ OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
|
|
|
1db854 |
|
|
|
1db854 |
- /* Find the old .bss section. Figure out parameters of the new
|
|
|
1db854 |
- data2 and bss sections. */
|
|
|
1db854 |
-
|
|
|
1db854 |
- old_bss_index = find_section (".bss", old_section_names,
|
|
|
1db854 |
- old_name, old_file_h, old_section_h, 0);
|
|
|
1db854 |
-
|
|
|
1db854 |
- old_sbss_index = find_section (".sbss", old_section_names,
|
|
|
1db854 |
- old_name, old_file_h, old_section_h, 1);
|
|
|
1db854 |
- if (old_sbss_index != -1)
|
|
|
1db854 |
- if (OLD_SECTION_H (old_sbss_index).sh_type != SHT_NOBITS)
|
|
|
1db854 |
- old_sbss_index = -1;
|
|
|
1db854 |
-
|
|
|
1db854 |
- /* PowerPC64 has .plt in the BSS section. */
|
|
|
1db854 |
- old_plt_index = find_section (".plt", old_section_names,
|
|
|
1db854 |
- old_name, old_file_h, old_section_h, 1);
|
|
|
1db854 |
- if (old_plt_index != -1)
|
|
|
1db854 |
- if (OLD_SECTION_H (old_plt_index).sh_type != SHT_NOBITS)
|
|
|
1db854 |
- old_plt_index = -1;
|
|
|
1db854 |
-
|
|
|
1db854 |
- if (old_sbss_index == -1 && old_plt_index == -1)
|
|
|
1db854 |
- {
|
|
|
1db854 |
- old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
|
|
|
1db854 |
- old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
|
|
|
1db854 |
- old_bss_offset = OLD_SECTION_H (old_bss_index).sh_offset;
|
|
|
1db854 |
- new_data2_index = old_bss_index;
|
|
|
1db854 |
- }
|
|
|
1db854 |
- else if (old_plt_index != -1
|
|
|
1db854 |
- && (old_sbss_index == -1
|
|
|
1db854 |
- || (OLD_SECTION_H (old_sbss_index).sh_addr
|
|
|
1db854 |
- > OLD_SECTION_H (old_plt_index).sh_addr)))
|
|
|
1db854 |
+ /* Find the PT_LOAD header covering the highest address. This
|
|
|
1db854 |
+ segment will be where bss sections are located, past p_filesz. */
|
|
|
1db854 |
+ old_bss_seg = 0;
|
|
|
1db854 |
+ for (n = old_file_h->e_phnum; --n >= 0; )
|
|
|
1db854 |
{
|
|
|
1db854 |
- old_bss_addr = OLD_SECTION_H (old_plt_index).sh_addr;
|
|
|
1db854 |
- old_bss_size = OLD_SECTION_H (old_bss_index).sh_size
|
|
|
1db854 |
- + OLD_SECTION_H (old_plt_index).sh_size;
|
|
|
1db854 |
- if (old_sbss_index != -1)
|
|
|
1db854 |
- old_bss_size += OLD_SECTION_H (old_sbss_index).sh_size;
|
|
|
1db854 |
- old_bss_offset = OLD_SECTION_H (old_plt_index).sh_offset;
|
|
|
1db854 |
- new_data2_index = old_plt_index;
|
|
|
1db854 |
+ ElfW (Phdr) *seg = &OLD_PROGRAM_H (n);
|
|
|
1db854 |
+ if (seg->p_type == PT_LOAD
|
|
|
1db854 |
+ && (old_bss_seg == 0
|
|
|
1db854 |
+ || seg->p_vaddr > old_bss_seg->p_vaddr))
|
|
|
1db854 |
+ old_bss_seg = seg;
|
|
|
1db854 |
}
|
|
|
1db854 |
- else
|
|
|
1db854 |
+
|
|
|
1db854 |
+ /* Note that old_bss_addr may be lower than the first bss section
|
|
|
1db854 |
+ address, since the section may need aligning. */
|
|
|
1db854 |
+ old_bss_addr = old_bss_seg->p_vaddr + old_bss_seg->p_filesz;
|
|
|
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 |
+ old_bss_index = -1;
|
|
|
1db854 |
+ for (n = old_file_h->e_shnum; --n > 0; )
|
|
|
1db854 |
{
|
|
|
1db854 |
- old_bss_addr = OLD_SECTION_H (old_sbss_index).sh_addr;
|
|
|
1db854 |
- old_bss_size = OLD_SECTION_H (old_bss_index).sh_size
|
|
|
1db854 |
- + OLD_SECTION_H (old_sbss_index).sh_size;
|
|
|
1db854 |
- old_bss_offset = OLD_SECTION_H (old_sbss_index).sh_offset;
|
|
|
1db854 |
- new_data2_index = old_sbss_index;
|
|
|
1db854 |
+ ElfW (Shdr) *shdr = &OLD_SECTION_H (n);
|
|
|
1db854 |
+ if (shdr->sh_type == SHT_NOBITS
|
|
|
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_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 |
@@ -761,13 +714,7 @@ unexec (const char *new_name, const char *old_name)
|
|
|
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_SECTION_H (old_data_index).sh_offset
|
|
|
1db854 |
- + (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
|
|
|
1db854 |
- /* This is the amount by which the sections following the bss sections
|
|
|
1db854 |
- must be shifted in the image. It can differ from new_data2_size if
|
|
|
1db854 |
- the end of the old .data section (and thus the offset of the .bss
|
|
|
1db854 |
- section) was unaligned. */
|
|
|
1db854 |
- new_data2_incr = new_data2_size + (new_data2_offset - old_bss_offset);
|
|
|
1db854 |
+ new_data2_offset = old_bss_offset;
|
|
|
1db854 |
|
|
|
1db854 |
#ifdef UNEXELF_DEBUG
|
|
|
1db854 |
fprintf (stderr, "old_bss_index %td\n", old_bss_index);
|
|
|
1db854 |
@@ -778,7 +725,6 @@ unexec (const char *new_name, const char *old_name)
|
|
|
1db854 |
DEBUG_LOG (new_data2_addr);
|
|
|
1db854 |
DEBUG_LOG (new_data2_size);
|
|
|
1db854 |
DEBUG_LOG (new_data2_offset);
|
|
|
1db854 |
- DEBUG_LOG (new_data2_incr);
|
|
|
1db854 |
#endif
|
|
|
1db854 |
|
|
|
1db854 |
if (new_bss_addr < old_bss_addr + old_bss_size)
|
|
|
1db854 |
@@ -792,7 +738,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_incr;
|
|
|
1db854 |
+ new_file_size = old_file_size + old_file_h->e_shentsize + new_data2_size;
|
|
|
1db854 |
|
|
|
1db854 |
if (ftruncate (new_file, new_file_size))
|
|
|
1db854 |
fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno));
|
|
|
1db854 |
@@ -811,15 +757,15 @@ unexec (const char *new_name, const char *old_name)
|
|
|
1db854 |
/* Fix up file header. We'll add one section. Section header is
|
|
|
1db854 |
further away now. */
|
|
|
1db854 |
|
|
|
1db854 |
- new_file_h->e_shoff += new_data2_incr;
|
|
|
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 + old_file_h->e_phoff);
|
|
|
1db854 |
- new_section_h = (ElfW (Shdr) *)
|
|
|
1db854 |
- ((byte *) new_base + old_file_h->e_shoff + new_data2_incr);
|
|
|
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 |
@@ -831,65 +777,21 @@ unexec (const char *new_name, const char *old_name)
|
|
|
1db854 |
fprintf (stderr, "New section count %td\n", (ptrdiff_t) new_file_h->e_shnum);
|
|
|
1db854 |
#endif
|
|
|
1db854 |
|
|
|
1db854 |
- /* Fix up a new program header. Extend the writable data segment so
|
|
|
1db854 |
- that the bss area is covered too. Find that segment by looking
|
|
|
1db854 |
- for a segment that ends just before the .bss area. Make sure
|
|
|
1db854 |
- that no segments are above the new .data2. Put a loop at the end
|
|
|
1db854 |
- to adjust the offset and address of any segment that is above
|
|
|
1db854 |
- data2, just in case we decide to allow this later. */
|
|
|
1db854 |
+ /* Fix up program header. Extend the writable data segment so
|
|
|
1db854 |
+ that the bss area is covered too. */
|
|
|
1db854 |
|
|
|
1db854 |
- for (n = new_file_h->e_phnum; --n >= 0; )
|
|
|
1db854 |
- {
|
|
|
1db854 |
- /* Compute maximum of all requirements for alignment of section. */
|
|
|
1db854 |
- ElfW (Word) alignment = (NEW_PROGRAM_H (n)).p_align;
|
|
|
1db854 |
- if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
|
|
|
1db854 |
- alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
|
|
|
1db854 |
-
|
|
|
1db854 |
-#ifdef __sgi
|
|
|
1db854 |
- /* According to r02kar@x4u2.desy.de (Karsten Kuenne)
|
|
|
1db854 |
- and oliva@gnu.org (Alexandre Oliva), on IRIX 5.2, we
|
|
|
1db854 |
- always get "Program segment above .bss" when dumping
|
|
|
1db854 |
- when the executable doesn't have an sbss section. */
|
|
|
1db854 |
- if (old_sbss_index != -1)
|
|
|
1db854 |
-#endif /* __sgi */
|
|
|
1db854 |
- if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz
|
|
|
1db854 |
- > (old_sbss_index == -1
|
|
|
1db854 |
- ? old_bss_addr
|
|
|
1db854 |
- : round_up (old_bss_addr, alignment)))
|
|
|
1db854 |
- fatal ("Program segment above .bss in %s", old_name);
|
|
|
1db854 |
-
|
|
|
1db854 |
- if (NEW_PROGRAM_H (n).p_type == PT_LOAD
|
|
|
1db854 |
- && (round_up ((NEW_PROGRAM_H (n)).p_vaddr
|
|
|
1db854 |
- + (NEW_PROGRAM_H (n)).p_filesz,
|
|
|
1db854 |
- alignment)
|
|
|
1db854 |
- == round_up (old_bss_addr, alignment)))
|
|
|
1db854 |
- break;
|
|
|
1db854 |
- }
|
|
|
1db854 |
- if (n < 0)
|
|
|
1db854 |
- fatal ("Couldn't find segment next to .bss in %s", old_name);
|
|
|
1db854 |
-
|
|
|
1db854 |
- /* Make sure that the size includes any padding before the old .bss
|
|
|
1db854 |
- section. */
|
|
|
1db854 |
- NEW_PROGRAM_H (n).p_filesz = new_bss_addr - NEW_PROGRAM_H (n).p_vaddr;
|
|
|
1db854 |
- NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz;
|
|
|
1db854 |
-
|
|
|
1db854 |
-#if 0 /* Maybe allow section after data2 - does this ever happen? */
|
|
|
1db854 |
- for (n = new_file_h->e_phnum; --n >= 0; )
|
|
|
1db854 |
- {
|
|
|
1db854 |
- if (NEW_PROGRAM_H (n).p_vaddr
|
|
|
1db854 |
- && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr)
|
|
|
1db854 |
- NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size;
|
|
|
1db854 |
+ new_bss_seg = new_program_h + (old_bss_seg - old_program_h);
|
|
|
1db854 |
+ new_bss_seg->p_filesz = new_bss_addr - new_bss_seg->p_vaddr;
|
|
|
1db854 |
+ new_bss_seg->p_memsz = new_bss_seg->p_filesz;
|
|
|
1db854 |
|
|
|
1db854 |
- if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset)
|
|
|
1db854 |
- NEW_PROGRAM_H (n).p_offset += new_data2_incr;
|
|
|
1db854 |
- }
|
|
|
1db854 |
-#endif
|
|
|
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 and new address
|
|
|
1db854 |
- is set. data2 section header gets added by copying the existing
|
|
|
1db854 |
- .data header and modifying the offset, address and size. */
|
|
|
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 |
@@ -900,9 +802,7 @@ unexec (const char *new_name, const char *old_name)
|
|
|
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 |
- /* new_data2_index is the index of either old_sbss or old_bss, that was
|
|
|
1db854 |
- chosen as a section for new_data2. */
|
|
|
1db854 |
- if (n == new_data2_index)
|
|
|
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 |
@@ -911,68 +811,43 @@ unexec (const char *new_name, const char *old_name)
|
|
|
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 |
- /* Use the bss section's alignment. This will assure that the
|
|
|
1db854 |
- new data2 section always be placed in the same spot as the old
|
|
|
1db854 |
- bss section by any other application. */
|
|
|
1db854 |
- new_shdr->sh_addralign = old_shdr->sh_addralign;
|
|
|
1db854 |
-
|
|
|
1db854 |
- /* Now copy over what we have in the memory now. */
|
|
|
1db854 |
- memcpy (new_shdr->sh_offset + new_base,
|
|
|
1db854 |
- (caddr_t) old_shdr->sh_addr,
|
|
|
1db854 |
- 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 |
|
|
|
1db854 |
- if (n == old_bss_index
|
|
|
1db854 |
- /* The new bss and sbss section's size is zero, and its file offset
|
|
|
1db854 |
- and virtual address should be off by NEW_DATA2_SIZE. */
|
|
|
1db854 |
- || n == old_sbss_index || n == old_plt_index
|
|
|
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 |
- /* NN should be `old_s?bss_index + 1' at this point. */
|
|
|
1db854 |
- new_shdr->sh_offset = new_data2_offset + new_data2_size;
|
|
|
1db854 |
- new_shdr->sh_addr = new_data2_addr + new_data2_size;
|
|
|
1db854 |
- /* Let the new bss section address alignment be the same as the
|
|
|
1db854 |
- section address alignment followed the old bss section, so
|
|
|
1db854 |
- this section will be placed in exactly the same place. */
|
|
|
1db854 |
- new_shdr->sh_addralign = OLD_SECTION_H (nn).sh_addralign;
|
|
|
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 |
+ + new_bss_seg->p_offset);
|
|
|
1db854 |
+
|
|
|
1db854 |
+ /* If this is was a SHT_NOBITS .plt section, then it is
|
|
|
1db854 |
+ probably a PowerPC PLT. If it is PowerPC64 ELFv1 then
|
|
|
1db854 |
+ glibc ld.so doesn't initialize the toc pointer word. A
|
|
|
1db854 |
+ non-zero toc pointer word can defeat Power7 thread safety
|
|
|
1db854 |
+ during lazy update of a PLT entry. This only matters if
|
|
|
1db854 |
+ emacs becomes multi-threaded. */
|
|
|
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_INCR. If a
|
|
|
1db854 |
- section overlaps the .bss section, consider it to be
|
|
|
1db854 |
- placed after the .bss section. Overlap can occur if the
|
|
|
1db854 |
- section just before .bss has less-strict alignment; this
|
|
|
1db854 |
- was observed between .symtab and .bss on Solaris 2.5.1
|
|
|
1db854 |
- (sparc) with GCC snapshot 960602.
|
|
|
1db854 |
+ section should now be off by NEW_DATA2_SIZE. */
|
|
|
1db854 |
|
|
|
1db854 |
-> 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 |
-[22] 1 3 0x335150 0x315150 0x4 .data.rel.local
|
|
|
1db854 |
- 0 0 0x4 0
|
|
|
1db854 |
-
|
|
|
1db854 |
-[23] 8 3 0x335158 0x315158 0x42720 .bss
|
|
|
1db854 |
- 0 0 0x8 0
|
|
|
1db854 |
-
|
|
|
1db854 |
-[24] 2 0 0 0x315154 0x1c9d0 .symtab
|
|
|
1db854 |
- 25 1709 0x4 0x10
|
|
|
1db854 |
- */
|
|
|
1db854 |
-
|
|
|
1db854 |
- if (new_shdr->sh_offset >= old_bss_offset
|
|
|
1db854 |
- || (new_shdr->sh_offset + new_shdr->sh_size
|
|
|
1db854 |
- > new_data2_offset))
|
|
|
1db854 |
- new_shdr->sh_offset += new_data2_incr;
|
|
|
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 |
@@ -992,23 +867,13 @@ temacs:
|
|
|
1db854 |
&& new_shdr->sh_type != SHT_DYNSYM)
|
|
|
1db854 |
PATCH_INDEX (new_shdr->sh_info);
|
|
|
1db854 |
|
|
|
1db854 |
- if (old_sbss_index != -1)
|
|
|
1db854 |
- if (!strcmp (old_section_names + new_shdr->sh_name, ".sbss"))
|
|
|
1db854 |
- {
|
|
|
1db854 |
- new_shdr->sh_offset =
|
|
|
1db854 |
- round_up (new_shdr->sh_offset,
|
|
|
1db854 |
- new_shdr->sh_addralign);
|
|
|
1db854 |
- new_shdr->sh_type = SHT_PROGBITS;
|
|
|
1db854 |
- }
|
|
|
1db854 |
-
|
|
|
1db854 |
/* Now, start to copy the content of sections. */
|
|
|
1db854 |
if (new_shdr->sh_type == SHT_NULL
|
|
|
1db854 |
|| new_shdr->sh_type == SHT_NOBITS)
|
|
|
1db854 |
continue;
|
|
|
1db854 |
|
|
|
1db854 |
- /* Write out the sections. .data and .data1 (and data2, called
|
|
|
1db854 |
- ".data" in the strings table) get copied from the current process
|
|
|
1db854 |
- instead of the old file. */
|
|
|
1db854 |
+ /* Some sections are copied from the current process instead of
|
|
|
1db854 |
+ the old file. */
|
|
|
1db854 |
if (!strcmp (old_section_names + new_shdr->sh_name, ".data")
|
|
|
1db854 |
|| !strcmp (old_section_names + new_shdr->sh_name, ".sdata")
|
|
|
1db854 |
|| !strcmp (old_section_names + new_shdr->sh_name, ".lit4")
|
|
|
1db854 |
@@ -1037,8 +902,7 @@ temacs:
|
|
|
1db854 |
|| !strcmp (old_section_names + new_shdr->sh_name, ".got")
|
|
|
1db854 |
#endif
|
|
|
1db854 |
|| !strcmp (old_section_names + new_shdr->sh_name, ".sdata1")
|
|
|
1db854 |
- || !strcmp (old_section_names + new_shdr->sh_name, ".data1")
|
|
|
1db854 |
- || !strcmp (old_section_names + new_shdr->sh_name, ".sbss"))
|
|
|
1db854 |
+ || !strcmp (old_section_names + new_shdr->sh_name, ".data1"))
|
|
|
1db854 |
src = (caddr_t) old_shdr->sh_addr;
|
|
|
1db854 |
else
|
|
|
1db854 |
src = old_base + old_shdr->sh_offset;
|
|
|
1db854 |
--
|
|
|
1db854 |
2.7.4
|
|
|
1db854 |
|