fix build failure on ppc64le (#1306793)

Resolves: #1306793
This commit is contained in:
Jan Synacek 2016-02-15 10:28:00 +01:00
parent 36c99ab41e
commit e76854c18d
11 changed files with 2159 additions and 0 deletions

View File

@ -0,0 +1,69 @@
From 0a97fb1992c8cc3612a2358f576f774ea1f36777 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Sun, 8 Nov 2015 09:28:59 -0800
Subject: ELF unexec: Correct section header index
Emacs should build on ppc64el. A problem with the bss has been fixed.
This upstream patch has been added [1/10]:
ELF unexec: Correct section header index
First a small fix. The code incorrectly uses "NEW_SECTION_H (n)" when
it should have been using "NEW_SECTION_H (nn)" to find the name of the
section currently being processed. Of course, before the bss
sections, n and nn have the same value, so this doesn't matter except
in the case of .sbss. For .sbss this probably meant .bss (most likely
the next section) was copied from memory. A later patch removes the
bogus .sbss handling anyway.
* unexelf.c (unexec): Use correct index to look up names.
Origin: upstream, commit: 0bcd08ef052bca9b8d08696068c2a0c387d0dd56
Bug: http://debbugs.gnu.org/20614
Bug-Debian: http://bugs.debian.org/808347
Added-by: Rob Browning <rlb@defaultvalue.org>
---
src/unexelf.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
Index: emacs-24.5/src/unexelf.c
===================================================================
--- emacs-24.5.orig/src/unexelf.c
+++ emacs-24.5/src/unexelf.c
@@ -1016,12 +1016,12 @@ temacs:
/* Write out the sections. .data and .data1 (and data2, called
".data" in the strings table) get copied from the current process
instead of the old file. */
- if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data")
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
+ if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data")
+ || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
".sdata")
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
+ || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
".lit4")
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
+ || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
".lit8")
/* The conditional bit below was in Oliva's original code
(1999-08-25) and seems to have been dropped by mistake
@@ -1044,14 +1044,14 @@ temacs:
loader, but I never got anywhere with an SGI support call
seeking clues. -- fx 2002-11-29. */
#ifdef IRIX6_5
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
+ || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
".got")
#endif
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
+ || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
".sdata1")
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
+ || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
".data1")
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
+ || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
".sbss"))
src = (caddr_t) OLD_SECTION_H (n).sh_addr;
else

View File

