View | Details | Raw Unified
Collapse All | Expand All

(-) emacs-18.59-orig/src/ChangeLog (+4 lines)
 Lines 1-3    Link Here 
2004-03-08  Ulrich Mueller  <ulm@kph.uni-mainz.de>
	* unexelf.c: Replaced with version from Emacs 21.3.
1999-11-05  Noah Friedman  <friedman@splode.com>
1999-11-05  Noah Friedman  <friedman@splode.com>
	* ymakefile [LIBS_TERMCAP]: Use -lncurses, not -lcurses.
	* ymakefile [LIBS_TERMCAP]: Use -lncurses, not -lcurses.
(-) emacs-18.59-orig/src/unexelf.c (-113 / +501 lines)
 Lines 1-4    Link Here 
/* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992
/* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992, 1999, 2000, 01, 02
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
This file is part of GNU Emacs.
This file is part of GNU Emacs.
 Lines 33-46    Link Here 
 * Modified heavily since then.
 * Modified heavily since then.
 *
 *
 * Synopsis:
 * Synopsis:
 *	unexec (new_name, a_name, data_start, bss_start, entry_address)
 *	unexec (new_name, old_name, data_start, bss_start, entry_address)
 *	char *new_name, *a_name;
 *	char *new_name, *old_name;
 *	unsigned data_start, bss_start, entry_address;
 *	unsigned data_start, bss_start, entry_address;
 *
 *
 * Takes a snapshot of the program and makes an a.out format file in the
 * Takes a snapshot of the program and makes an a.out format file in the
 * file named by the string argument new_name.
 * file named by the string argument new_name.
 * If a_name is non-NULL, the symbol table will be taken from the given file.
 * If old_name is non-NULL, the symbol table will be taken from the given file.
 * On some machines, an existing a_name file is required.
 * On some machines, an existing old_name file is required.
 *
 *
 * The boundaries within the a.out file may be adjusted with the data_start
 * The boundaries within the a.out file may be adjusted with the data_start
 * and bss_start arguments.  Either or both may be given as 0 for defaults.
 * and bss_start arguments.  Either or both may be given as 0 for defaults.
 Lines 52-62    Link Here 
 * The value you specify may be rounded down to a suitable boundary
 * The value you specify may be rounded down to a suitable boundary
 * as required by the machine you are using.
 * as required by the machine you are using.
 *
 *
 * Specifying zero for data_start means the boundary between text and data
 * should not be the same as when the program was loaded.
 * If NO_REMAP is defined, the argument data_start is ignored and the
 * segment boundaries are never changed.
 *
 * Bss_start indicates how much of the data segment is to be saved in the
 * Bss_start indicates how much of the data segment is to be saved in the
 * a.out file and restored when the program is executed.  It gives the lowest
 * a.out file and restored when the program is executed.  It gives the lowest
 * unsaved address, and is rounded up to a page boundary.  The default when 0
 * unsaved address, and is rounded up to a page boundary.  The default when 0
 Lines 66-74    Link Here 
 *
 *
 * The new file is set up to start at entry_address.
 * The new file is set up to start at entry_address.
 *
 *
 * If you make improvements I'd like to get them too.
 * harpo!utah-cs!thomas, thomas@Utah-20
 *
 */
 */
/* Even more heavily modified by james@bigtex.cactus.org of Dell Computer Co.
/* Even more heavily modified by james@bigtex.cactus.org of Dell Computer Co.
 Lines 412-433    Link Here 
 */
 */


/*
 * Modified by rdh@yottayotta.com of Yotta Yotta Incorporated.
 * 
 * The code originally used mmap() to create a memory image of the new
 * and old object files.  This had a few handy features: (1) you get
 * to use a cool system call like mmap, (2) no need to explicitly
 * write out the new file before the close, and (3) no swap space
 * requirements.  Unfortunately, mmap() often fails to work with
 * nfs-mounted file systems.
 *
 * So, instead of relying on the vm subsystem to do the file i/o for
 * us, it's now done explicitly.  A buffer of the right size for the
 * file is dynamically allocated, and either the old_name is read into
 * it, or it is initialized with the correct new executable contents,
 * and then written to new_name.
 */

