summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKarl Heuer <kwzh@gnu.org>1996-01-08 22:29:48 +0000
committerKarl Heuer <kwzh@gnu.org>1996-01-08 22:29:48 +0000
commit33b298028e43520078ed699d42b8d7327eba3867 (patch)
treee5c6440ca9f70574d75e259abfdd523e4280c273 /src
parentf546397ee2dc53911b6879f8fe9334ba091e4125 (diff)
downloademacs-33b298028e43520078ed699d42b8d7327eba3867.tar.gz
(unexec) [SOLARIS2]: Undo relocations performed by the
runtime linker.
Diffstat (limited to 'src')
-rw-r--r--src/unexelf.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/src/unexelf.c b/src/unexelf.c
index c61f4c368f1..c86663f7ace 100644
--- a/src/unexelf.c
+++ b/src/unexelf.c
@@ -807,6 +807,40 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr));
}
+#ifdef SOLARIS2
+ /* 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--)
+ {
+ Elf32_Shdr section = NEW_SECTION_H (n);
+ 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. */
+ 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),
+ ".data1"))
+ {
+ Elf32_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)
+ {
+ Elf32_Addr addr = ((Elf32_Rel *) reloc)->r_offset - offset;
+ memcpy (new_base + addr, old_base + addr, 4);
+ }
+ }
+ break;
+ }
+ }
+#endif
+
#ifdef UNEXEC_USE_MAP_PRIVATE
if (lseek (new_file, 0, SEEK_SET) == -1)
fatal ("Can't rewind (%s): errno %d\n", new_name, errno);