From bb3be4ec8bac50c4d873b4159f54c38bb3f4cff8 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Mar 02 2017 15:23:55 +0000 Subject: import emacs-24.3-19.el7_3 --- diff --git a/SOURCES/emacs-0001-ppc64-fixes-prepatch.patch b/SOURCES/emacs-0001-ppc64-fixes-prepatch.patch new file mode 100644 index 0000000..55e93e7 --- /dev/null +++ b/SOURCES/emacs-0001-ppc64-fixes-prepatch.patch @@ -0,0 +1,436 @@ +From 7ffe5bd31f9cb53a37f91c5fd1a9b6ce0df51c81 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Tue, 24 May 2016 09:39:42 +0200 +Subject: [PATCH 01/11] ppc64 fixes prepatch + +--- + src/unexelf.c | 210 +++++++++++++++++++++++++++++----------------------------- + 1 file changed, 105 insertions(+), 105 deletions(-) + +diff --git a/src/unexelf.c b/src/unexelf.c +index d365940..483da6e 100644 +--- a/src/unexelf.c ++++ b/src/unexelf.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 1985-1988, 1990, 1992, 1999-2013 Free Software ++/* Copyright (C) 1985-1988, 1990, 1992, 1999-2015 Free Software + Foundation, Inc. + + This file is part of GNU Emacs. +@@ -386,18 +386,19 @@ temacs: + Instead we read the whole file, modify it, and write it out. */ + + #include +-#include ++#include "unexec.h" ++#include "lisp.h" + +-extern void fatal (const char *msgid, ...); +- +-#include ++#include ++#include ++#include ++#include + #include + #include + #include +-#include +-#include ++#include + #include +-#include ++ + #if !defined (__NetBSD__) && !defined (__OpenBSD__) + #include + #endif /* not __NetBSD__ and not __OpenBSD__ */ +@@ -519,6 +520,18 @@ typedef struct { + # define ElfW(type) ElfExpandBitsW (ELFSIZE, type) + #endif + ++/* The code often converts ElfW (Half) values like e_shentsize to ptrdiff_t; ++ check that this doesn't lose information. */ ++#include ++#include ++verify ((! TYPE_SIGNED (ElfW (Half)) ++ || PTRDIFF_MIN <= TYPE_MINIMUM (ElfW (Half))) ++ && TYPE_MAXIMUM (ElfW (Half)) <= PTRDIFF_MAX); ++ ++#ifdef UNEXELF_DEBUG ++# define DEBUG_LOG(expr) fprintf (stderr, #expr " 0x%jx\n", (uintmax_t) (expr)) ++#endif ++ + /* Get the address of a particular section or program header entry, + * accounting for the size of the entries. + */ +@@ -546,17 +559,21 @@ typedef struct { + Apr 23, 1996 + */ + ++static void * ++entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize) ++{ ++ char *h = section_h; ++ return h + idx * entsize; ++} ++ + #define OLD_SECTION_H(n) \ +- (*(ElfW (Shdr) *) ((byte *) old_section_h + old_file_h->e_shentsize * (n))) ++ (*(ElfW (Shdr) *) entry_address (old_section_h, n, old_file_h->e_shentsize)) + #define NEW_SECTION_H(n) \ +- (*(ElfW (Shdr) *) ((byte *) new_section_h + new_file_h->e_shentsize * (n))) ++ (*(ElfW (Shdr) *) entry_address (new_section_h, n, new_file_h->e_shentsize)) + #define NEW_PROGRAM_H(n) \ +- (*(ElfW (Phdr) *) ((byte *) new_program_h + new_file_h->e_phentsize * (n))) ++ (*(ElfW (Phdr) *) entry_address (new_program_h, n, new_file_h->e_phentsize)) + +-#define PATCH_INDEX(n) \ +- do { \ +- if ((int) (n) >= old_bss_index) \ +- (n)++; } while (0) ++#define PATCH_INDEX(n) ((n) += old_bss_index <= (n)) + typedef unsigned char byte; + + /* Round X up to a multiple of Y. */ +@@ -564,7 +581,7 @@ typedef unsigned char byte; + static ElfW (Addr) + round_up (ElfW (Addr) x, ElfW (Addr) y) + { +- int rem = x % y; ++ ElfW (Addr) rem = x % y; + if (rem == 0) + return x; + return x - rem + y; +@@ -575,33 +592,28 @@ round_up (ElfW (Addr) x, ElfW (Addr) y) + about the file we are looking in. + + If we don't find the section NAME, that is a fatal error +- if NOERROR is 0; we return -1 if NOERROR is nonzero. */ ++ if NOERROR is false; return -1 if NOERROR is true. */ + +-static int ++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, int noerror) ++ ElfW (Ehdr) *old_file_h, ElfW (Shdr) *old_section_h, ++ bool noerror) + { +- int idx; ++ ptrdiff_t idx; + + for (idx = 1; idx < old_file_h->e_shnum; idx++) + { +-#ifdef DEBUG +- fprintf (stderr, "Looking for %s - found %s\n", name, +- section_names + OLD_SECTION_H (idx).sh_name); ++ 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 (section_names + OLD_SECTION_H (idx).sh_name, +- name)) +- break; +- } +- if (idx == old_file_h->e_shnum) +- { +- if (noerror) +- return -1; +- else +- fatal ("Can't find %s in %s.\n", name, file_name); ++ if (strcmp (name, found_name) == 0) ++ return idx; + } + +- return idx; ++ if (! noerror) ++ fatal ("Can't find %s in %s", name, file_name); ++ return -1; + } + + /* **************************************************************** +@@ -616,11 +628,9 @@ find_section (const char *name, const char *section_names, const char *file_name + void + unexec (const char *new_name, const char *old_name) + { +- int new_file, old_file, new_file_size; +- +-#if defined (emacs) || !defined (DEBUG) ++ int new_file, old_file; ++ off_t new_file_size; + void *new_break; +-#endif + + /* Pointers to the base of the image of the two files. */ + caddr_t old_base, new_base; +@@ -647,30 +657,30 @@ unexec (const char *new_name, const char *old_name) + ElfW (Off) old_bss_offset; + ElfW (Word) new_data2_incr; + +- int n, nn; +- int old_bss_index, old_sbss_index, old_plt_index; +- int old_data_index, new_data2_index; ++ 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 +- int old_mdebug_index; ++ ptrdiff_t old_mdebug_index; + #endif + struct stat stat_buf; +- int old_file_size; ++ off_t old_file_size; + + /* Open the old file, allocate a buffer of the right size, and read + in the file contents. */ + +- old_file = open (old_name, O_RDONLY); ++ old_file = emacs_open (old_name, O_RDONLY, 0); + + if (old_file < 0) +- fatal ("Can't open %s for reading: errno %d\n", old_name, errno); ++ fatal ("Can't open %s for reading: %s", old_name, strerror (errno)); + +- if (fstat (old_file, &stat_buf) == -1) +- fatal ("Can't fstat (%s): errno %d\n", old_name, errno); ++ if (fstat (old_file, &stat_buf) != 0) ++ fatal ("Can't fstat (%s): %s", old_name, strerror (errno)); + + #if MAP_ANON == 0 +- mmap_fd = open ("/dev/zero", O_RDONLY); ++ mmap_fd = emacs_open ("/dev/zero", O_RDONLY, 0); + if (mmap_fd < 0) +- fatal ("Can't open /dev/zero for reading: errno %d\n", errno, 0); ++ fatal ("Can't open /dev/zero for reading: %s", strerror (errno)); + #endif + + /* We cannot use malloc here because that may use sbrk. If it does, +@@ -678,13 +688,15 @@ unexec (const char *new_name, const char *old_name) + extra careful to use the correct value of sbrk(0) after + allocating all buffers in the code below, which we aren't. */ + old_file_size = stat_buf.st_size; ++ if (! (0 <= old_file_size && old_file_size <= SIZE_MAX)) ++ fatal ("File size out of range"); + old_base = mmap (NULL, old_file_size, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, mmap_fd, 0); + if (old_base == MAP_FAILED) +- fatal ("Can't allocate buffer for %s\n", old_name, 0); ++ fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno)); + +- if (read (old_file, old_base, stat_buf.st_size) != stat_buf.st_size) +- fatal ("Didn't read all of %s: errno %d\n", old_name, errno); ++ if (read (old_file, old_base, old_file_size) != old_file_size) ++ fatal ("Didn't read all of %s: %s", old_name, strerror (errno)); + + /* Get pointers to headers & section names */ + +@@ -755,12 +767,8 @@ unexec (const char *new_name, const char *old_name) + old_data_index = find_section (".data", old_section_names, + old_name, old_file_h, old_section_h, 0); + +-#if defined (emacs) || !defined (DEBUG) + new_break = sbrk (0); + new_bss_addr = (ElfW (Addr)) new_break; +-#else +- new_bss_addr = old_bss_addr + old_bss_size + 0x1234; +-#endif + 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 +@@ -771,38 +779,38 @@ unexec (const char *new_name, const char *old_name) + section) was unaligned. */ + new_data2_incr = new_data2_size + (new_data2_offset - old_bss_offset); + +-#ifdef DEBUG +- fprintf (stderr, "old_bss_index %d\n", old_bss_index); +- fprintf (stderr, "old_bss_addr %x\n", old_bss_addr); +- fprintf (stderr, "old_bss_size %x\n", old_bss_size); +- fprintf (stderr, "old_bss_offset %x\n", old_bss_offset); +- fprintf (stderr, "new_bss_addr %x\n", new_bss_addr); +- fprintf (stderr, "new_data2_addr %x\n", new_data2_addr); +- fprintf (stderr, "new_data2_size %x\n", new_data2_size); +- fprintf (stderr, "new_data2_offset %x\n", new_data2_offset); +- fprintf (stderr, "new_data2_incr %x\n", new_data2_incr); ++#ifdef UNEXELF_DEBUG ++ fprintf (stderr, "old_bss_index %td\n", old_bss_index); ++ DEBUG_LOG (old_bss_addr); ++ 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); ++ DEBUG_LOG (new_data2_incr); + #endif + +- if ((uintptr_t) new_bss_addr < (uintptr_t) old_bss_addr + old_bss_size) +- fatal (".bss shrank when undumping???\n", 0, 0); ++ if (new_bss_addr < old_bss_addr + old_bss_size) ++ fatal (".bss shrank when undumping"); + + /* Set the output file to the right size. Allocate a buffer to hold + the image of the new file. Set pointers to various interesting +- objects. stat_buf still has old_file data. */ ++ objects. */ + +- new_file = open (new_name, O_RDWR | O_CREAT, 0666); ++ new_file = emacs_open (new_name, O_RDWR | O_CREAT, 0777); + if (new_file < 0) +- fatal ("Can't creat (%s): errno %d\n", new_name, errno); ++ fatal ("Can't creat (%s): %s", new_name, strerror (errno)); + +- new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_incr; ++ new_file_size = old_file_size + old_file_h->e_shentsize + new_data2_incr; + + if (ftruncate (new_file, new_file_size)) +- fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno); ++ fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno)); + + new_base = mmap (NULL, new_file_size, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, mmap_fd, 0); + if (new_base == MAP_FAILED) +- fatal ("Can't allocate buffer for %s\n", old_name, 0); ++ 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); +@@ -825,11 +833,11 @@ unexec (const char *new_name, const char *old_name) + new_file_h->e_shoff += new_data2_incr; + new_file_h->e_shnum += 1; + +-#ifdef DEBUG +- fprintf (stderr, "Old section offset %x\n", old_file_h->e_shoff); +- fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum); +- fprintf (stderr, "New section offset %x\n", new_file_h->e_shoff); +- fprintf (stderr, "New section count %d\n", new_file_h->e_shnum); ++#ifdef UNEXELF_DEBUG ++ DEBUG_LOG (old_file_h->e_shoff); ++ fprintf (stderr, "Old section count %td\n", (ptrdiff_t) old_file_h->e_shnum); ++ DEBUG_LOG (new_file_h->e_shoff); ++ 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 +@@ -839,7 +847,7 @@ unexec (const char *new_name, const char *old_name) + to adjust the offset and address of any segment that is above + data2, just in case we decide to allow this later. */ + +- for (n = new_file_h->e_phnum - 1; n >= 0; n--) ++ 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; +@@ -857,7 +865,7 @@ unexec (const char *new_name, const char *old_name) + > (old_sbss_index == -1 + ? old_bss_addr + : round_up (old_bss_addr, alignment))) +- fatal ("Program segment above .bss in %s\n", old_name, 0); ++ 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 +@@ -867,7 +875,7 @@ unexec (const char *new_name, const char *old_name) + break; + } + if (n < 0) +- fatal ("Couldn't find segment next to .bss in %s\n", old_name, 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. */ +@@ -875,7 +883,7 @@ unexec (const char *new_name, const char *old_name) + 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 - 1; n >= 0; n--) ++ 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) +@@ -894,7 +902,7 @@ unexec (const char *new_name, const char *old_name) + + /* Walk through all section headers, insert the new data2 section right + before the new bss section. */ +- for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++) ++ for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++) + { + caddr_t src; + /* If it is (s)bss section, insert the new data2 section before it. */ +@@ -1076,8 +1084,9 @@ temacs: + if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG + && old_mdebug_index != -1) + { +- int diff = NEW_SECTION_H (nn).sh_offset +- - OLD_SECTION_H (old_mdebug_index).sh_offset; ++ ptrdiff_t new_offset = NEW_SECTION_H (nn).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); + + if (diff) +@@ -1157,7 +1166,7 @@ temacs: + || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) + { + ElfW (Shdr) *spt = &NEW_SECTION_H (nn); +- unsigned int num = spt->sh_size / spt->sh_entsize; ++ ptrdiff_t num = spt->sh_size / spt->sh_entsize; + ElfW (Sym) * sym = (ElfW (Sym) *) (NEW_SECTION_H (nn).sh_offset + + new_base); + for (; num--; sym++) +@@ -1173,7 +1182,7 @@ temacs: + } + + /* Update the symbol values of _edata and _end. */ +- for (n = new_file_h->e_shnum - 1; n; n--) ++ for (n = new_file_h->e_shnum; 0 < --n; ) + { + byte *symnames; + ElfW (Sym) *symp, *symendp; +@@ -1233,7 +1242,7 @@ temacs: + + /* This loop seeks out relocation sections for the data section, so + that it can undo relocations performed by the runtime linker. */ +- for (n = new_file_h->e_shnum - 1; n; n--) ++ for (n = new_file_h->e_shnum; 0 < --n; ) + { + ElfW (Shdr) section = NEW_SECTION_H (n); + +@@ -1293,29 +1302,20 @@ temacs: + /* Write out new_file, and free the buffers. */ + + if (write (new_file, new_base, new_file_size) != new_file_size) +- fatal ("Didn't write %d bytes to %s: errno %d\n", +- new_file_size, new_name, errno); ++ fatal ("Didn't write %lu bytes to %s: %s", ++ (unsigned long) new_file_size, new_name, strerror (errno)); + munmap (old_base, old_file_size); + munmap (new_base, new_file_size); + + /* Close the files and make the new file executable. */ + + #if MAP_ANON == 0 +- close (mmap_fd); ++ emacs_close (mmap_fd); + #endif + +- if (close (old_file)) +- fatal ("Can't close (%s): errno %d\n", old_name, errno); +- +- if (close (new_file)) +- fatal ("Can't close (%s): errno %d\n", new_name, errno); +- +- if (stat (new_name, &stat_buf) == -1) +- fatal ("Can't stat (%s): errno %d\n", new_name, errno); ++ if (emacs_close (old_file) != 0) ++ fatal ("Can't close (%s): %s", old_name, strerror (errno)); + +- n = umask (777); +- umask (n); +- stat_buf.st_mode |= 0111 & ~n; +- if (chmod (new_name, stat_buf.st_mode) == -1) +- fatal ("Can't chmod (%s): errno %d\n", new_name, errno); ++ if (emacs_close (new_file) != 0) ++ fatal ("Can't close (%s): %s", new_name, strerror (errno)); + } +-- +2.7.4 + diff --git a/SOURCES/emacs-0002-ELF-unexec-Correct-section-header-index.patch b/SOURCES/emacs-0002-ELF-unexec-Correct-section-header-index.patch new file mode 100644 index 0000000..760d934 --- /dev/null +++ b/SOURCES/emacs-0002-ELF-unexec-Correct-section-header-index.patch @@ -0,0 +1,61 @@ +From acfdfce2687342a119d4fe7cae8f5d04550a9d4a Mon Sep 17 00:00:00 2001 +From: Alan Modra +Date: Sun, 8 Nov 2015 09:28:59 -0800 +Subject: [PATCH 02/11] 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. +--- + src/unexelf.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/src/unexelf.c b/src/unexelf.c +index 483da6e..1699f31 100644 +--- a/src/unexelf.c ++++ b/src/unexelf.c +@@ -1015,12 +1015,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 +@@ -1043,14 +1043,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 +-- +2.7.4 + diff --git a/SOURCES/emacs-0003-ELF-unexec-Tidy-code.patch b/SOURCES/emacs-0003-ELF-unexec-Tidy-code.patch new file mode 100644 index 0000000..7ecaa3a --- /dev/null +++ b/SOURCES/emacs-0003-ELF-unexec-Tidy-code.patch @@ -0,0 +1,414 @@ +From c7ffdf36d7eb5ed8044818902d4c69516d09dbb2 Mon Sep 17 00:00:00 2001 +From: Alan Modra +Date: Sun, 8 Nov 2015 09:28:59 -0800 +Subject: [PATCH 03/11] 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. +--- + src/unexelf.c | 210 +++++++++++++++++++++++++++------------------------------- + 1 file changed, 96 insertions(+), 114 deletions(-) + +diff --git a/src/unexelf.c b/src/unexelf.c +index 1699f31..d6c6648 100644 +--- a/src/unexelf.c ++++ b/src/unexelf.c +@@ -812,20 +812,11 @@ unexec (const char *new_name, const char *old_name) + 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. */ +@@ -833,6 +824,16 @@ unexec (const char *new_name, const char *old_name) + 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); +@@ -905,32 +906,35 @@ unexec (const char *new_name, const char *old_name) + 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 +@@ -939,13 +943,13 @@ unexec (const char *new_name, const char *old_name) + ) + { + /* 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 + { +@@ -975,53 +979,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 +@@ -1043,28 +1044,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; +@@ -1081,13 +1076,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) + { +@@ -1123,8 +1118,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); +@@ -1141,8 +1136,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. +@@ -1162,13 +1157,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) +@@ -1186,15 +1179,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 ++) + { +@@ -1218,22 +1212,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 +@@ -1244,13 +1237,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; +@@ -1259,28 +1249,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__ +@@ -1295,8 +1279,6 @@ temacs: + } + break; + } +- +- #undef n + } + + /* Write out new_file, and free the buffers. */ +-- +2.7.4 + diff --git a/SOURCES/emacs-0004-ELF-unexec-Merge-Alpha-and-MIPS-COFF-debug-handling.patch b/SOURCES/emacs-0004-ELF-unexec-Merge-Alpha-and-MIPS-COFF-debug-handling.patch new file mode 100644 index 0000000..1a58328 --- /dev/null +++ b/SOURCES/emacs-0004-ELF-unexec-Merge-Alpha-and-MIPS-COFF-debug-handling.patch @@ -0,0 +1,166 @@ +From 14e5f5be6a45f6d238a47b117d9dc9e3eb36a380 Mon Sep 17 00:00:00 2001 +From: Alan Modra +Date: Sun, 8 Nov 2015 09:28:59 -0800 +Subject: [PATCH 04/11] 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. +--- + src/unexelf.c | 96 ++++++++++++++++++----------------------------------------- + 1 file changed, 29 insertions(+), 67 deletions(-) + +diff --git a/src/unexelf.c b/src/unexelf.c +index d6c6648..0065491 100644 +--- a/src/unexelf.c ++++ b/src/unexelf.c +@@ -660,9 +660,6 @@ unexec (const char *new_name, const char *old_name) + 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; + +@@ -706,13 +703,6 @@ unexec (const char *new_name, const char *old_name) + 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. */ + +@@ -1055,51 +1045,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 +@@ -1110,7 +1080,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) \ +@@ -1120,7 +1091,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); +@@ -1136,22 +1107,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 */ +-- +2.7.4 + diff --git a/SOURCES/emacs-0005-ELF-unexec-Symbol-table-patching.patch b/SOURCES/emacs-0005-ELF-unexec-Symbol-table-patching.patch new file mode 100644 index 0000000..14e07f7 --- /dev/null +++ b/SOURCES/emacs-0005-ELF-unexec-Symbol-table-patching.patch @@ -0,0 +1,42 @@ +From b99e034e9696f745d8da4742251bb538e0841f63 Mon Sep 17 00:00:00 2001 +From: Alan Modra +Date: Sun, 8 Nov 2015 09:29:00 -0800 +Subject: [PATCH 05/11] 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. +--- + src/unexelf.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/src/unexelf.c b/src/unexelf.c +index 0065491..286ba2e 100644 +--- a/src/unexelf.c ++++ b/src/unexelf.c +@@ -1118,7 +1118,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) + { +@@ -1126,9 +1126,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); +-- +2.7.4 + diff --git a/SOURCES/emacs-0006-ELF-unexec-_OBJC_-symbols-in-bss-sections.patch b/SOURCES/emacs-0006-ELF-unexec-_OBJC_-symbols-in-bss-sections.patch new file mode 100644 index 0000000..bc6e417 --- /dev/null +++ b/SOURCES/emacs-0006-ELF-unexec-_OBJC_-symbols-in-bss-sections.patch @@ -0,0 +1,62 @@ +From 8c30fba366c6814c7bb1795fdda16265eb48efb0 Mon Sep 17 00:00:00 2001 +From: Alan Modra +Date: Sun, 8 Nov 2015 09:29:00 -0800 +Subject: [PATCH 06/11] 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. +--- + src/unexelf.c | 31 ++++++++++++++++++------------- + 1 file changed, 18 insertions(+), 13 deletions(-) + +diff --git a/src/unexelf.c b/src/unexelf.c +index 286ba2e..df99f92 100644 +--- a/src/unexelf.c ++++ b/src/unexelf.c +@@ -1176,20 +1176,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 +-- +2.7.4 + diff --git a/SOURCES/emacs-0007-ELF-unexec-R_-_NONE-relocs.patch b/SOURCES/emacs-0007-ELF-unexec-R_-_NONE-relocs.patch new file mode 100644 index 0000000..fd39f28 --- /dev/null +++ b/SOURCES/emacs-0007-ELF-unexec-R_-_NONE-relocs.patch @@ -0,0 +1,50 @@ +From c00b42d59c296ef9b0660afd7b31e1d3c10972e7 Mon Sep 17 00:00:00 2001 +From: Alan Modra +Date: Sun, 8 Nov 2015 09:29:00 -0800 +Subject: [PATCH 07/11] 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. +--- + src/unexelf.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/src/unexelf.c b/src/unexelf.c +index df99f92..15a4cde 100644 +--- a/src/unexelf.c ++++ b/src/unexelf.c +@@ -1202,7 +1202,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); +@@ -1235,14 +1235,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; +-- +2.7.4 + diff --git a/SOURCES/emacs-0008-ELF-unexec-Drive-from-PT_LOAD-header-rather-than-sec.patch b/SOURCES/emacs-0008-ELF-unexec-Drive-from-PT_LOAD-header-rather-than-sec.patch new file mode 100644 index 0000000..b64e361 --- /dev/null +++ b/SOURCES/emacs-0008-ELF-unexec-Drive-from-PT_LOAD-header-rather-than-sec.patch @@ -0,0 +1,473 @@ +From a2085a540975a1e6660dbc3b0c092789f002703e Mon Sep 17 00:00:00 2001 +From: Alan Modra +Date: Sun, 8 Nov 2015 09:29:00 -0800 +Subject: [PATCH 08/11] 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) +--- + src/unexelf.c | 290 ++++++++++++++++------------------------------------------ + 1 file changed, 77 insertions(+), 213 deletions(-) + +diff --git a/src/unexelf.c b/src/unexelf.c +index 15a4cde..4e9c50d 100644 +--- a/src/unexelf.c ++++ b/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_t idx, ptrdiff_t entsize) + (*(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 *old_name) + /* 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; + +@@ -703,54 +670,40 @@ unexec (const char *new_name, const char *old_name) + 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. */ + +@@ -761,13 +714,7 @@ unexec (const char *new_name, const char *old_name) + 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); +@@ -778,7 +725,6 @@ unexec (const char *new_name, const char *old_name) + 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) +@@ -792,7 +738,7 @@ unexec (const char *new_name, const char *old_name) + 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)); +@@ -811,15 +757,15 @@ unexec (const char *new_name, const char *old_name) + /* 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); +@@ -831,65 +777,21 @@ unexec (const char *new_name, const char *old_name) + 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. */ +@@ -900,9 +802,7 @@ unexec (const char *new_name, const char *old_name) + 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), +@@ -911,68 +811,43 @@ unexec (const char *new_name, const char *old_name) + 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. ++ section should now be off by NEW_DATA2_SIZE. */ + +-> 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; ++ 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 +@@ -992,23 +867,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") +@@ -1037,8 +902,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; +-- +2.7.4 + diff --git a/SOURCES/emacs-0009-ELF-unexec-Don-t-insert-a-new-section.patch b/SOURCES/emacs-0009-ELF-unexec-Don-t-insert-a-new-section.patch new file mode 100644 index 0000000..db4bb4b --- /dev/null +++ b/SOURCES/emacs-0009-ELF-unexec-Don-t-insert-a-new-section.patch @@ -0,0 +1,697 @@ +From 76b336e1655c8eacaf17a362c3c59d6103357c09 Mon Sep 17 00:00:00 2001 +From: Alan Modra +Date: Sun, 8 Nov 2015 09:29:00 -0800 +Subject: [PATCH 09/11] 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. +--- + src/unexelf.c | 524 ++++++---------------------------------------------------- + 1 file changed, 50 insertions(+), 474 deletions(-) + +diff --git a/src/unexelf.c b/src/unexelf.c +index 4e9c50d..85ed934 100644 +--- a/src/unexelf.c ++++ b/src/unexelf.c +@@ -40,347 +40,6 @@ what you give them. Help stamp out software-hoarding! */ + * 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_t idx, ptrdiff_t entsize) + #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 *old_name) + 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; + +@@ -688,7 +315,7 @@ unexec (const char *new_name, const char *old_name) + 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; ) + { +@@ -697,22 +324,15 @@ unexec (const char *new_name, const char *old_name) + && 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; + +@@ -722,7 +342,6 @@ unexec (const char *new_name, const char *old_name) + 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 +@@ -738,7 +357,7 @@ unexec (const char *new_name, const char *old_name) + 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)); +@@ -754,21 +373,18 @@ unexec (const char *new_name, const char *old_name) + 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); +@@ -787,42 +403,21 @@ unexec (const char *new_name, const char *old_name) + /* 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 +@@ -837,35 +432,20 @@ unexec (const char *new_name, const char *old_name) + 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. */ ++ /* 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; + +- 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; ++ /* 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 +@@ -981,24 +561,6 @@ unexec (const char *new_name, const char *old_name) + } + } + #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. */ +@@ -1042,15 +604,10 @@ unexec (const char *new_name, const char *old_name) + 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 +@@ -1065,6 +622,25 @@ unexec (const char *new_name, const char *old_name) + } + } + ++ /* 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; ) +-- +2.7.4 + diff --git a/SOURCES/emacs-0010-src-unexelf.c-NEW_PROGRAM_H-Remove-unused-macro-Bug-.patch b/SOURCES/emacs-0010-src-unexelf.c-NEW_PROGRAM_H-Remove-unused-macro-Bug-.patch new file mode 100644 index 0000000..7aa9324 --- /dev/null +++ b/SOURCES/emacs-0010-src-unexelf.c-NEW_PROGRAM_H-Remove-unused-macro-Bug-.patch @@ -0,0 +1,35 @@ +From b9df09624d31c34bb214a4df6f24aef3c3c37d1c Mon Sep 17 00:00:00 2001 +From: Paul Eggert +Date: Sun, 8 Nov 2015 09:36:14 -0800 +Subject: [PATCH 10/11] * src/unexelf.c (NEW_PROGRAM_H): Remove unused macro + (Bug#20614). + +--- + src/unexelf.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/src/unexelf.c b/src/unexelf.c +index 85ed934..c10c7f2 100644 +--- a/src/unexelf.c ++++ b/src/unexelf.c +@@ -208,8 +208,6 @@ entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize) + (*(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 *old_name) + 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; +-- +2.7.4 + diff --git a/SOURCES/emacs-0011-ELF-unexec-align-section-header.patch b/SOURCES/emacs-0011-ELF-unexec-align-section-header.patch new file mode 100644 index 0000000..c379805 --- /dev/null +++ b/SOURCES/emacs-0011-ELF-unexec-align-section-header.patch @@ -0,0 +1,56 @@ +From cb83c302eb77748a99940fa41026d5f373976478 Mon Sep 17 00:00:00 2001 +From: Paul Eggert +Date: Mon, 16 Nov 2015 17:48:08 -0800 +Subject: [PATCH 11/11] ELF unexec: align section header +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This ports the recent unexelf.c changes to Fedora x86-64 +when configured with GCC’s -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. +--- + src/unexelf.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/src/unexelf.c b/src/unexelf.c +index c10c7f2..03e6daf 100644 +--- a/src/unexelf.c ++++ b/src/unexelf.c +@@ -247,7 +247,7 @@ unexec (const char *new_name, const char *old_name) + + 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; +@@ -331,7 +331,11 @@ unexec (const char *new_name, const char *old_name) + + 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 +@@ -399,7 +403,8 @@ unexec (const char *new_name, const char *old_name) + 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++) +-- +2.7.4 + diff --git a/SOURCES/emacs-environment-crash.patch b/SOURCES/emacs-environment-crash.patch new file mode 100644 index 0000000..a164d9e --- /dev/null +++ b/SOURCES/emacs-environment-crash.patch @@ -0,0 +1,94 @@ +Upstream report: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=13054 +Upstream commit: 21e54a94d7527e07ddc37066c8cb488f478339c9 +Resolves: #1308518 + +--- emacs-24.3/src/callproc.c 2013-02-02 04:20:04.000000000 +0100 ++++ emacs-24.3-new/src/callproc.c 2016-02-29 08:24:53.628487375 +0100 +@@ -491,9 +491,6 @@ usage: (call-process PROGRAM &optional I + } + + { +- /* child_setup must clobber environ in systems with true vfork. +- Protect it from permanent change. */ +- register char **save_environ = environ; + register int fd1 = fd[1]; + int fd_error = fd1; + +@@ -640,8 +637,6 @@ usage: (call-process PROGRAM &optional I + emacs_close (fd_error); + #endif /* not MSDOS */ + +- environ = save_environ; +- + /* Close most of our fd's, but not fd[0] + since we will use that to read input from. */ + emacs_close (filefd); +@@ -1098,10 +1093,6 @@ add_env (char **env, char **new_env, cha + Initialize inferior's priority, pgrp, connected dir and environment. + then exec another program based on new_argv. + +- This function may change environ for the superior process. +- Therefore, the superior process must save and restore the value +- of environ around the vfork and the call to this function. +- + If SET_PGRP, put the subprocess into a separate process group. + + CURRENT_DIR is an elisp string giving the path of the current +@@ -1308,11 +1299,7 @@ child_setup (int in, int out, int err, c + /* setpgrp_of_tty is incorrect here; it uses input_fd. */ + tcsetpgrp (0, pid); + +- /* execvp does not accept an environment arg so the only way +- to pass this environment is to set environ. Our caller +- is responsible for restoring the ambient value of environ. */ +- environ = env; +- execvp (new_argv[0], new_argv); ++ execve (new_argv[0], new_argv, env); + + emacs_write (1, "Can't exec program: ", 20); + emacs_write (1, new_argv[0], strlen (new_argv[0])); +--- emacs-24.3/src/process.c 2013-01-01 21:37:17.000000000 +0100 ++++ emacs-24.3-new/src/process.c 2016-02-29 08:23:23.218671832 +0100 +@@ -1606,9 +1606,6 @@ create_process (Lisp_Object process, cha + volatile int pty_flag = 0; + volatile Lisp_Object lisp_pty_name = Qnil; + volatile Lisp_Object encoded_current_dir; +-#if HAVE_WORKING_VFORK +- char **volatile save_environ; +-#endif + + inchannel = outchannel = -1; + +@@ -1728,12 +1725,6 @@ create_process (Lisp_Object process, cha + pthread_sigmask (SIG_BLOCK, &blocked, 0); + #endif + +-#if HAVE_WORKING_VFORK +- /* child_setup must clobber environ on systems with true vfork. +- Protect it from permanent change. */ +- save_environ = environ; +-#endif +- + #ifndef WINDOWSNT + pid = vfork (); + if (pid == 0) +@@ -1875,10 +1866,6 @@ create_process (Lisp_Object process, cha + + /* Back in the parent process. */ + +-#if HAVE_WORKING_VFORK +- environ = save_environ; +-#endif +- + XPROCESS (process)->pid = pid; + + /* Stop blocking signals in the parent. */ +@@ -1928,7 +1915,7 @@ create_process (Lisp_Object process, cha + /* Wait for child_setup to complete in case that vfork is + actually defined as fork. The descriptor wait_child_setup[1] + of a pipe is closed at the child side either by close-on-exec +- on successful execvp or the _exit call in child_setup. */ ++ on successful execve or the _exit call in child_setup. */ + { + char dummy; + diff --git a/SOURCES/emacs-segment-bss.patch b/SOURCES/emacs-segment-bss.patch deleted file mode 100644 index b2fd01d..0000000 --- a/SOURCES/emacs-segment-bss.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/src/unexelf.c b/src/unexelf.c -index d365940..f78f85a 100644 ---- a/src/unexelf.c -+++ b/src/unexelf.c -@@ -717,7 +717,14 @@ unexec (const char *new_name, const char *old_name) - 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) -+ if (OLD_SECTION_H (old_plt_index).sh_type != SHT_NOBITS -+ || ((OLD_SECTION_H (old_plt_index).sh_addr -+ + OLD_SECTION_H (old_plt_index).sh_size -+ != OLD_SECTION_H (old_bss_index).sh_addr) -+ && (old_sbss_index == -1 -+ || (OLD_SECTION_H (old_plt_index).sh_addr -+ + OLD_SECTION_H (old_plt_index).sh_size -+ != OLD_SECTION_H (old_sbss_index).sh_addr)))) - old_plt_index = -1; - - if (old_sbss_index == -1 && old_plt_index == -1) diff --git a/SPECS/emacs.spec b/SPECS/emacs.spec index 4089c22..a5d59c4 100644 --- a/SPECS/emacs.spec +++ b/SPECS/emacs.spec @@ -4,7 +4,7 @@ Summary: GNU Emacs text editor Name: emacs Epoch: 1 Version: 24.3 -Release: 18%{?dist} +Release: 19%{?dist} License: GPLv3+ URL: http://www.gnu.org/software/emacs/ Group: Applications/Editors @@ -30,7 +30,19 @@ Patch13: emacs-help-update.patch # Fix for emacs counts used memory incorrectly #107836 Patch14: emacs-remove-memory-warning.patch # Fix for emacs building under ppc64le -Patch15: emacs-segment-bss.patch +Patch16: emacs-0001-ppc64-fixes-prepatch.patch +Patch17: emacs-0002-ELF-unexec-Correct-section-header-index.patch +Patch18: emacs-0003-ELF-unexec-Tidy-code.patch +Patch19: emacs-0004-ELF-unexec-Merge-Alpha-and-MIPS-COFF-debug-handling.patch +Patch20: emacs-0005-ELF-unexec-Symbol-table-patching.patch +Patch21: emacs-0006-ELF-unexec-_OBJC_-symbols-in-bss-sections.patch +Patch22: emacs-0007-ELF-unexec-R_-_NONE-relocs.patch +Patch23: emacs-0008-ELF-unexec-Drive-from-PT_LOAD-header-rather-than-sec.patch +Patch24: emacs-0009-ELF-unexec-Don-t-insert-a-new-section.patch +Patch25: emacs-0010-src-unexelf.c-NEW_PROGRAM_H-Remove-unused-macro-Bug-.patch +Patch26: emacs-0011-ELF-unexec-align-section-header.patch +# Fix for #1308518, upstreamed +Patch27: emacs-environment-crash.patch # Fix for emacs bug #13460. Patch100: emacs-24.3-hunspell.patch # Fix for emacs bug #827033 @@ -179,7 +191,18 @@ packages that add functionality to Emacs. %patch12 -p1 -b .gtk-warning.patch %patch13 -p1 -b .help-update.patch %patch14 -p1 -b .remove-warning.patch -%patch15 -p1 -b .segment +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 +%patch20 -p1 +%patch21 -p1 +%patch22 -p1 +%patch23 -p1 +%patch24 -p1 +%patch25 -p1 +%patch26 -p1 +%patch27 -p1 %patch100 -p1 -b .hunspell %patch101 -p1 -b .hunspell.2 @@ -484,6 +507,10 @@ update-desktop-database &> /dev/null || : %dir %{_datadir}/emacs/site-lisp/site-start.d %changelog +* Fri Jan 6 2017 Jan Synáček - 1:24.3-19 +- fix build failure on ppc64 (#1336711) +- fix emacs crashes (#1308518) + * Wed Oct 07 2015 Petr Hracek - 1:24.3-18 - Fix for sbit on emacs binary - Related: #1223033