#ifndef emacs
#define fatal(a, b, c) fprintf (stderr, a, b, c), exit (1)
#include <string.h>
#else
#include "config.h"
extern void fatal (char *, ...);
#endif
#include <sys/types.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/stat.h>
#include <memory.h>
#include <memory.h>
#include <string.h>
#include <errno.h>
#include <errno.h>
#include <unistd.h>
#include <unistd.h>
#include <fcntl.h>
#include <fcntl.h>
#if !defined (__NetBSD__) && !defined (__OpenBSD__)
#include <elf.h>
#include <elf.h>
#endif
#include <sys/mman.h>
#include <sys/mman.h>
#if defined (__sony_news) && defined (_SYSTYPE_SYSV)
#ifndef emacs
#include <sys/elf_mips.h>
#define fatal(a, b, c) fprintf (stderr, a, b, c), exit (1)
#include <sym.h>
#endif /* __sony_news && _SYSTYPE_SYSV */
#if __sgi
#include <syms.h> /* for HDRR declaration */
#endif /* __sgi */
#ifndef MAP_ANON
#ifdef MAP_ANONYMOUS
#define MAP_ANON MAP_ANONYMOUS
#else
#else
#include "config.h"
#define MAP_ANON 0
extern void fatal (char *, ...);
#endif
#endif
#ifndef MAP_FAILED
#define MAP_FAILED ((void *) -1)
#endif
#if defined (__alpha__) && !defined (__NetBSD__) && !defined (__OpenBSD__)
/* Declare COFF debugging symbol table.  This used to be in
   /usr/include/sym.h, but this file is no longer included in Red Hat
   5.0 and presumably in any other glibc 2.x based distribution.  */
typedef struct {
	short magic;
	short vstamp;
	int ilineMax;
	int idnMax;
	int ipdMax;
	int isymMax;
	int ioptMax;
	int iauxMax;
	int issMax;
	int issExtMax;
	int ifdMax;
	int crfd;
	int iextMax;
	long cbLine;
	long cbLineOffset;
	long cbDnOffset;
	long cbPdOffset;
	long cbSymOffset;
	long cbOptOffset;
	long cbAuxOffset;
	long cbSsOffset;
	long cbSsExtOffset;
	long cbFdOffset;
	long cbRfdOffset;
	long cbExtOffset;
} HDRR, *pHDRR; 
#define cbHDRR sizeof(HDRR)
#define hdrNil ((pHDRR)0)
#endif
#ifdef __NetBSD__
/*
 * NetBSD does not have normal-looking user-land ELF support.
 */
# if defined __alpha__ || defined __sparc_v9__
#  define ELFSIZE	64
# else
#  define ELFSIZE	32
# endif
# include <sys/exec_elf.h>
# ifndef PT_LOAD
#  define PT_LOAD	Elf_pt_load
#  if 0						/* was in pkgsrc patches for 20.7 */
#   define SHT_PROGBITS Elf_sht_progbits
#  endif
#  define SHT_SYMTAB	Elf_sht_symtab
#  define SHT_DYNSYM	Elf_sht_dynsym
#  define SHT_NULL	Elf_sht_null
#  define SHT_NOBITS	Elf_sht_nobits
#  define SHT_REL	Elf_sht_rel
#  define SHT_RELA	Elf_sht_rela
#  define SHN_UNDEF	Elf_eshn_undefined
#  define SHN_ABS	Elf_eshn_absolute
#  define SHN_COMMON	Elf_eshn_common
# endif /* !PT_LOAD */
# ifdef __alpha__
#  include <sys/exec_ecoff.h>
#  define HDRR		struct ecoff_symhdr
#  define pHDRR		HDRR *
# endif /* __alpha__ */
#ifdef __mips__			/* was in pkgsrc patches for 20.7 */
# define SHT_MIPS_DEBUG	DT_MIPS_FLAGS
# define HDRR		struct Elf_Shdr
#endif /* __mips__ */
#endif /* __NetBSD__ */
#ifdef __OpenBSD__
# include <sys/exec_elf.h>
#endif
#if __GNU_LIBRARY__ - 0 >= 6
# include <link.h>	/* get ElfW etc */
#endif
#ifndef ElfW
# ifdef __STDC__
#  define ElfBitsW(bits, type) Elf##bits##_##type
# else
#  define ElfBitsW(bits, type) Elf/**/bits/**/_/**/type
# endif
# ifdef _LP64
#  define ELFSIZE 64
# else
#  define ELFSIZE 32
# endif
  /* This macro expands `bits' before invoking ElfBitsW.  */