@ -0,0 +1,422 @@
From 9fa97f0c2c1afae39b6662a836910deb1e0130ad Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Sun, 8 Nov 2015 09:28:59 -0800
Subject: ELF unexec: Tidy code
Emacs should build on ppc64el. A problem with the bss has been fixed.
This upstream patch has been added [2/10]:
ELF unexec: Tidy code
Separate out some of the more mechanical changes so following patches
are smaller.
* unexelf.c (unexec): Rearrange initialisation of program
header vars. Use pointer vars in loops rather than indexing
section header array via macros. Simplify _OBJC_ sym code
and reloc handling code.
Origin: upstream, commit: 856f4eaba8a76953e0bbcfc7ebb0ca4f2e3cf351
Bug: http://debbugs.gnu.org/20614
Bug-Debian: http://bugs.debian.org/808347
Added-by: Rob Browning <rlb@defaultvalue.org>
---
src/unexelf.c | 210 ++++++++++++++++++++++++++--------------------------------
1 file changed, 96 insertions(+), 114 deletions(-)
Index: emacs-24.5/src/unexelf.c
===================================================================
--- emacs-24.5.orig/src/unexelf.c
+++ emacs-24.5/src/unexelf.c
@@ -813,20 +813,11 @@ unexec (const char *new_name, const char
if (new_base == MAP_FAILED)
fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
- new_file_h = (ElfW (Ehdr) *) new_base;
- new_program_h = (ElfW (Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
- new_section_h = (ElfW (Shdr) *)
- ((byte *) new_base + old_file_h->e_shoff + new_data2_incr);
-
/* Make our new file, program and section headers as copies of the
originals. */
+ new_file_h = (ElfW (Ehdr) *) new_base;
memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
- memcpy (new_program_h, old_program_h,
- old_file_h->e_phnum * old_file_h->e_phentsize);
-
- /* Modify the e_shstrndx if necessary. */
- PATCH_INDEX (new_file_h->e_shstrndx);
/* Fix up file header. We'll add one section. Section header is
further away now. */
@@ -834,6 +825,16 @@ unexec (const char *new_name, const char
new_file_h->e_shoff += new_data2_incr;
new_file_h->e_shnum += 1;
+ /* Modify the e_shstrndx if necessary. */
+ PATCH_INDEX (new_file_h->e_shstrndx);
+
+ new_program_h = (ElfW (Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
+ new_section_h = (ElfW (Shdr) *)
+ ((byte *) new_base + old_file_h->e_shoff + new_data2_incr);
+
+ memcpy (new_program_h, old_program_h,
+ old_file_h->e_phnum * old_file_h->e_phentsize);
+
#ifdef UNEXELF_DEBUG
DEBUG_LOG (old_file_h->e_shoff);
fprintf (stderr, "Old section count %td\n", (ptrdiff_t) old_file_h->e_shnum);
@@ -906,32 +907,35 @@ unexec (const char *new_name, const char
for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++)
{
caddr_t src;
+ ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
+ ElfW (Shdr) *new_shdr = &NEW_SECTION_H (nn);
+
/* If it is (s)bss section, insert the new data2 section before it. */
/* new_data2_index is the index of either old_sbss or old_bss, that was
chosen as a section for new_data2. */
if (n == new_data2_index)
{
/* Steal the data section header for this data2 section. */
- memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index),
+ memcpy (new_shdr, &OLD_SECTION_H (old_data_index),
new_file_h->e_shentsize);
- NEW_SECTION_H (nn).sh_addr = new_data2_addr;
- NEW_SECTION_H (nn).sh_offset = new_data2_offset;
- NEW_SECTION_H (nn).sh_size = new_data2_size;
+ new_shdr->sh_addr = new_data2_addr;
+ new_shdr->sh_offset = new_data2_offset;
+ new_shdr->sh_size = new_data2_size;
/* Use the bss section's alignment. This will assure that the
new data2 section always be placed in the same spot as the old
bss section by any other application. */
- NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign;
+ new_shdr->sh_addralign = old_shdr->sh_addralign;
/* Now copy over what we have in the memory now. */
- memcpy (NEW_SECTION_H (nn).sh_offset + new_base,
- (caddr_t) OLD_SECTION_H (n).sh_addr,
+ memcpy (new_shdr->sh_offset + new_base,
+ (caddr_t) old_shdr->sh_addr,
new_data2_size);
nn++;
+ new_shdr++;
}
- memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
- old_file_h->e_shentsize);
+ memcpy (new_shdr, old_shdr, old_file_h->e_shentsize);
if (n == old_bss_index
/* The new bss and sbss section's size is zero, and its file offset
@@ -940,13 +944,13 @@ unexec (const char *new_name, const char
)
{
/* NN should be `old_s?bss_index + 1' at this point. */
- NEW_SECTION_H (nn).sh_offset = new_data2_offset + new_data2_size;
- NEW_SECTION_H (nn).sh_addr = new_data2_addr + new_data2_size;
+ new_shdr->sh_offset = new_data2_offset + new_data2_size;
+ new_shdr->sh_addr = new_data2_addr + new_data2_size;
/* Let the new bss section address alignment be the same as the
section address alignment followed the old bss section, so
this section will be placed in exactly the same place. */
- NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign;
- NEW_SECTION_H (nn).sh_size = 0;
+ new_shdr->sh_addralign = OLD_SECTION_H (nn).sh_addralign;
+ new_shdr->sh_size = 0;
}
else
{
@@ -976,53 +980,50 @@ temacs:
25 1709 0x4 0x10
*/
- if (NEW_SECTION_H (nn).sh_offset >= old_bss_offset
- || (NEW_SECTION_H (nn).sh_offset + NEW_SECTION_H (nn).sh_size
+ if (new_shdr->sh_offset >= old_bss_offset
+ || (new_shdr->sh_offset + new_shdr->sh_size
> new_data2_offset))
- NEW_SECTION_H (nn).sh_offset += new_data2_incr;
+ new_shdr->sh_offset += new_data2_incr;
/* Any section that was originally placed after the section
header table should now be off by the size of one section
header table entry. */
- if (NEW_SECTION_H (nn).sh_offset > new_file_h->e_shoff)
- NEW_SECTION_H (nn).sh_offset += new_file_h->e_shentsize;
+ if (new_shdr->sh_offset > new_file_h->e_shoff)
+ new_shdr->sh_offset += new_file_h->e_shentsize;
}
/* If any section hdr refers to the section after the new .data
section, make it refer to next one because we have inserted
a new section in between. */
- PATCH_INDEX (NEW_SECTION_H (nn).sh_link);
+ PATCH_INDEX (new_shdr->sh_link);
/* For symbol tables, info is a symbol table index,
so don't change it. */
- if (NEW_SECTION_H (nn).sh_type != SHT_SYMTAB
- && NEW_SECTION_H (nn).sh_type != SHT_DYNSYM)
- PATCH_INDEX (NEW_SECTION_H (nn).sh_info);
+ if (new_shdr->sh_type != SHT_SYMTAB
+ && new_shdr->sh_type != SHT_DYNSYM)
+ PATCH_INDEX (new_shdr->sh_info);
if (old_sbss_index != -1)
- if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".sbss"))
+ if (!strcmp (old_section_names + new_shdr->sh_name, ".sbss"))
{
- NEW_SECTION_H (nn).sh_offset =
- round_up (NEW_SECTION_H (nn).sh_offset,
- NEW_SECTION_H (nn).sh_addralign);
- NEW_SECTION_H (nn).sh_type = SHT_PROGBITS;
+ new_shdr->sh_offset =
+ round_up (new_shdr->sh_offset,
+ new_shdr->sh_addralign);
+ new_shdr->sh_type = SHT_PROGBITS;
}
/* Now, start to copy the content of sections. */
- if (NEW_SECTION_H (nn).sh_type == SHT_NULL
- || NEW_SECTION_H (nn).sh_type == SHT_NOBITS)
+ if (new_shdr->sh_type == SHT_NULL
+ || new_shdr->sh_type == SHT_NOBITS)
continue;
/* Write out the sections. .data and .data1 (and data2, called
".data" in the strings table) get copied from the current process
instead of the old file. */
- if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".sdata")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".lit4")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".lit8")
+ if (!strcmp (old_section_names + new_shdr->sh_name, ".data")
+ || !strcmp (old_section_names + new_shdr->sh_name, ".sdata")
+ || !strcmp (old_section_names + new_shdr->sh_name, ".lit4")
+ || !strcmp (old_section_names + new_shdr->sh_name, ".lit8")
/* The conditional bit below was in Oliva's original code
(1999-08-25) and seems to have been dropped by mistake
subsequently. It prevents a crash at startup under X in
@@ -1044,28 +1045,22 @@ temacs:
loader, but I never got anywhere with an SGI support call
seeking clues. -- fx 2002-11-29. */
#ifdef IRIX6_5
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".got")
+ || !strcmp (old_section_names + new_shdr->sh_name, ".got")
#endif
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".sdata1")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".data1")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".sbss"))
- src = (caddr_t) OLD_SECTION_H (n).sh_addr;
+ || !strcmp (old_section_names + new_shdr->sh_name, ".sdata1")
+ || !strcmp (old_section_names + new_shdr->sh_name, ".data1")
+ || !strcmp (old_section_names + new_shdr->sh_name, ".sbss"))
+ src = (caddr_t) old_shdr->sh_addr;
else
- src = old_base + OLD_SECTION_H (n).sh_offset;
+ src = old_base + old_shdr->sh_offset;
- memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src,
- NEW_SECTION_H (nn).sh_size);
+ memcpy (new_shdr->sh_offset + new_base, src, new_shdr->sh_size);
#if defined __alpha__ && !defined __OpenBSD__
/* Update Alpha COFF symbol table: */
- if (strcmp (old_section_names + OLD_SECTION_H (n).sh_name, ".mdebug")
- == 0)
+ if (strcmp (old_section_names + old_shdr->sh_name, ".mdebug") == 0)
{
- pHDRR symhdr = (pHDRR) (NEW_SECTION_H (nn).sh_offset + new_base);
+ pHDRR symhdr = (pHDRR) (new_shdr->sh_offset + new_base);
symhdr->cbLineOffset += new_data2_size;
symhdr->cbDnOffset += new_data2_size;
@@ -1082,13 +1077,13 @@ temacs:
#endif /* __alpha__ && !__OpenBSD__ */
#if defined (_SYSTYPE_SYSV)
- if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG
+ if (new_shdr->sh_type == SHT_MIPS_DEBUG
&& old_mdebug_index != -1)
{
- ptrdiff_t new_offset = NEW_SECTION_H (nn).sh_offset;
+ ptrdiff_t new_offset = new_shdr->sh_offset;
ptrdiff_t old_offset = OLD_SECTION_H (old_mdebug_index).sh_offset;
ptrdiff_t diff = new_offset - old_offset;
- HDRR *phdr = (HDRR *)(NEW_SECTION_H (nn).sh_offset + new_base);
+ HDRR *phdr = (HDRR *) (new_shdr->sh_offset + new_base);
if (diff)
{
@@ -1124,8 +1119,8 @@ temacs:
n_phdrr->__fileaddr += movement; \
}
- HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset);
- HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset);
+ HDRR *o_phdrr = (HDRR *) ((byte *) old_base + old_shdr->sh_offset);
+ HDRR *n_phdrr = (HDRR *) ((byte *) new_base + new_shdr->sh_offset);
unsigned movement = new_data2_size;
MDEBUGADJUST (idnMax, cbDnOffset);
@@ -1142,8 +1137,8 @@ temacs:
requires special handling. */
if (n_phdrr->cbLine > 0)
{
- if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset
- + OLD_SECTION_H (n).sh_size))
+ if (o_phdrr->cbLineOffset > (old_shdr->sh_offset
+ + old_shdr->sh_size))
{
/* line data is in a hole in elf. do special copy and adjust
for this ld mistake.
@@ -1163,13 +1158,11 @@ temacs:
#endif /* __sgi */
/* If it is the symbol table, its st_shndx field needs to be patched. */
- if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB
- || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)
+ if (new_shdr->sh_type == SHT_SYMTAB
+ || new_shdr->sh_type == SHT_DYNSYM)
{
- ElfW (Shdr) *spt = &NEW_SECTION_H (nn);
- ptrdiff_t num = spt->sh_size / spt->sh_entsize;
- ElfW (Sym) * sym = (ElfW (Sym) *) (NEW_SECTION_H (nn).sh_offset +
- new_base);
+ ptrdiff_t num = new_shdr->sh_size / new_shdr->sh_entsize;
+ ElfW (Sym) *sym = (ElfW (Sym) *) (new_shdr->sh_offset + new_base);
for (; num--; sym++)
{
if ((sym->st_shndx == SHN_UNDEF)
@@ -1187,15 +1180,16 @@ temacs:
{
byte *symnames;
ElfW (Sym) *symp, *symendp;
+ ElfW (Shdr) *sym_shdr = &NEW_SECTION_H (n);
- if (NEW_SECTION_H (n).sh_type != SHT_DYNSYM
- && NEW_SECTION_H (n).sh_type != SHT_SYMTAB)
+ if (sym_shdr->sh_type != SHT_DYNSYM
+ && sym_shdr->sh_type != SHT_SYMTAB)
continue;
symnames = ((byte *) new_base
- + NEW_SECTION_H (NEW_SECTION_H (n).sh_link).sh_offset);
- symp = (ElfW (Sym) *) (NEW_SECTION_H (n).sh_offset + new_base);
- symendp = (ElfW (Sym) *) ((byte *)symp + NEW_SECTION_H (n).sh_size);
+ + NEW_SECTION_H (sym_shdr->sh_link).sh_offset);
+ symp = (ElfW (Sym) *) (sym_shdr->sh_offset + new_base);
+ symendp = (ElfW (Sym) *) ((byte *) symp + sym_shdr->sh_size);
for (; symp < symendp; symp ++)
{
@@ -1219,22 +1213,21 @@ temacs:
if (strncmp ((char *) (symnames + symp->st_name),
"_OBJC_", sizeof ("_OBJC_") - 1) == 0)
{
- caddr_t old, new;
+ ElfW (Shdr) *new_shdr = &NEW_SECTION_H (symp->st_shndx);
+ ptrdiff_t reladdr = symp->st_value - new_shdr->sh_addr;
+ ptrdiff_t newoff = reladdr + new_shdr->sh_offset;
- new = ((symp->st_value - NEW_SECTION_H (symp->st_shndx).sh_addr)
- + NEW_SECTION_H (symp->st_shndx).sh_offset + new_base);
/* "Unpatch" index. */
nn = symp->st_shndx;
if (nn > old_bss_index)
nn--;
if (nn == old_bss_index)
- memset (new, 0, symp->st_size);
+ memset (new_base + newoff, 0, symp->st_size);
else
{
- old = ((symp->st_value
- - NEW_SECTION_H (symp->st_shndx).sh_addr)
- + OLD_SECTION_H (nn).sh_offset + old_base);
- memcpy (new, old, symp->st_size);
+ ElfW (Shdr) *old_shdr = &OLD_SECTION_H (nn);
+ ptrdiff_t oldoff = reladdr + old_shdr->sh_offset;
+ memcpy (new_base + newoff, old_base + oldoff, symp->st_size);
}
}
#endif
@@ -1245,13 +1238,10 @@ temacs:
that it can undo relocations performed by the runtime linker. */
for (n = new_file_h->e_shnum; 0 < --n; )
{
- ElfW (Shdr) section = NEW_SECTION_H (n);
-
- /* Cause a compilation error if anyone uses n instead of nn below. */
- #define n ((void) 0);
- n /* Prevent 'macro "n" is not used' warnings. */
+ ElfW (Shdr) *rel_shdr = &NEW_SECTION_H (n);
+ ElfW (Shdr) *shdr;
- switch (section.sh_type)
+ switch (rel_shdr->sh_type)
{
default:
break;
@@ -1260,28 +1250,22 @@ temacs:
/* This code handles two different size structs, but there should
be no harm in that provided that r_offset is always the first
member. */
- nn = section.sh_info;
- if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".sdata")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".lit4")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".lit8")
+ shdr = &NEW_SECTION_H (rel_shdr->sh_info);
+ if (!strcmp (old_section_names + shdr->sh_name, ".data")
+ || !strcmp (old_section_names + shdr->sh_name, ".sdata")
+ || !strcmp (old_section_names + shdr->sh_name, ".lit4")
+ || !strcmp (old_section_names + shdr->sh_name, ".lit8")
#ifdef IRIX6_5 /* see above */
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".got")
+ || !strcmp (old_section_names + shdr->sh_name, ".got")
#endif
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".sdata1")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".data1"))
+ || !strcmp (old_section_names + shdr->sh_name, ".sdata1")
+ || !strcmp (old_section_names + shdr->sh_name, ".data1"))
{
- ElfW (Addr) offset = (NEW_SECTION_H (nn).sh_addr
- - NEW_SECTION_H (nn).sh_offset);
- caddr_t reloc = old_base + section.sh_offset, end;
- for (end = reloc + section.sh_size; reloc < end;
- reloc += section.sh_entsize)
+ ElfW (Addr) offset = shdr->sh_addr - shdr->sh_offset;
+ caddr_t reloc = old_base + rel_shdr->sh_offset, end;
+ for (end = reloc + rel_shdr->sh_size;
+ reloc < end;
+ reloc += rel_shdr->sh_entsize)
{
ElfW (Addr) addr = ((ElfW (Rel) *) reloc)->r_offset - offset;
#ifdef __alpha__
@@ -1296,8 +1280,6 @@ temacs:
}
break;
}
-
- #undef n
}
/* Write out new_file, and free the buffers. */

