diff options
Diffstat (limited to 'sysdeps/s390/s390-64')
-rw-r--r-- | sysdeps/s390/s390-64/bits/link.h | 5 | ||||
-rw-r--r-- | sysdeps/s390/s390-64/dl-machine.h | 17 |
2 files changed, 21 insertions, 1 deletions
diff --git a/sysdeps/s390/s390-64/bits/link.h b/sysdeps/s390/s390-64/bits/link.h new file mode 100644 index 0000000000..34add4ffaa --- /dev/null +++ b/sysdeps/s390/s390-64/bits/link.h @@ -0,0 +1,5 @@ +struct link_map_machine + { + Elf64_Addr plt; /* Address of .plt + 0x2e */ + Elf64_Addr gotplt; /* Address of .got + 0x18 */ + }; diff --git a/sysdeps/s390/s390-64/dl-machine.h b/sysdeps/s390/s390-64/dl-machine.h index e77017ab1a..4d4c344ea0 100644 --- a/sysdeps/s390/s390-64/dl-machine.h +++ b/sysdeps/s390/s390-64/dl-machine.h @@ -85,6 +85,14 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) and then jump to _GLOBAL_OFFSET_TABLE[2]. */ Elf64_Addr *got; got = (Elf64_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 + 0x2e. */ + if (got[1]) + { + l->l_mach.plt = got[1] + l->l_addr; + l->l_mach.gotplt = (Elf64_Addr) &got[3]; + } got[1] = (Elf64_Addr) l; /* Identify this shared object. */ /* The got[2] entry contains the address of a function which gets @@ -434,7 +442,14 @@ elf_machine_lazy_rel (struct link_map *map, const unsigned int r_type = ELF32_R_TYPE (reloc->r_info); /* Check for unexpected PLT reloc type. */ if (__builtin_expect (r_type == R_390_JMP_SLOT, 1)) - *reloc_addr += l_addr; + { + if (__builtin_expect (map->l_mach.plt, 0) == 0) + *reloc_addr += l_addr; + else + *reloc_addr = + map->l_mach.plt + + (((Elf64_Addr) reloc_addr) - map->l_mach.gotplt) * 4; + } else _dl_reloc_bad_type (map, r_type, 1); } |