# define ElfExpandBitsW(bits, type) ElfBitsW (bits, type)
# define ElfW(type) ElfExpandBitsW (ELFSIZE, type)
#endif
#endif
#ifndef ELF_BSS_SECTION_NAME
#ifndef ELF_BSS_SECTION_NAME
 Lines 462-474    Link Here 
   */
   */
#define OLD_SECTION_H(n) \
#define OLD_SECTION_H(n) \
     (*(Elf32_Shdr *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))
     (*(ElfW(Shdr) *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))
#define NEW_SECTION_H(n) \
#define NEW_SECTION_H(n) \
     (*(Elf32_Shdr *) ((byte *) new_section_h + new_file_h->e_shentsize * (n)))
     (*(ElfW(Shdr) *) ((byte *) new_section_h + new_file_h->e_shentsize * (n)))
#define OLD_PROGRAM_H(n) \
#define OLD_PROGRAM_H(n) \
     (*(Elf32_Phdr *) ((byte *) old_program_h + old_file_h->e_phentsize * (n)))
     (*(ElfW(Phdr) *) ((byte *) old_program_h + old_file_h->e_phentsize * (n)))
#define NEW_PROGRAM_H(n) \
#define NEW_PROGRAM_H(n) \
     (*(Elf32_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))
     (*(ElfW(Phdr) *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))
