From: Eli Zaretskii Date: Sat, 18 Mar 2006 14:51:54 +0000 (+0000) Subject: [BROKEN_NOCOMBRELOC]: Include assert.h. X-Git-Tag: emacs-pretest-22.0.90~3531 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=8daaf78be89633514b94e661945f0814ea3e1f90;p=emacs.git [BROKEN_NOCOMBRELOC]: Include assert.h. (unexec) [BROKEN_NOCOMBRELOC]: Handle platforms whose nocombreloc option is broken (e.g., MIPS/NetBSD). --- diff --git a/src/unexelf.c b/src/unexelf.c index 30a35372544..a236b98eab1 100644 --- a/src/unexelf.c +++ b/src/unexelf.c @@ -433,6 +433,9 @@ extern void fatal (const char *msgid, ...); #if __sgi #include /* for HDRR declaration */ #endif /* __sgi */ +#ifdef BROKEN_NOCOMBRELOC +#include +#endif #ifndef MAP_ANON #ifdef MAP_ANONYMOUS @@ -687,6 +690,9 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) int old_mdebug_index; struct stat stat_buf; int old_file_size; +#ifdef BROKEN_NOCOMBRELOC + int unreloc_sections[10], n_unreloc_sections; +#endif /* Open the old file, allocate a buffer of the right size, and read in the file contents. */ @@ -1218,6 +1224,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) /* This loop seeks out relocation sections for the data section, so that it can undo relocations performed by the runtime linker. */ +#ifndef BROKEN_NOCOMBRELOC for (n = new_file_h->e_shnum - 1; n; n--) { ElfW(Shdr) section = NEW_SECTION_H (n); @@ -1272,6 +1279,81 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) break; } } +#else /* BROKEN_NOCOMBRELOC */ + for (n = 1, n_unreloc_sections = 0; n < new_file_h->e_shnum; n++) + if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") + || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sdata") + || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".lit4") + || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".lit8") +#ifdef IRIX6_5 /* see above */ + || !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")) + { + assert (n_unreloc_sections + < (sizeof (unreloc_sections) / sizeof (unreloc_sections[0]))); + unreloc_sections[n_unreloc_sections++] = n; +#ifdef DEBUG + fprintf (stderr, "section %d: %s\n", n, + old_section_names + NEW_SECTION_H (n).sh_name); +#endif + } + + for (n = new_file_h->e_shnum - 1; n; n--) + { + ElfW(Shdr) section = NEW_SECTION_H (n); + caddr_t reloc, end; + ElfW(Addr) addr, offset; + int target; + + switch (section.sh_type) + { + default: + break; + case SHT_REL: + case SHT_RELA: + /* This code handles two different size structs, but there should + be no harm in that provided that r_offset is always the first + member. */ + for (reloc = old_base + section.sh_offset, + end = reloc + section.sh_size; + reloc < end; + reloc += section.sh_entsize) + { + addr = ((ElfW(Rel) *) reloc)->r_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... */ + if (addr == 0) + continue; +#endif + for (nn = 0; nn < n_unreloc_sections; nn++) + { + target = unreloc_sections[nn]; + if (NEW_SECTION_H (target).sh_addr <= addr + && addr < (NEW_SECTION_H (target).sh_addr + + NEW_SECTION_H (target).sh_size)) + { + offset = (NEW_SECTION_H (target).sh_addr - + NEW_SECTION_H (target).sh_offset); + memcpy (new_base + addr - offset, + old_base + addr - offset, + sizeof (ElfW(Addr))); +#ifdef DEBUG + fprintf (stderr, "unrelocate: [%08lx] <= %08lx\n", + (long) addr, + (long) *((long *) (new_base + addr - offset))); +#endif + break; + } + } + } + break; + } + } +#endif /* BROKEN_NOCOMBRELOC */ /* Write out new_file, and free the buffers. */