-/* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992, 1993, 1999, 2000
+/* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992, 1993
Free Software Foundation, Inc.
This file is part of XEmacs.
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Synched up with: FSF 20.6.90. */
+/* Synched up with: FSF 20.4. */
/*
* unexec.c - Convert a running program into an a.out file.
* The value you specify may be rounded down to a suitable boundary
* 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
* 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
*
* 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.
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
-#if !defined (__NetBSD__) && !defined (__OpenBSD__)
+#ifdef HAVE_ELF_H
#include <elf.h>
#endif
#include <sys/mman.h>
#include <sym.h>
#endif /* __sony_news && _SYSTYPE_SYSV */
#ifdef __sgi
-#include <syms.h> /* for HDRR declaration */
+#include <sym.h> /* for HDRR declaration */
#endif /* __sgi */
#if defined (__alpha__) && !defined (__NetBSD__) && !defined (__OpenBSD__)
#define hdrNil ((pHDRR)0)
#endif
-#ifdef __NetBSD__
-/*
- * NetBSD does not have normal-looking user-land ELF support.
- */
-# ifdef __alpha__
-# define ELFSIZE 64
-# else
-# define ELFSIZE 32
-# endif
-# include <sys/exec_elf.h>
-
-# ifndef PT_LOAD
-# define PT_LOAD Elf_pt_load
-# 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
-
-# ifdef __alpha__
-# include <sys/exec_ecoff.h>
-# define HDRR struct ecoff_symhdr
-# define pHDRR HDRR *
-# endif
-#endif /* __NetBSD__ */
-
#ifdef __OpenBSD__
# include <sys/exec_elf.h>
#endif
#ifndef ElfW
# ifdef __STDC__
-# define ElfBitsW(bits, type) Elf##bits##_##type
+# define ElfW(type) Elf32_##type
# else
-# define ElfBitsW(bits, type) Elf/**/bits/**/_/**/type
+# define ElfW(type) Elf32_/**/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
#ifndef ELF_BSS_SECTION_NAME
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, 0);
- }
-
- return idx;
-}
-
/* ****************************************************************
* unexec
*
ElfW(Off) new_data2_offset;
ElfW(Addr) new_data2_addr;
- int n, nn;
- int old_bss_index, old_sbss_index;
- int old_data_index, new_data2_index;
- int old_mdebug_index;
+ int n, nn, old_bss_index, old_data_index, new_data2_index;
+ int old_sbss_index, old_mdebug_index;
struct stat stat_buf;
/* Open the old file & map it into the address space. */
old_section_names = (char *) old_base
+ 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
* 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_PROGBITS)
- old_sbss_index = -1;
+ for (old_bss_index = 1; old_bss_index < (int) old_file_h->e_shnum;
+ old_bss_index++)
+ {
+#ifdef DEBUG
+ fprintf (stderr, "Looking for .bss - found %s\n",
+ old_section_names + OLD_SECTION_H (old_bss_index).sh_name);
+#endif
+ if (!strcmp (old_section_names + OLD_SECTION_H (old_bss_index).sh_name,
+ ELF_BSS_SECTION_NAME))
+ break;
+ }
+ if (old_bss_index == old_file_h->e_shnum)
+ fatal ("Can't find .bss in %s.\n", old_name, 0);
- if (old_sbss_index == -1)
+ for (old_sbss_index = 1; old_sbss_index < (int) old_file_h->e_shnum;
+ old_sbss_index++)
+ {
+#ifdef DEBUG
+ fprintf (stderr, "Looking for .sbss - found %s\n",
+ old_section_names + OLD_SECTION_H (old_sbss_index).sh_name);
+#endif
+ if (!strcmp (old_section_names + OLD_SECTION_H (old_sbss_index).sh_name,
+ ".sbss"))
+ break;
+ }
+ if (old_sbss_index == old_file_h->e_shnum)
{
- old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
- old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
+ old_sbss_index = -1;
+ old_bss_addr = OLD_SECTION_H(old_bss_index).sh_addr;
+ old_bss_size = OLD_SECTION_H(old_bss_index).sh_size;
new_data2_index = old_bss_index;
}
else
{
- 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_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;
}
- /* Find the old .data section. Figure out parameters of
- the new data2 and bss sections. */
+ for (old_mdebug_index = 1; old_mdebug_index < (int) old_file_h->e_shnum;
+ old_mdebug_index++)
+ {
+#ifdef DEBUG
+ fprintf (stderr, "Looking for .mdebug - found %s\n",
+ old_section_names + OLD_SECTION_H (old_mdebug_index).sh_name);
+#endif
+ if (!strcmp (old_section_names + OLD_SECTION_H (old_mdebug_index).sh_name,
+ ".mdebug"))
+ break;
+ }
+ if (old_mdebug_index == old_file_h->e_shnum)
+ old_mdebug_index = 0;
- old_data_index = find_section (".data", old_section_names,
- old_name, old_file_h, old_section_h, 0);
+ for (old_data_index = 1; old_data_index < (int) old_file_h->e_shnum;
+ old_data_index++)
+ {
+#ifdef DEBUG
+ fprintf (stderr, "Looking for .data - found %s\n",
+ old_section_names + OLD_SECTION_H (old_data_index).sh_name);
+#endif
+ if (!strcmp (old_section_names + OLD_SECTION_H (old_data_index).sh_name,
+ ".data"))
+ break;
+ }
+ if (old_data_index == old_file_h->e_shnum)
+ old_data_index = 0;
#if defined (emacs) || !defined (DEBUG)
new_bss_addr = (ElfW(Addr)) sbrk (0);
if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
-#ifdef __sgi
+#ifdef __mips
/* 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 */
+#endif /* __mips */
if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz
> (old_sbss_index == -1
? old_bss_addr
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 (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. */
if (NEW_SECTION_H (nn).sh_type == SHT_NULL
/* Taking these sections from the current process, breaks
Linux in a subtle way. Binaries only run on the
architecture (e.g. i586 vs i686) of the dumping machine */
+#ifdef __sgi
|| !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
".lit4")
|| !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
".lit8")
|| !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 (nn).sh_name,
- ".sbss"))
+ ".data1"))
src = (caddr_t) OLD_SECTION_H (n).sh_addr;
else
src = old_base + OLD_SECTION_H (n).sh_offset;
#endif /* __alpha__ */
#if defined (__sony_news) && defined (_SYSTYPE_SYSV)
- if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG
- && old_mdebug_index != -1)
+ if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG && old_mdebug_index)
{
int diff = NEW_SECTION_H(nn).sh_offset
- OLD_SECTION_H(old_mdebug_index).sh_offset;
if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data")
|| !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
".sdata")
+#ifdef __sgi
|| !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
".lit4")
|| !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
".lit8")
|| !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),