#define PATCH_INDEX(n) \
#define PATCH_INDEX(n) \
  do { \
  do { \
 Lines 478-486    Link Here 
/* Round X up to a multiple of Y.  */
/* Round X up to a multiple of Y.  */
int
static ElfW(Addr)
round_up (x, y)
round_up (x, y)
     int x, y;
     ElfW(Addr) x, y;
{
{
  int rem = x % y;
  int rem = x % y;
  if (rem == 0)
  if (rem == 0)
 Lines 488-493    Link Here 
  return x - rem + y;
  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.
   If we don't find the section NAME, that is a fatal error
   if NOERROR is 0; we return -1 if NOERROR is nonzero.  */
static int
find_section (name, section_names, file_name, old_file_h, old_section_h, noerror)
     char *name;
     char *section_names;
     char *file_name;
     ElfW(Ehdr) *old_file_h;
     ElfW(Shdr) *old_section_h;
     int noerror;
{
  int 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);
#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);
    }
  return idx;
}
/* ****************************************************************
/* ****************************************************************
 * unexec
 * unexec
 *
 *
 Lines 507-531    Link Here 
  /* Pointers to the base of the image of the two files. */
  /* Pointers to the base of the image of the two files. */
  caddr_t old_base, new_base;
  caddr_t old_base, new_base;
#if MAP_ANON == 0
  int mmap_fd;
#else
# define mmap_fd -1
#endif
  /* Pointers to the file, program and section headers for the old and new
  /* Pointers to the file, program and section headers for the old and new
   * files.
   * files.
   */
   */
  Elf32_Ehdr *old_file_h, *new_file_h;
  ElfW(Ehdr) *old_file_h, *new_file_h;
  Elf32_Phdr *old_program_h, *new_program_h;
  ElfW(Phdr) *old_program_h, *new_program_h;
  Elf32_Shdr *old_section_h, *new_section_h;
  ElfW(Shdr) *old_section_h, *new_section_h;
  /* Point to the section name table in the old file */
  /* Point to the section name table in the old file */
  char *old_section_names;
  char *old_section_names;
  Elf32_Addr old_bss_addr, new_bss_addr;
  ElfW(Addr) old_bss_addr, new_bss_addr;
  Elf32_Word old_bss_size, new_data2_size;
  ElfW(Word) old_bss_size, new_data2_size;
  Elf32_Off  new_data2_offset;
  ElfW(Off)  new_data2_offset;
  Elf32_Addr new_data2_addr;
  ElfW(Addr) new_data2_addr;
  int n, nn, old_bss_index, old_data_index, new_data2_index;
  int n, nn;
  int old_bss_index, old_sbss_index;
  int old_data_index, new_data2_index;
  int old_mdebug_index;
  struct stat stat_buf;
  struct stat stat_buf;
  int old_file_size;
  /* Open the old file & map it into the address space. */
  /* 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 = open (old_name, O_RDONLY);
 Lines 535-586    Link Here 
  if (fstat (old_file, &stat_buf) == -1)
  if (fstat (old_file, &stat_buf) == -1)
    fatal ("Can't fstat (%s): errno %d\n", old_name, errno);
    fatal ("Can't fstat (%s): errno %d\n", old_name, errno);
  old_base = mmap (0, stat_buf.st_size, PROT_READ, MAP_SHARED, old_file, 0);
#if MAP_ANON == 0
  mmap_fd = open ("/dev/zero", O_RDONLY);
  if (mmap_fd < 0)
    fatal ("Can't open /dev/zero for reading: errno %d\n", errno);
#endif
  if (old_base == (caddr_t) -1)
  /* We cannot use malloc here because that may use sbrk.  If it does,
    fatal ("Can't mmap (%s): errno %d\n", old_name, errno);
     we'd dump our temporary buffers with Emacs, and we'd have to be
     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;
  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);
#ifdef DEBUG
  if (read (old_file, old_base, stat_buf.st_size) != stat_buf.st_size)
  fprintf (stderr, "mmap (%s, %x) -> %x\n", old_name, stat_buf.st_size,
    fatal ("Didn't read all of %s: errno %d\n", old_name, errno);
	   old_base);
#endif
  /* Get pointers to headers & section names */
  /* Get pointers to headers & section names */
  old_file_h = (Elf32_Ehdr *) old_base;
  old_file_h = (ElfW(Ehdr) *) old_base;
  old_program_h = (Elf32_Phdr *) ((byte *) old_base + old_file_h->e_phoff);
  old_program_h = (ElfW(Phdr) *) ((byte *) old_base + old_file_h->e_phoff);
  old_section_h = (Elf32_Shdr *) ((byte *) old_base + old_file_h->e_shoff);
  old_section_h = (ElfW(Shdr) *) ((byte *) old_base + old_file_h->e_shoff);
  old_section_names = (char *) old_base
  old_section_names = (char *) old_base
    + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
    + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
  /* Find the mdebug section, if any.  */
  old_mdebug_index = find_section (".mdebug", old_section_names,
				   old_name, old_file_h, old_section_h, 1);
  /* Find the old .bss section.  Figure out parameters of the new
  /* Find the old .bss section.  Figure out parameters of the new
   * data2 and bss sections.
   * data2 and bss sections.
   */
   */
  for (old_bss_index = 1; old_bss_index < (int) old_file_h->e_shnum;
  old_bss_index = find_section (".bss", old_section_names,
       old_bss_index++)
				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_PROGBITS)
      old_sbss_index = -1;
  if (old_sbss_index == -1)
    {
    {
#ifdef DEBUG
      old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
      fprintf (stderr, "Looking for .bss - found %s\n",
      old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
	       old_section_names + OLD_SECTION_H (old_bss_index).sh_name);
      new_data2_index = old_bss_index;
#endif
    }
      if (!strcmp (old_section_names + OLD_SECTION_H (old_bss_index).sh_name,
  else
		   ELF_BSS_SECTION_NAME))
    {
	break;
      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;
      new_data2_index = old_sbss_index;
    }
    }
  if (old_bss_index == old_file_h->e_shnum)
    fatal ("Can't find .bss in %s.\n", old_name, 0);
  old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
  /* Find the old .data section.  Figure out parameters of
  old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
     the new data2 and bss sections.  */
#if defined(emacs) || !defined(DEBUG)
  new_bss_addr = (Elf32_Addr) sbrk (0);
  old_data_index = find_section (".data", old_section_names,
				 old_name, old_file_h, old_section_h, 0);
#if defined (emacs) || !defined (DEBUG)
  new_bss_addr = (ElfW(Addr)) sbrk (0);
#else
#else
  new_bss_addr = old_bss_addr + old_bss_size + 0x1234;
  new_bss_addr = old_bss_addr + old_bss_size + 0x1234;
#endif
#endif
  new_data2_addr = old_bss_addr;
  new_data2_addr = old_bss_addr;
  new_data2_size = new_bss_addr - old_bss_addr;
  new_data2_size = new_bss_addr - old_bss_addr;
  new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset;
  new_data2_offset  = OLD_SECTION_H (old_data_index).sh_offset +
    (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "old_bss_index %d\n", old_bss_index);
  fprintf (stderr, "old_bss_index %d\n", old_bss_index);
 Lines 595-603    Link Here 
  if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
  if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
    fatal (".bss shrank when undumping???\n", 0, 0);
    fatal (".bss shrank when undumping???\n", 0, 0);
  /* Set the output file to the right size and mmap it.  Set
  /* Set the output file to the right size.  Allocate a buffer to hold
   * pointers to various interesting objects.  stat_buf still has
   * the image of the new file.  Set pointers to various interesting
   * old_file data.
   * objects.  stat_buf still has old_file data.
   */
   */
  new_file = open (new_name, O_RDWR | O_CREAT, 0666);
  new_file = open (new_name, O_RDWR | O_CREAT, 0666);
 Lines 609-628    Link Here 
  if (ftruncate (new_file, new_file_size))
  if (ftruncate (new_file, new_file_size))
    fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno);
    fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno);
