# HG changeset patch # User Eli Zaretskii # Date 1142693514 0 # Node ID dab2f548eda2c05ba93d79717e005455b926c2b0 # Parent 130314bad206e2919730a7db7f21626a488a6780 [BROKEN_NOCOMBRELOC]: Include assert.h. (unexec) [BROKEN_NOCOMBRELOC]: Handle platforms whose nocombreloc option is broken (e.g., MIPS/NetBSD). diff -r 130314bad206 -r dab2f548eda2 src/unexelf.c --- a/src/unexelf.c Sat Mar 18 14:47:20 2006 +0000 +++ b/src/unexelf.c Sat Mar 18 14:51:54 2006 +0000 @@ -433,6 +433,9 @@ #if __sgi #include /* for HDRR declaration */ #endif /* __sgi */ +#ifdef BROKEN_NOCOMBRELOC +#include +#endif #ifndef MAP_ANON #ifdef MAP_ANONYMOUS @@ -687,6 +690,9 @@ 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 @@ /* 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 @@ 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. */