aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/sh
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/sh')
-rw-r--r--sysdeps/sh/bits/link.h5
-rw-r--r--sysdeps/sh/dl-machine.h17
2 files changed, 21 insertions, 1 deletions
diff --git a/sysdeps/sh/bits/link.h b/sysdeps/sh/bits/link.h
new file mode 100644
index 0000000000..bb2fbb5f16
--- /dev/null
+++ b/sysdeps/sh/bits/link.h
@@ -0,0 +1,5 @@
+struct link_map_machine
+ {
+ Elf32_Addr plt; /* Address of .plt + 36 */
+ Elf32_Addr gotplt; /* Address of .got + 0x0c */
+ };
diff --git a/sysdeps/sh/dl-machine.h b/sysdeps/sh/dl-machine.h
index dc53c652d0..b303756e44 100644
--- a/sysdeps/sh/dl-machine.h
+++ b/sysdeps/sh/dl-machine.h
@@ -85,6 +85,14 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
offset into the .rela.plt section and _GLOBAL_OFFSET_TABLE_[1],
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
+ /* If a library is prelinked but we have to relocate anyway,
+ we have to be able to undo the prelinking of .got.plt.
+ The prelinker saved us here address of .plt + 36. */
+ if (got[1])
+ {
+ l->l_mach.plt = got[1] + l->l_addr;
+ l->l_mach.gotplt = (Elf32_Addr) &got[3];
+ }
got[1] = (Elf32_Addr) l; /* Identify this shared object. */
/* The got[2] entry contains the address of a function which gets
@@ -582,7 +590,14 @@ elf_machine_lazy_rel (struct link_map *map,
Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
/* Check for unexpected PLT reloc type. */
if (ELF32_R_TYPE (reloc->r_info) == R_SH_JMP_SLOT)
- *reloc_addr += l_addr;
+ {
+ if (__builtin_expect (map->l_mach.plt, 0) == 0)
+ *reloc_addr += l_addr;
+ else
+ *reloc_addr =
+ map->l_mach.plt
+ + (((Elf32_Addr) reloc_addr) - map->l_mach.gotplt) * 7;
+ }
else
_dl_reloc_bad_type (map, ELF32_R_TYPE (reloc->r_info), 1);
}