#ifdef UNEXEC_USE_MAP_PRIVATE
  new_base = mmap (NULL, new_file_size, PROT_READ | PROT_WRITE,
  new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
		   MAP_ANON | MAP_PRIVATE, mmap_fd, 0);
		   new_file, 0);
  if (new_base == MAP_FAILED)
#else
    fatal ("Can't allocate buffer for %s\n", old_name);
  new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED,
		   new_file, 0);
  new_file_h = (ElfW(Ehdr) *) new_base;
#endif
  new_program_h = (ElfW(Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
  new_section_h = (ElfW(Shdr) *)
  if (new_base == (caddr_t) -1)
    fatal ("Can't mmap (%s): errno %d\n", new_name, errno);
  new_file_h = (Elf32_Ehdr *) new_base;
  new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff);
  new_section_h = (Elf32_Shdr *)
    ((byte *) new_base + old_file_h->e_shoff + new_data2_size);
    ((byte *) new_base + old_file_h->e_shoff + new_data2_size);
  /* Make our new file, program and section headers as copies of the
  /* Make our new file, program and section headers as copies of the
 Lines 661-672    Link Here 
  for (n = new_file_h->e_phnum - 1; n >= 0; n--)
  for (n = new_file_h->e_phnum - 1; n >= 0; n--)
    {
    {
      /* Compute maximum of all requirements for alignment of section.  */
      /* Compute maximum of all requirements for alignment of section.  */
      int alignment = (NEW_PROGRAM_H (n)).p_align;
      ElfW(Word) alignment = (NEW_PROGRAM_H (n)).p_align;
      if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
      if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
	alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
	alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
      if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_bss_addr)
#ifdef __sgi
	fatal ("Program segment above .bss in %s\n", old_name, 0);
	  /* 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\n", old_name, 0);
      if (NEW_PROGRAM_H (n).p_type == PT_LOAD
      if (NEW_PROGRAM_H (n).p_type == PT_LOAD
	  && (round_up ((NEW_PROGRAM_H (n)).p_vaddr
	  && (round_up ((NEW_PROGRAM_H (n)).p_vaddr
 Lines 678-684    Link Here 
  if (n < 0)
  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\n", old_name, 0);
  NEW_PROGRAM_H (n).p_filesz += new_data2_size;
  /* 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;
  NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz;
#if 0 /* Maybe allow section after data2 - does this ever happen? */
#if 0 /* Maybe allow section after data2 - does this ever happen? */
 Lines 712-723    Link Here 
  for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++)
  for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++)
    {
    {
      caddr_t src;
      caddr_t src;
      /* If it is bss section, insert the new data2 section before it. */
      /* If it is (s)bss section, insert the new data2 section before it.  */
      if (n == old_bss_index)
      /* 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. */
	  /* Steal the data section header for this data2 section. */
	  memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index),
	  memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index),
	  new_file_h->e_shentsize);
		  new_file_h->e_shentsize);
	  NEW_SECTION_H (nn).sh_addr = new_data2_addr;
	  NEW_SECTION_H (nn).sh_addr = new_data2_addr;
	  NEW_SECTION_H (nn).sh_offset = new_data2_offset;
	  NEW_SECTION_H (nn).sh_offset = new_data2_offset;
 Lines 737-749    Link Here 
      memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
      memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
	      old_file_h->e_shentsize);
	      old_file_h->e_shentsize);
      /* The new bss section's size is zero, and its file offset and virtual
      if (n == old_bss_index
	 address should be off by NEW_DATA2_SIZE. */
	  /* The new bss and sbss section's size is zero, and its file offset
      if (n == old_bss_index)
	     and virtual address should be off by NEW_DATA2_SIZE.  */
	  || n == old_sbss_index
	  )
	{
	{
	  /* NN should be `old_bss_index + 1' at this point. */
	  /* NN should be `old_s?bss_index + 1' at this point. */
	  NEW_SECTION_H (nn).sh_offset += new_data2_size;
	  NEW_SECTION_H (nn).sh_offset =
	  NEW_SECTION_H (nn).sh_addr += new_data2_size;
	    NEW_SECTION_H (new_data2_index).sh_offset + new_data2_size;
	  NEW_SECTION_H (nn).sh_addr =
	    NEW_SECTION_H (new_data2_index).sh_addr + new_data2_size;
	  /* Let the new bss section address alignment be the same as the
	  /* Let the new bss section address alignment be the same as the
	     section address alignment followed the old bss section, so
	     section address alignment followed the old bss section, so
	     this section will be placed in exactly the same place. */
	     this section will be placed in exactly the same place. */
 Lines 767-773    Link Here 
	      >= OLD_SECTION_H (old_bss_index-1).sh_offset)
	      >= OLD_SECTION_H (old_bss_index-1).sh_offset)
	    NEW_SECTION_H (nn).sh_offset += new_data2_size;
	    NEW_SECTION_H (nn).sh_offset += new_data2_size;