View File

@ -0,0 +1,174 @@
From 2cb9075979e413e4cc31c85d3bd830f791cc574b Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Sun, 8 Nov 2015 09:28:59 -0800
Subject: ELF unexec: Merge Alpha and MIPS COFF debug handling
Emacs should build on ppc64el. A problem with the bss has been fixed.
This upstream patch has been added [3/10]:
ELF unexec: Merge Alpha and MIPS COFF debug handling
* unexelf.c (unexec): Merge Alpha and MIPS COFF debug handling.
Don't find .mdebug section index, find the section in the loop.
Allow for unlikely possibility that .mdebug is located at sh_offset
before bss segment, by calculating move from difference in
sh_offset rather than just assuming new_data2_size. Simplify
cbLineOffset handling.
Origin: upstream, commit: 47c6e3035b8182c6436de4673473de7824ad59f1
Bug: http://debbugs.gnu.org/20614
Bug-Debian: http://bugs.debian.org/808347
Added-by: Rob Browning <rlb@defaultvalue.org>
---
src/unexelf.c | 96 +++++++++++++++++-----------------------------------------
1 file changed, 29 insertions(+), 67 deletions(-)
Index: emacs-24.5/src/unexelf.c
===================================================================
--- emacs-24.5.orig/src/unexelf.c
+++ emacs-24.5/src/unexelf.c
@@ -660,9 +660,6 @@ unexec (const char *new_name, const char
ptrdiff_t n, nn;
ptrdiff_t old_bss_index, old_sbss_index, old_plt_index;
ptrdiff_t old_data_index, new_data2_index;
-#if defined _SYSTYPE_SYSV || defined __sgi
- ptrdiff_t old_mdebug_index;
-#endif
struct stat stat_buf;
off_t old_file_size;
int mask;
@@ -707,13 +704,6 @@ unexec (const char *new_name, const char
old_section_names = (char *) old_base
+ OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
- /* Find the mdebug section, if any. */
-
-#if defined _SYSTYPE_SYSV || defined __sgi
- old_mdebug_index = find_section (".mdebug", old_section_names,
- old_name, old_file_h, old_section_h, 1);
-#endif
-
/* Find the old .bss section. Figure out parameters of the new
data2 and bss sections. */
@@ -1056,51 +1046,31 @@ temacs:
memcpy (new_shdr->sh_offset + new_base, src, new_shdr->sh_size);
-#if defined __alpha__ && !defined __OpenBSD__
- /* Update Alpha COFF symbol table: */
- if (strcmp (old_section_names + old_shdr->sh_name, ".mdebug") == 0)
- {
- pHDRR symhdr = (pHDRR) (new_shdr->sh_offset + new_base);
-
- symhdr->cbLineOffset += new_data2_size;
- symhdr->cbDnOffset += new_data2_size;
- symhdr->cbPdOffset += new_data2_size;
- symhdr->cbSymOffset += new_data2_size;
- symhdr->cbOptOffset += new_data2_size;
- symhdr->cbAuxOffset += new_data2_size;
- symhdr->cbSsOffset += new_data2_size;
- symhdr->cbSsExtOffset += new_data2_size;
- symhdr->cbFdOffset += new_data2_size;
- symhdr->cbRfdOffset += new_data2_size;
- symhdr->cbExtOffset += new_data2_size;
- }
-#endif /* __alpha__ && !__OpenBSD__ */
-
-#if defined (_SYSTYPE_SYSV)
- if (new_shdr->sh_type == SHT_MIPS_DEBUG
- && old_mdebug_index != -1)
+#if (defined __alpha__ && !defined __OpenBSD__) || defined _SYSTYPE_SYSV
+ /* Update Alpha and MIPS COFF debug symbol table. */
+ if (strcmp (old_section_names + new_shdr->sh_name, ".mdebug") == 0
+ && new_shdr->sh_offset - old_shdr->sh_offset != 0
+#if defined _SYSTYPE_SYSV
+ && new_shdr->sh_type == SHT_MIPS_DEBUG
+#endif
+ )
{
- ptrdiff_t new_offset = new_shdr->sh_offset;
- ptrdiff_t old_offset = OLD_SECTION_H (old_mdebug_index).sh_offset;
- ptrdiff_t diff = new_offset - old_offset;
+ ptrdiff_t diff = new_shdr->sh_offset - old_shdr->sh_offset;
HDRR *phdr = (HDRR *) (new_shdr->sh_offset + new_base);
- if (diff)
- {
- phdr->cbLineOffset += diff;
- phdr->cbDnOffset += diff;
- phdr->cbPdOffset += diff;
- phdr->cbSymOffset += diff;
- phdr->cbOptOffset += diff;
- phdr->cbAuxOffset += diff;
- phdr->cbSsOffset += diff;
- phdr->cbSsExtOffset += diff;
- phdr->cbFdOffset += diff;
- phdr->cbRfdOffset += diff;
- phdr->cbExtOffset += diff;
- }
+ phdr->cbLineOffset += diff;
+ phdr->cbDnOffset += diff;
+ phdr->cbPdOffset += diff;
+ phdr->cbSymOffset += diff;
+ phdr->cbOptOffset += diff;
+ phdr->cbAuxOffset += diff;
+ phdr->cbSsOffset += diff;
+ phdr->cbSsExtOffset += diff;
+ phdr->cbFdOffset += diff;
+ phdr->cbRfdOffset += diff;
+ phdr->cbExtOffset += diff;
}
-#endif /* _SYSTYPE_SYSV */
+#endif /* __alpha__ || _SYSTYPE_SYSV */
#if __sgi
/* Adjust the HDRR offsets in .mdebug and copy the
@@ -1111,7 +1081,8 @@ temacs:
the ld bug that gets the line table in a hole in the
elf file rather than in the .mdebug section proper.
David Anderson. davea@sgi.com Jan 16,1994. */
- if (n == old_mdebug_index)
+ if (strcmp (old_section_names + new_shdr->sh_name, ".mdebug") == 0
+ && new_shdr->sh_offset - old_shdr->sh_offset != 0)
{
#define MDEBUGADJUST(__ct,__fileaddr) \
if (n_phdrr->__ct > 0) \
@@ -1121,7 +1092,7 @@ temacs:
HDRR *o_phdrr = (HDRR *) ((byte *) old_base + old_shdr->sh_offset);
HDRR *n_phdrr = (HDRR *) ((byte *) new_base + new_shdr->sh_offset);
- unsigned movement = new_data2_size;
+ ptrdiff_t movement = new_shdr->sh_offset - old_shdr->sh_offset;
MDEBUGADJUST (idnMax, cbDnOffset);
MDEBUGADJUST (ipdMax, cbPdOffset);
@@ -1137,22 +1108,13 @@ temacs:
requires special handling. */
if (n_phdrr->cbLine > 0)
{
+ n_phdrr->cbLineOffset += movement;
+
if (o_phdrr->cbLineOffset > (old_shdr->sh_offset
+ old_shdr->sh_size))
- {
- /* line data is in a hole in elf. do special copy and adjust
- for this ld mistake.
- */
- n_phdrr->cbLineOffset += movement;
-
- memcpy (n_phdrr->cbLineOffset + new_base,
- o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
- }
- else
- {
- /* somehow line data is in .mdebug as it is supposed to be. */
- MDEBUGADJUST (cbLine, cbLineOffset);
- }
+ /* If not covered by section, it hasn't yet been copied. */
+ memcpy (n_phdrr->cbLineOffset + new_base,
+ o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
}
}
#endif /* __sgi */

View File

@ -0,0 +1,50 @@
From 2776e4ffe1f4cf965a6b99201097ca7d4ee2f95c Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Sun, 8 Nov 2015 09:29:00 -0800
Subject: ELF unexec: Symbol table patching
Emacs should build on ppc64el. A problem with the bss has been fixed.
This upstream patch has been added [4/10]:
ELF unexec: Symbol table patching
No st_shndx value larger than SHN_LORESERVE should be changed.
* unexelf.c (unexec): Don't adjust any st_shndx larger than
SHN_LORESERVE. Error on SHN_XINDEX.
Origin: upstream, commit: 190b968f189cb7d06223bb39045ec9055df67f68
Bug: http://debbugs.gnu.org/20614
Bug-Debian: http://bugs.debian.org/808347
Added-by: Rob Browning <rlb@defaultvalue.org>
---
src/unexelf.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
Index: emacs-24.5/src/unexelf.c
===================================================================
--- emacs-24.5.orig/src/unexelf.c
+++ emacs-24.5/src/unexelf.c
@@ -1119,7 +1119,7 @@ temacs:
}
#endif /* __sgi */
- /* If it is the symbol table, its st_shndx field needs to be patched. */
+ /* Patch st_shndx field of symbol table. */
if (new_shdr->sh_type == SHT_SYMTAB
|| new_shdr->sh_type == SHT_DYNSYM)
{
@@ -1127,9 +1127,10 @@ temacs:
ElfW (Sym) *sym = (ElfW (Sym) *) (new_shdr->sh_offset + new_base);
for (; num--; sym++)
{
- if ((sym->st_shndx == SHN_UNDEF)
- || (sym->st_shndx == SHN_ABS)
- || (sym->st_shndx == SHN_COMMON))
+ if (sym->st_shndx == SHN_XINDEX)
+ fatal ("SHT_SYMTAB_SHNDX unsupported");
+ if (sym->st_shndx == SHN_UNDEF
+ || sym->st_shndx >= SHN_LORESERVE)
continue;
PATCH_INDEX (sym->st_shndx);

View File

@ -0,0 +1,70 @@
From af11708e83ab826202593ab1b9c22601c46a5056 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Sun, 8 Nov 2015 09:29:00 -0800
Subject: ELF unexec: _OBJC_ symbols in bss sections
Emacs should build on ppc64el. A problem with the bss has been fixed.
This upstream patch has been added [5/10]:
ELF unexec: _OBJC_ symbols in bss sections
This code assumed that there was only one bss section. Rather than
checking for a particular index, check the section type. Also, handle
the possibility that the section was SHT_NOBITS originally and is
unchanged, in which case no clearing is needed (and sh_offset isn't
necessarily valid, which can lead to a wild memset).
* unexelf.c (unexec): Properly handle _OBJC_ symbols in bss sections.
Origin: upstream, commit: 3ff9fc0e8d738be5004c65c3be314af9aca68148
Bug: http://debbugs.gnu.org/20614
Bug-Debian: http://bugs.debian.org/808347
Added-by: Rob Browning <rlb@defaultvalue.org>
---
src/unexelf.c | 31 ++++++++++++++++++-------------
1 file changed, 18 insertions(+), 13 deletions(-)
Index: emacs-24.5/src/unexelf.c
===================================================================
--- emacs-24.5.orig/src/unexelf.c
+++ emacs-24.5/src/unexelf.c
@@ -1177,20 +1177,25 @@ temacs:
"_OBJC_", sizeof ("_OBJC_") - 1) == 0)
{
ElfW (Shdr) *new_shdr = &NEW_SECTION_H (symp->st_shndx);
- ptrdiff_t reladdr = symp->st_value - new_shdr->sh_addr;
- ptrdiff_t newoff = reladdr + new_shdr->sh_offset;
-
- /* "Unpatch" index. */
- nn = symp->st_shndx;
- if (nn > old_bss_index)
- nn--;
- if (nn == old_bss_index)
- memset (new_base + newoff, 0, symp->st_size);
- else
+ if (new_shdr->sh_type != SHT_NOBITS)
{
- ElfW (Shdr) *old_shdr = &OLD_SECTION_H (nn);
- ptrdiff_t oldoff = reladdr + old_shdr->sh_offset;
- memcpy (new_base + newoff, old_base + oldoff, symp->st_size);
+ ElfW (Shdr) *old_shdr;
+ ptrdiff_t reladdr = symp->st_value - new_shdr->sh_addr;
+ ptrdiff_t newoff = reladdr + new_shdr->sh_offset;
+
+ /* "Unpatch" index. */
+ nn = symp->st_shndx;
+ if (nn > old_bss_index)
+ nn--;
+ old_shdr = &OLD_SECTION_H (nn);
+ if (old_shdr->sh_type == SHT_NOBITS)
+ memset (new_base + newoff, 0, symp->st_size);
+ else
+ {
+ ptrdiff_t oldoff = reladdr + old_shdr->sh_offset;
+ memcpy (new_base + newoff, old_base + oldoff,
+ symp->st_size);
+ }
}
}
#endif

View File

@ -0,0 +1,58 @@
From f9d91515971443b754b9c9eaac45a293d0e620c1 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Sun, 8 Nov 2015 09:29:00 -0800
Subject: ELF unexec: R_*_NONE relocs
Emacs should build on ppc64el. A problem with the bss has been fixed.
This upstream patch has been added [6/10]:
ELF unexec: R_*_NONE relocs
These should be ignored on all targets.
* unexelf.c (unexec): Ignore R_*_NONE relocs for any target,
not just Alpha. Comment on reloc size assumption.
Origin: upstream, commit: 8285c2ab8050de218c0c06182659ee0a7b23a0f6
Bug: http://debbugs.gnu.org/20614
Bug-Debian: http://bugs.debian.org/808347
Added-by: Rob Browning <rlb@defaultvalue.org>
---
src/unexelf.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
Index: emacs-24.5/src/unexelf.c
===================================================================
--- emacs-24.5.orig/src/unexelf.c
+++ emacs-24.5/src/unexelf.c
@@ -1203,7 +1203,7 @@ temacs:
}
/* This loop seeks out relocation sections for the data section, so
- that it can undo relocations performed by the runtime linker. */
+ that it can undo relocations performed by the runtime loader. */
for (n = new_file_h->e_shnum; 0 < --n; )
{
ElfW (Shdr) *rel_shdr = &NEW_SECTION_H (n);
@@ -1236,14 +1236,14 @@ temacs:
reloc += rel_shdr->sh_entsize)
{
ElfW (Addr) addr = ((ElfW (Rel) *) reloc)->r_offset - offset;
-#ifdef __alpha__
- /* The Alpha ELF binutils currently have a bug that
- sometimes results in relocs that contain all
- zeroes. Work around this for now... */
+ /* Ignore R_*_NONE relocs. */
if (((ElfW (Rel) *) reloc)->r_offset == 0)
continue;
-#endif
- memcpy (new_base + addr, old_base + addr, sizeof (ElfW (Addr)));
+ /* Assume reloc applies to a word.
+ ??? This is not always true, eg. TLS module/index
+ pair in .got which occupies two words. */
+ memcpy (new_base + addr, old_base + addr,
+ sizeof (ElfW (Addr)));
}
}
break;

View File

@ -0,0 +1,481 @@
From 75dc7e12d73ad8c1bf9583515e41913980883dbe Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Sun, 8 Nov 2015 09:29:00 -0800
Subject: ELF unexec: Drive from PT_LOAD header rather than sections
Emacs should build on ppc64el. A problem with the bss has been fixed.
This upstream patch has been added [7/10]:
ELF unexec: Drive from PT_LOAD header rather than sections
This rewrites bss handling in the ELF unexec code. Finding bss
sections by name results in complicated code that
- does not account for all names of possible bss sections,
- assumes specific ordering of bss sections,
- can wrongly choose a SHT_NOBITS section not in the bss segment,
- incorrectly calculates bss size (no accounting for alignment gaps),
- assumes .data and .bss are in the same segment.
All of these problems and more are solved by finding the bss segment
in PT_LOAD headers, ie. the address range included in p_memsz but not
p_filesz of the last PT_LOAD header, then matching SHT_NOBITS sections
in that address range.
* unexelf.c: Delete old ppc comment.
(OLD_PROGRAM_H): Define.
(round_up): Delete.
(unexec): Don't search for bss style sections by name. Instead,
use the last PT_LOAD header address range covered by p_memsz
but not p_filesz and match any SHT_NOBITS section in that
address range. Simplify initialisation of section header vars.
Don't assume that section headers are above bss segment. Move
copying of bss area out of section loop. Align .data2 section
to 1, since it now covers the entire bss area. For SHT_NOBITS
sections in the bss segment, leave sh_addr and sh_addralign
unchanged, but correct sh_offset. Clear memory corresponding
to SHT_NOBITS .plt section. Delete comment and hacks for
sections partly overlapping bss range now that the full range
is properly calculated. Delete now dead .sbss code.
(Bug#20614)
Origin: upstream, commit: 0d6442265e5b709af5eebedf8f0d6b82974f4c31
Bug: http://debbugs.gnu.org/20614
Bug-Debian: http://bugs.debian.org/808347
Added-by: Rob Browning <rlb@defaultvalue.org>
---
src/unexelf.c | 292 +++++++++++++++-------------------------------------------
1 file changed, 78 insertions(+), 214 deletions(-)
Index: emacs-24.5/src/unexelf.c
===================================================================
--- emacs-24.5.orig/src/unexelf.c
+++ emacs-24.5/src/unexelf.c
@@ -535,29 +535,6 @@ verify ((! TYPE_SIGNED (ElfW (Half))
/* Get the address of a particular section or program header entry,
* accounting for the size of the entries.
*/
-/*
- On PPC Reference Platform running Solaris 2.5.1
- the plt section is also of type NOBI like the bss section.
- (not really stored) and therefore sections after the bss
- section start at the plt offset. The plt section is always
- the one just before the bss section.
- Thus, we modify the test from
- if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
- to
- if (NEW_SECTION_H (nn).sh_offset >=
- OLD_SECTION_H (old_bss_index-1).sh_offset)
- This is just a hack. We should put the new data section
- before the .plt section.
- And we should not have this routine at all but use
- the libelf library to read the old file and create the new
- file.
- The changed code is minimal and depends on prep set in m/prep.h
- Erik Deumens
- Quantum Theory Project
- University of Florida
- deumens@qtp.ufl.edu
- Apr 23, 1996
- */
static void *
entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize)
@@ -570,23 +547,14 @@ entry_address (void *section_h, ptrdiff_
(*(ElfW (Shdr) *) entry_address (old_section_h, n, old_file_h->e_shentsize))
#define NEW_SECTION_H(n) \
(*(ElfW (Shdr) *) entry_address (new_section_h, n, new_file_h->e_shentsize))
+#define OLD_PROGRAM_H(n) \
+ (*(ElfW (Phdr) *) entry_address (old_program_h, n, old_file_h->e_phentsize))
#define NEW_PROGRAM_H(n) \
(*(ElfW (Phdr) *) entry_address (new_program_h, n, new_file_h->e_phentsize))
#define PATCH_INDEX(n) ((n) += old_bss_index <= (n))
typedef unsigned char byte;
-/* Round X up to a multiple of Y. */
-
-static ElfW (Addr)
-round_up (ElfW (Addr) x, ElfW (Addr) y)
-{
- ElfW (Addr) rem = x % y;
- if (rem == 0)
- return x;
- return x - rem + y;
-}
-
/* Return the index of the section named NAME.
SECTION_NAMES, FILE_NAME and FILE_H give information
about the file we are looking in.
@@ -650,16 +618,15 @@ unexec (const char *new_name, const char
/* Point to the section name table in the old file. */
char *old_section_names;
+ ElfW (Phdr) *old_bss_seg, *new_bss_seg;
ElfW (Addr) old_bss_addr, new_bss_addr;
ElfW (Word) old_bss_size, new_data2_size;
ElfW (Off) new_data2_offset;
ElfW (Addr) new_data2_addr;
ElfW (Off) old_bss_offset;
- ElfW (Word) new_data2_incr;
ptrdiff_t n, nn;
- ptrdiff_t old_bss_index, old_sbss_index, old_plt_index;
- ptrdiff_t old_data_index, new_data2_index;
+ ptrdiff_t old_bss_index, old_data_index;
struct stat stat_buf;
off_t old_file_size;
int mask;
@@ -704,54 +671,40 @@ unexec (const char *new_name, const char
old_section_names = (char *) old_base
+ OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
- /* Find the old .bss section. Figure out parameters of the new
- data2 and bss sections. */
-
- old_bss_index = find_section (".bss", old_section_names,
- old_name, old_file_h, old_section_h, 0);
-
- old_sbss_index = find_section (".sbss", old_section_names,
- old_name, old_file_h, old_section_h, 1);
- if (old_sbss_index != -1)
- if (OLD_SECTION_H (old_sbss_index).sh_type != SHT_NOBITS)
- old_sbss_index = -1;
-
- /* PowerPC64 has .plt in the BSS section. */
- old_plt_index = find_section (".plt", old_section_names,
- old_name, old_file_h, old_section_h, 1);
- if (old_plt_index != -1)
- if (OLD_SECTION_H (old_plt_index).sh_type != SHT_NOBITS)
- old_plt_index = -1;
-
- if (old_sbss_index == -1 && old_plt_index == -1)
- {
- old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
- old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
- old_bss_offset = OLD_SECTION_H (old_bss_index).sh_offset;
- new_data2_index = old_bss_index;
- }
- else if (old_plt_index != -1
- && (old_sbss_index == -1
- || (OLD_SECTION_H (old_sbss_index).sh_addr
- > OLD_SECTION_H (old_plt_index).sh_addr)))
+ /* Find the PT_LOAD header covering the highest address. This
+ segment will be where bss sections are located, past p_filesz. */
+ old_bss_seg = 0;
+ for (n = old_file_h->e_phnum; --n >= 0; )
{
- old_bss_addr = OLD_SECTION_H (old_plt_index).sh_addr;
- old_bss_size = OLD_SECTION_H (old_bss_index).sh_size
- + OLD_SECTION_H (old_plt_index).sh_size;
- if (old_sbss_index != -1)
- old_bss_size += OLD_SECTION_H (old_sbss_index).sh_size;
- old_bss_offset = OLD_SECTION_H (old_plt_index).sh_offset;
- new_data2_index = old_plt_index;
+ ElfW (Phdr) *seg = &OLD_PROGRAM_H (n);
+ if (seg->p_type == PT_LOAD
+ && (old_bss_seg == 0
+ || seg->p_vaddr > old_bss_seg->p_vaddr))
+ old_bss_seg = seg;
}
- else
+
+ /* Note that old_bss_addr may be lower than the first bss section
+ address, since the section may need aligning. */
+ old_bss_addr = old_bss_seg->p_vaddr + old_bss_seg->p_filesz;
+ old_bss_offset = old_bss_seg->p_offset + old_bss_seg->p_filesz;
+ old_bss_size = old_bss_seg->p_memsz - old_bss_seg->p_filesz;
+
+ /* Find the first bss style section in the bss segment range. */
+ old_bss_index = -1;
+ for (n = old_file_h->e_shnum; --n > 0; )
{
- old_bss_addr = OLD_SECTION_H (old_sbss_index).sh_addr;
- old_bss_size = OLD_SECTION_H (old_bss_index).sh_size
- + OLD_SECTION_H (old_sbss_index).sh_size;
- old_bss_offset = OLD_SECTION_H (old_sbss_index).sh_offset;
- new_data2_index = old_sbss_index;
+ ElfW (Shdr) *shdr = &OLD_SECTION_H (n);
+ if (shdr->sh_type == SHT_NOBITS
+ && shdr->sh_addr >= old_bss_addr
+ && shdr->sh_addr + shdr->sh_size <= old_bss_addr + old_bss_size
+ && (old_bss_index == -1
+ || OLD_SECTION_H (old_bss_index).sh_addr > shdr->sh_addr))
+ old_bss_index = n;
}
+ if (old_bss_index == -1)
+ fatal ("no bss section found");
+
/* Find the old .data section. Figure out parameters of
the new data2 and bss sections. */
@@ -762,13 +715,7 @@ unexec (const char *new_name, const char
new_bss_addr = (ElfW (Addr)) new_break;
new_data2_addr = old_bss_addr;
new_data2_size = new_bss_addr - old_bss_addr;
- new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset
- + (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
- /* This is the amount by which the sections following the bss sections
- must be shifted in the image. It can differ from new_data2_size if
- the end of the old .data section (and thus the offset of the .bss
- section) was unaligned. */
- new_data2_incr = new_data2_size + (new_data2_offset - old_bss_offset);
+ new_data2_offset = old_bss_offset;
#ifdef UNEXELF_DEBUG
fprintf (stderr, "old_bss_index %td\n", old_bss_index);
@@ -779,7 +726,6 @@ unexec (const char *new_name, const char
DEBUG_LOG (new_data2_addr);
DEBUG_LOG (new_data2_size);
DEBUG_LOG (new_data2_offset);
- DEBUG_LOG (new_data2_incr);
#endif
if (new_bss_addr < old_bss_addr + old_bss_size)
@@ -793,7 +739,7 @@ unexec (const char *new_name, const char
if (new_file < 0)
fatal ("Can't creat (%s): %s", new_name, strerror (errno));
- new_file_size = old_file_size + old_file_h->e_shentsize + new_data2_incr;
+ new_file_size = old_file_size + old_file_h->e_shentsize + new_data2_size;
if (ftruncate (new_file, new_file_size))
fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno));
@@ -812,15 +758,15 @@ unexec (const char *new_name, const char
/* Fix up file header. We'll add one section. Section header is
further away now. */
- new_file_h->e_shoff += new_data2_incr;
+ if (new_file_h->e_shoff >= old_bss_offset)
+ new_file_h->e_shoff += new_data2_size;
new_file_h->e_shnum += 1;
/* Modify the e_shstrndx if necessary. */
PATCH_INDEX (new_file_h->e_shstrndx);
- new_program_h = (ElfW (Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
- new_section_h = (ElfW (Shdr) *)
- ((byte *) new_base + old_file_h->e_shoff + new_data2_incr);
+ new_program_h = (ElfW (Phdr) *) ((byte *) new_base + new_file_h->e_phoff);
+ new_section_h = (ElfW (Shdr) *) ((byte *) new_base + new_file_h->e_shoff);
memcpy (new_program_h, old_program_h,
old_file_h->e_phnum * old_file_h->e_phentsize);
@@ -832,65 +778,21 @@ unexec (const char *new_name, const char
fprintf (stderr, "New section count %td\n", (ptrdiff_t) new_file_h->e_shnum);
#endif
- /* Fix up a new program header. Extend the writable data segment so
- that the bss area is covered too. Find that segment by looking
- for a segment that ends just before the .bss area. Make sure
- that no segments are above the new .data2. Put a loop at the end
- to adjust the offset and address of any segment that is above
- data2, just in case we decide to allow this later. */
+ /* Fix up program header. Extend the writable data segment so
+ that the bss area is covered too. */
- for (n = new_file_h->e_phnum; --n >= 0; )
- {
- /* Compute maximum of all requirements for alignment of section. */
- ElfW (Word) alignment = (NEW_PROGRAM_H (n)).p_align;
- if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
- alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
-
-#ifdef __sgi
- /* According to r02kar@x4u2.desy.de (Karsten Kuenne)
- and oliva@gnu.org (Alexandre Oliva), on IRIX 5.2, we
- always get "Program segment above .bss" when dumping
- when the executable doesn't have an sbss section. */
- if (old_sbss_index != -1)
-#endif /* __sgi */
- if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz
- > (old_sbss_index == -1
- ? old_bss_addr
- : round_up (old_bss_addr, alignment)))
- fatal ("Program segment above .bss in %s", old_name);
-
- if (NEW_PROGRAM_H (n).p_type == PT_LOAD
- && (round_up ((NEW_PROGRAM_H (n)).p_vaddr
- + (NEW_PROGRAM_H (n)).p_filesz,
- alignment)
- == round_up (old_bss_addr, alignment)))
- break;
- }
- if (n < 0)
- fatal ("Couldn't find segment next to .bss in %s", old_name);
-
- /* Make sure that the size includes any padding before the old .bss
- section. */
- NEW_PROGRAM_H (n).p_filesz = new_bss_addr - NEW_PROGRAM_H (n).p_vaddr;
- NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz;
-
-#if 0 /* Maybe allow section after data2 - does this ever happen? */
- for (n = new_file_h->e_phnum; --n >= 0; )
- {
- if (NEW_PROGRAM_H (n).p_vaddr
- && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr)
- NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size;
+ new_bss_seg = new_program_h + (old_bss_seg - old_program_h);
+ new_bss_seg->p_filesz = new_bss_addr - new_bss_seg->p_vaddr;
+ new_bss_seg->p_memsz = new_bss_seg->p_filesz;
- if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset)
- NEW_PROGRAM_H (n).p_offset += new_data2_incr;
- }
-#endif
+ /* Copy over what we have in memory now for the bss area. */
+ memcpy (new_base + new_data2_offset, (caddr_t) old_bss_addr, new_data2_size);
/* Fix up section headers based on new .data2 section. Any section
whose offset or virtual address is after the new .data2 section
- gets its value adjusted. .bss size becomes zero and new address
- is set. data2 section header gets added by copying the existing
- .data header and modifying the offset, address and size. */
+ gets its value adjusted. .bss size becomes zero. data2 section
+ header gets added by copying the existing .data header and
+ modifying the offset, address and size. */
/* Walk through all section headers, insert the new data2 section right
before the new bss section. */
@@ -901,9 +803,7 @@ unexec (const char *new_name, const char
ElfW (Shdr) *new_shdr = &NEW_SECTION_H (nn);
/* If it is (s)bss section, insert the new data2 section before it. */
- /* new_data2_index is the index of either old_sbss or old_bss, that was
- chosen as a section for new_data2. */
- if (n == new_data2_index)
+ if (n == old_bss_index)
{
/* Steal the data section header for this data2 section. */
memcpy (new_shdr, &OLD_SECTION_H (old_data_index),
@@ -912,68 +812,43 @@ unexec (const char *new_name, const char
new_shdr->sh_addr = new_data2_addr;
new_shdr->sh_offset = new_data2_offset;
new_shdr->sh_size = new_data2_size;
- /* Use the bss section's alignment. This will assure that the
- new data2 section always be placed in the same spot as the old
- bss section by any other application. */
- new_shdr->sh_addralign = old_shdr->sh_addralign;
-
- /* Now copy over what we have in the memory now. */
- memcpy (new_shdr->sh_offset + new_base,
- (caddr_t) old_shdr->sh_addr,
- new_data2_size);
+ new_shdr->sh_addralign = 1;
nn++;
new_shdr++;
}
memcpy (new_shdr, old_shdr, old_file_h->e_shentsize);
- if (n == old_bss_index
- /* The new bss and sbss section's size is zero, and its file offset
- and virtual address should be off by NEW_DATA2_SIZE. */
- || n == old_sbss_index || n == old_plt_index
- )
+ if (new_shdr->sh_type == SHT_NOBITS
+ && new_shdr->sh_addr >= old_bss_addr
+ && (new_shdr->sh_addr + new_shdr->sh_size
+ <= old_bss_addr + old_bss_size))
{
- /* NN should be `old_s?bss_index + 1' at this point. */
- new_shdr->sh_offset = new_data2_offset + new_data2_size;
- new_shdr->sh_addr = new_data2_addr + new_data2_size;
- /* Let the new bss section address alignment be the same as the
- section address alignment followed the old bss section, so
- this section will be placed in exactly the same place. */
- new_shdr->sh_addralign = OLD_SECTION_H (nn).sh_addralign;
+ /* SHT_NOBITS sections do not need a valid sh_offset, so it
+ might be incorrect. Write the correct value. */
+ new_shdr->sh_offset = (new_shdr->sh_addr - new_bss_seg->p_vaddr
+ + new_bss_seg->p_offset);
+
+ /* If this is was a SHT_NOBITS .plt section, then it is
+ probably a PowerPC PLT. If it is PowerPC64 ELFv1 then
+ glibc ld.so doesn't initialize the toc pointer word. A
+ non-zero toc pointer word can defeat Power7 thread safety
+ during lazy update of a PLT entry. This only matters if
+ emacs becomes multi-threaded. */
+ if (strcmp (old_section_names + new_shdr->sh_name, ".plt") == 0)
+ memset (new_shdr->sh_offset + new_base, 0, new_shdr->sh_size);
+
+ /* Set the new bss and sbss section's size to zero, because
+ we've already covered this address range by .data2. */
new_shdr->sh_size = 0;
}
else
{
/* Any section that was originally placed after the .bss
- section should now be off by NEW_DATA2_INCR. If a
- section overlaps the .bss section, consider it to be
- placed after the .bss section. Overlap can occur if the
- section just before .bss has less-strict alignment; this
- was observed between .symtab and .bss on Solaris 2.5.1
- (sparc) with GCC snapshot 960602.
-
-> dump -h temacs
-
-temacs:
-
- **** SECTION HEADER TABLE ****
-[No] Type Flags Addr Offset Size Name
- Link Info Adralgn Entsize
-
-[22] 1 3 0x335150 0x315150 0x4 .data.rel.local
- 0 0 0x4 0
-
-[23] 8 3 0x335158 0x315158 0x42720 .bss
- 0 0 0x8 0
-
-[24] 2 0 0 0x315154 0x1c9d0 .symtab
- 25 1709 0x4 0x10
- */
-
- if (new_shdr->sh_offset >= old_bss_offset
- || (new_shdr->sh_offset + new_shdr->sh_size
- > new_data2_offset))
- new_shdr->sh_offset += new_data2_incr;
+ section should now be off by NEW_DATA2_SIZE. */
+
+ if (new_shdr->sh_offset >= old_bss_offset)
+ new_shdr->sh_offset += new_data2_size;
/* Any section that was originally placed after the section
header table should now be off by the size of one section
@@ -993,23 +868,13 @@ temacs:
&& new_shdr->sh_type != SHT_DYNSYM)
PATCH_INDEX (new_shdr->sh_info);
- if (old_sbss_index != -1)
- if (!strcmp (old_section_names + new_shdr->sh_name, ".sbss"))
- {
- new_shdr->sh_offset =
- round_up (new_shdr->sh_offset,
- new_shdr->sh_addralign);
- new_shdr->sh_type = SHT_PROGBITS;
- }
-
/* Now, start to copy the content of sections. */
if (new_shdr->sh_type == SHT_NULL
|| new_shdr->sh_type == SHT_NOBITS)
continue;
- /* Write out the sections. .data and .data1 (and data2, called
- ".data" in the strings table) get copied from the current process
- instead of the old file. */
+ /* Some sections are copied from the current process instead of
+ the old file. */
if (!strcmp (old_section_names + new_shdr->sh_name, ".data")
|| !strcmp (old_section_names + new_shdr->sh_name, ".sdata")
|| !strcmp (old_section_names + new_shdr->sh_name, ".lit4")
@@ -1038,8 +903,7 @@ temacs:
|| !strcmp (old_section_names + new_shdr->sh_name, ".got")
#endif
|| !strcmp (old_section_names + new_shdr->sh_name, ".sdata1")
- || !strcmp (old_section_names + new_shdr->sh_name, ".data1")
- || !strcmp (old_section_names + new_shdr->sh_name, ".sbss"))
+ || !strcmp (old_section_names + new_shdr->sh_name, ".data1"))
src = (caddr_t) old_shdr->sh_addr;
else
src = old_base + old_shdr->sh_offset;

View File

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

View File

@ -0,0 +1,41 @@
From 9b52726df50cc9b4fdfce2ed1dc114311dc60a93 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sun, 8 Nov 2015 09:36:14 -0800
Subject: * src/unexelf.c (NEW_PROGRAM_H): Remove unused macro (Bug#20614).
Emacs should build on ppc64el. A problem with the bss has been fixed.
This upstream patch has been added [9/10]:
* src/unexelf.c (NEW_PROGRAM_H): Remove unused macro (Bug#20614).
Origin: upstream, commit: 2ce0c0674eba9179ba57c537e387bc3f7b0e5b63
Bug: http://debbugs.gnu.org/20614
Bug-Debian: http://bugs.debian.org/808347
Added-by: Rob Browning <rlb@defaultvalue.org>
---
src/unexelf.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
Index: emacs-24.5/src/unexelf.c
===================================================================
--- emacs-24.5.orig/src/unexelf.c
+++ emacs-24.5/src/unexelf.c
@@ -208,8 +208,6 @@ entry_address (void *section_h, ptrdiff_
(*(ElfW (Shdr) *) entry_address (new_section_h, n, new_file_h->e_shentsize))
#define OLD_PROGRAM_H(n) \
(*(ElfW (Phdr) *) entry_address (old_program_h, n, old_file_h->e_phentsize))
-#define NEW_PROGRAM_H(n) \
- (*(ElfW (Phdr) *) entry_address (new_program_h, n, new_file_h->e_phentsize))
typedef unsigned char byte;
@@ -250,7 +248,7 @@ unexec (const char *new_name, const char
ElfW (Phdr) *old_bss_seg, *new_bss_seg;
ElfW (Addr) old_bss_addr, new_bss_addr;
ElfW (Word) old_bss_size, new_data2_size;
- ElfW (Off) old_bss_offset, new_data2_offset;
+ ElfW (Off) old_bss_offset, new_data2_offset;
ptrdiff_t n;
ptrdiff_t old_bss_index;

View File

@ -0,0 +1,64 @@
From 0de7316751e94c29aeb4b75731ac6e8c9eba77e6 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Mon, 16 Nov 2015 17:48:08 -0800
Subject: ELF unexec: align section header
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Emacs should build on ppc64el. A problem with the bss has been fixed.
This upstream patch has been added [10/10]:
ELF unexec: align section header
This ports the recent unexelf.c changes to Fedora x86-64
when configured with GCCs -fsanitize=undefined option.
* src/unexelf.c (unexec): Align new_data2_size to a multiple
of ElfW (Shdr)s alignment, so that NEW_SECTION_H returns a
pointer aligned appropriately for its type.
Origin: upstream, commit: c9fd597a4cffcae873b25381ee8cc755f0debe95
Bug: http://debbugs.gnu.org/20614
Bug-Debian: http://bugs.debian.org/808347
Added-by: Rob Browning <rlb@defaultvalue.org>
---
src/unexelf.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
Index: emacs-24.5/src/unexelf.c
===================================================================
--- emacs-24.5.orig/src/unexelf.c
+++ emacs-24.5/src/unexelf.c
@@ -247,7 +247,7 @@ unexec (const char *new_name, const char
ElfW (Phdr) *old_bss_seg, *new_bss_seg;
ElfW (Addr) old_bss_addr, new_bss_addr;
- ElfW (Word) old_bss_size, new_data2_size;
+ ElfW (Word) old_bss_size, bss_size_growth, new_data2_size;
ElfW (Off) old_bss_offset, new_data2_offset;
ptrdiff_t n;
@@ -332,7 +332,11 @@ unexec (const char *new_name, const char
new_break = sbrk (0);
new_bss_addr = (ElfW (Addr)) new_break;
- new_data2_size = new_bss_addr - old_bss_addr;
+ bss_size_growth = new_bss_addr - old_bss_addr;
+ new_data2_size = bss_size_growth;
+ new_data2_size += alignof (ElfW (Shdr)) - 1;
+ new_data2_size -= new_data2_size % alignof (ElfW (Shdr));
+
new_data2_offset = old_bss_offset;
#ifdef UNEXELF_DEBUG
@@ -400,7 +404,8 @@ unexec (const char *new_name, const char
new_bss_seg->p_memsz = new_bss_seg->p_filesz;
/* Copy over what we have in memory now for the bss area. */
- memcpy (new_base + new_data2_offset, (caddr_t) old_bss_addr, new_data2_size);
+ memcpy (new_base + new_data2_offset, (caddr_t) old_bss_addr,
+ bss_size_growth);
/* Walk through all section headers, copying data and updating. */
for (n = 1; n < old_file_h->e_shnum; n++)

View File

@ -32,6 +32,17 @@ Patch6: emacs-mercurial.patch
# http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=439f483be35a000e7a3bec6acf395ce4d54d6323
# http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=9c86325b69d75e9b17ff468f5a2220597979635f
Patch7: emacs-gdb-ascii.patch
# All upstreamed, see the patches for more info
Patch8: emacs-24-0010-ELF-unexec-Correct-section-header-index.patch
Patch9: emacs-24-0011-ELF-unexec-Tidy-code.patch
Patch10: emacs-24-0012-ELF-unexec-Merge-Alpha-and-MIPS-COFF-debug-handling.patch
Patch11: emacs-24-0013-ELF-unexec-Symbol-table-patching.patch
Patch12: emacs-24-0014-ELF-unexec-_OBJC_-symbols-in-bss-sections.patch
Patch13: emacs-24-0015-ELF-unexec-R_-_NONE-relocs.patch
Patch14: emacs-24-0016-ELF-unexec-Drive-from-PT_LOAD-header-rather-than-sec.patch
Patch15: emacs-24-0017-ELF-unexec-Don-t-insert-a-new-section.patch
Patch16: emacs-24-0018-src-unexelf.c-NEW_PROGRAM_H-Remove-unused-macro-Bug-.patch
Patch17: emacs-24-0019-ELF-unexec-align-section-header.patch
BuildRequires: atk-devel
BuildRequires: cairo-devel
@ -177,6 +188,16 @@ packages that add functionality to Emacs.
%patch5 -p1 -b .bbdb
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%patch17 -p1
autoconf
# We prefer our emacs.desktop file
@ -448,6 +469,9 @@ update-desktop-database &> /dev/null || :
%dir %{_datadir}/emacs/site-lisp/site-start.d
%changelog
* Mon Feb 15 2016 Jan Synáček <jsynacek@redhat.com> - 1:24.5-10
- fix build failure on ppc64le (#1306793)
* Mon Feb 8 2016 Jan Synáček <jsynacek@redhat.com> - 1:24.5-10
- refix: set default value for smime-CA-directory (#1131558)