#else
#else
	  if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
	  if (round_up (NEW_SECTION_H (nn).sh_offset,
			OLD_SECTION_H (old_bss_index).sh_addralign)
	      >= new_data2_offset)
	    NEW_SECTION_H (nn).sh_offset += new_data2_size;
	    NEW_SECTION_H (nn).sh_offset += new_data2_size;
#endif
#endif
	  /* Any section that was originally placed after the section
	  /* Any section that was originally placed after the section
 Lines 787-804    Link Here 
      if (NEW_SECTION_H (nn).sh_type != SHT_SYMTAB
      if (NEW_SECTION_H (nn).sh_type != SHT_SYMTAB
	  && NEW_SECTION_H (nn).sh_type != SHT_DYNSYM)
	  && NEW_SECTION_H (nn).sh_type != SHT_DYNSYM)
	PATCH_INDEX (NEW_SECTION_H (nn).sh_info);
	PATCH_INDEX (NEW_SECTION_H (nn).sh_info);
      
      if (old_sbss_index != -1)
	if (!strcmp (old_section_names + NEW_SECTION_H (nn).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;
	  }
      /* Now, start to copy the content of sections.  */
      /* Now, start to copy the content of sections.  */
      if (NEW_SECTION_H (nn).sh_type == SHT_NULL
      if (NEW_SECTION_H (nn).sh_type == SHT_NULL
	  || NEW_SECTION_H (nn).sh_type == SHT_NOBITS)
	  || NEW_SECTION_H (nn).sh_type == SHT_NOBITS)
	continue;
	continue;
  /* Write out the sections. .data and .data1 (and data2, called
      /* Write out the sections. .data and .data1 (and data2, called
	 ".data" in the strings table) get copied from the current process
	 ".data" in the strings table) get copied from the current process
	 instead of the old file.  */
	 instead of the old file.  */
      if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data")
      if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data")
	  || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
	  || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
		      ".data1"))
		      ".sdata")
	  || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
		      ".lit4")
	  || !strcmp ((old_section_names + NEW_SECTION_H (n).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
	     `IRIX64 6.5 6.5.17m' with c_dev 7.3.1.3m.  It causes no
	     trouble on the other ELF platforms I could test (Irix
	     6.5.15m, Solaris 8, Debian Potato x86, Debian Woody
	     SPARC); however, it's reported to cause crashes under
	     some version of GNU/Linux.  It's not yet clear what's
	     changed in that Irix version to cause the problem, or why
	     the fix sometimes fails under GNU/Linux.  There's
	     probably no good reason to have something Irix-specific
	     here, but this will have to do for now.  IRIX6_5 is the
	     most specific macro we have to test.  -- fx 2002-10-01  */
#ifdef IRIX6_5
	  || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
		      ".got")
#endif
	  || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
		      ".sdata1")
	  || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
		      ".data1")
	  || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
		      ".sbss"))
	src = (caddr_t) OLD_SECTION_H (n).sh_addr;
	src = (caddr_t) OLD_SECTION_H (n).sh_addr;
      else
      else
	src = old_base + OLD_SECTION_H (n).sh_offset;
	src = old_base + OLD_SECTION_H (n).sh_offset;
 Lines 806-818    Link Here 
      memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src,
      memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src,
	      NEW_SECTION_H (nn).sh_size);
	      NEW_SECTION_H (nn).sh_size);
#ifdef __alpha__
      /* Update Alpha COFF symbol table: */
      if (strcmp (old_section_names + OLD_SECTION_H (n).sh_name, ".mdebug")
	  == 0)
	{
	  pHDRR symhdr = (pHDRR) (NEW_SECTION_H (nn).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__ */
#if defined (__sony_news) && defined (_SYSTYPE_SYSV)
      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;
	  HDRR *phdr = (HDRR *)(NEW_SECTION_H (nn).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;
	    }
	}
#endif /* __sony_news && _SYSTYPE_SYSV */
#if __sgi
      /* Adjust  the HDRR offsets in .mdebug and copy the 
	 line data if it's in its usual 'hole' in the object.
	 Makes the new file debuggable with dbx.
	 patches up two problems: the absolute file offsets
	 in the HDRR record of .mdebug (see /usr/include/syms.h), and
	 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)
	{
#define MDEBUGADJUST(__ct,__fileaddr)		\
  if (n_phdrr->__ct > 0)			\
    {						\
      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);
	  unsigned movement = new_data2_size;
	  MDEBUGADJUST (idnMax, cbDnOffset);
	  MDEBUGADJUST (ipdMax, cbPdOffset);
	  MDEBUGADJUST (isymMax, cbSymOffset);
	  MDEBUGADJUST (ioptMax, cbOptOffset);
	  MDEBUGADJUST (iauxMax, cbAuxOffset);
	  MDEBUGADJUST (issMax, cbSsOffset);
	  MDEBUGADJUST (issExtMax, cbSsExtOffset);
	  MDEBUGADJUST (ifdMax, cbFdOffset);
	  MDEBUGADJUST (crfd, cbRfdOffset);
	  MDEBUGADJUST (iextMax, cbExtOffset);
	  /* The Line Section, being possible off in a hole of the object,
	     requires special handling.  */
	  if (n_phdrr->cbLine > 0)
	    {
	      if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset
					   + OLD_SECTION_H (n).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);
		}
	    }
	}
#endif /* __sgi */
      /* If it is the symbol table, its st_shndx field needs to be patched.  */
      /* If it is the symbol table, its st_shndx field needs to be patched.  */
      if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB
      if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB
	  || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)
	  || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)
	{
	{
	  Elf32_Shdr *spt = &NEW_SECTION_H (nn);
	  ElfW(Shdr) *spt = &NEW_SECTION_H (nn);
	  unsigned int num = spt->sh_size / spt->sh_entsize;
	  unsigned int num = spt->sh_size / spt->sh_entsize;
	  Elf32_Sym * sym = (Elf32_Sym *) (NEW_SECTION_H (nn).sh_offset +
	  ElfW(Sym) * sym = (ElfW(Sym) *) (NEW_SECTION_H (nn).sh_offset +
					   new_base);
					   new_base);
	  for (; num--; sym++)
	  for (; num--; sym++)
	    {
	    {
 Lines 830-836    Link Here 
  for (n = new_file_h->e_shnum - 1; n; n--)
  for (n = new_file_h->e_shnum - 1; n; n--)
    {
    {
      byte *symnames;
      byte *symnames;
      Elf32_Sym *symp, *symendp;
      ElfW(Sym) *symp, *symendp;
      if (NEW_SECTION_H (n).sh_type != SHT_DYNSYM
      if (NEW_SECTION_H (n).sh_type != SHT_DYNSYM
	  && NEW_SECTION_H (n).sh_type != SHT_SYMTAB)
	  && NEW_SECTION_H (n).sh_type != SHT_SYMTAB)
 Lines 838-849    Link Here 
      symnames = ((byte *) new_base
      symnames = ((byte *) new_base
		  + NEW_SECTION_H (NEW_SECTION_H (n).sh_link).sh_offset);
		  + NEW_SECTION_H (NEW_SECTION_H (n).sh_link).sh_offset);
      symp = (Elf32_Sym *) (NEW_SECTION_H (n).sh_offset + new_base);
      symp = (ElfW(Sym) *) (NEW_SECTION_H (n).sh_offset + new_base);
      symendp = (Elf32_Sym *) ((byte *)symp + NEW_SECTION_H (n).sh_size);
      symendp = (ElfW(Sym) *) ((byte *)symp + NEW_SECTION_H (n).sh_size);
      for (; symp < symendp; symp ++)
      for (; symp < symendp; symp ++)
	if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0
	if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0
	    || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0)
	    || strcmp ((char *) (symnames + symp->st_name), "end") == 0
	    || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0
	    || strcmp ((char *) (symnames + symp->st_name), "edata") == 0)
	  memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr));
	  memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr));
    }
    }
 Lines 851-857    Link Here 
     that it can undo relocations performed by the runtime linker.  */
     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 - 1; n; n--)
    {
    {
      Elf32_Shdr section = NEW_SECTION_H (n);
      ElfW(Shdr) section = NEW_SECTION_H (n);
      switch (section.sh_type) {
      switch (section.sh_type) {
      default:
      default:
	break;
	break;
 Lines 863-899    Link Here 
	nn = section.sh_info;
	nn = section.sh_info;
	if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data")
	if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data")
	    || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
	    || !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")
#ifdef IRIX6_5			/* see above */
	    || !strcmp ((old_section_names + NEW_SECTION_H (nn).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"))
			".data1"))
	  {
	  {
	    Elf32_Addr offset = NEW_SECTION_H (nn).sh_addr -
	    ElfW(Addr) offset = NEW_SECTION_H (nn).sh_addr -
	      NEW_SECTION_H (nn).sh_offset;
	      NEW_SECTION_H (nn).sh_offset;
	    caddr_t reloc = old_base + section.sh_offset, end;
	    caddr_t reloc = old_base + section.sh_offset, end;
	    for (end = reloc + section.sh_size; reloc < end;
	    for (end = reloc + section.sh_size; reloc < end;
		 reloc += section.sh_entsize)
		 reloc += section.sh_entsize)
	      {
	      {
		Elf32_Addr addr = ((Elf32_Rel *) reloc)->r_offset - offset;
		ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset;
		memcpy (new_base + addr, old_base + addr, 4);
#ifdef __alpha__
    }
		/* The Alpha ELF binutils currently have a bug that
		   sometimes results in relocs that contain all
		   zeroes.  Work around this for now...  */
		if (((ElfW(Rel) *) reloc)->r_offset == 0)
		    continue;
#endif
		memcpy (new_base + addr, old_base + addr, sizeof(ElfW(Addr)));
	      }
	  }
	  }
	break;
	break;
      }
      }
    }
    }
#ifdef UNEXEC_USE_MAP_PRIVATE
  /* Write out new_file, close it, and free the buffer containing its
  if (lseek (new_file, 0, SEEK_SET) == -1)
   * contents */
    fatal ("Can't rewind (%s): errno %d\n", new_name, errno);
  if (write (new_file, new_base, new_file_size) != new_file_size)
  if (write (new_file, new_base, new_file_size) != new_file_size)
    fatal ("Can't write (%s): errno %d\n", new_name, errno);
    fatal ("Didn't write %d bytes to %s: errno %d\n", 
#endif
	   new_file_size, new_base, errno);
  if (close (new_file))
    fatal ("Can't close (%s): errno %d\n", new_name, errno);
  munmap (new_base, new_file_size);
  /* Close the files and make the new file executable.  */
  /* Close old_file, and free the corresponding buffer */
#if MAP_ANON == 0
  close (mmap_fd);
#endif
  if (close (old_file))
  if (close (old_file))
    fatal ("Can't close (%s): errno %d\n", old_name, errno);
    fatal ("Can't close (%s): errno %d\n", old_name, errno);
  if (close (new_file))
  munmap (old_base, old_file_size);
    fatal ("Can't close (%s): errno %d\n", new_name, errno);
  /* Make the new file executable */
  if (stat (new_name, &stat_buf) == -1)
  if (stat (new_name, &stat_buf) == -1)
    fatal ("Can't stat (%s): errno %d\n", new_name, errno);
    fatal ("Can't stat (%s): errno %d\n", new_name, errno);