From 1e52d4ce3aa2093d12901d32fe07aae70211fe2a Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Fri, 15 Feb 2019 14:39:57 +0100 Subject: [PATCH] s390: elflint should check if _GLOBAL_OFFSET_TABLE_ points to .got. The _GLOBAL_OFFSET_TABLE_ symbol might point to the DT_PLTGOT, which is in the .got section, even if the symbol itself is associated with the .got.plt section. See https://sourceware.org/ml/binutils/2018-07/msg00200.html Signed-off-by: Mark Wielaard --- backends/ChangeLog | 5 +++++ backends/s390_init.c | 1 + backends/s390_symbol.c | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/backends/ChangeLog b/backends/ChangeLog index 58a1b77..0c61a0b 100644 --- a/backends/ChangeLog +++ b/backends/ChangeLog @@ -1,3 +1,8 @@ +2019-02-15 Mark Wielaard + + * s390_init.c (s390_init): Hook check_special_symbol. + * s390_symbol.c (s390_check_sepcial_symbol): New function. + 2018-12-27 Jim Wilson * Makefile.am (riscv_SRCS): Add riscv64_corenote.c. diff --git a/backends/s390_init.c b/backends/s390_init.c index ba8df45..0004aee 100644 --- a/backends/s390_init.c +++ b/backends/s390_init.c @@ -54,6 +54,7 @@ s390_init (Elf *elf __attribute__ ((unused)), eh->name = "IBM S/390"; s390_init_reloc (eh); HOOK (eh, reloc_simple_type); + HOOK (eh, check_special_symbol); HOOK (eh, register_info); HOOK (eh, return_value_location); if (eh->class == ELFCLASS64) diff --git a/backends/s390_symbol.c b/backends/s390_symbol.c index f91e137..9e80eca 100644 --- a/backends/s390_symbol.c +++ b/backends/s390_symbol.c @@ -32,6 +32,7 @@ #include #include +#include #define BACKEND s390_ #include "libebl_CPU.h" @@ -55,3 +56,40 @@ s390_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type, return ELF_T_NUM; } } + +/* The _GLOBAL_OFFSET_TABLE_ symbol might point to the DT_PLTGOT, + which is in the .got section, even if the symbol itself is + associated with the is a .got.plt section. + https://sourceware.org/ml/binutils/2018-07/msg00200.html */ +bool +s390_check_special_symbol (Elf *elf, const GElf_Sym *sym, + const char *name, const GElf_Shdr *destshdr) +{ + if (name != NULL + && strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0) + { + size_t shstrndx; + if (elf_getshdrstrndx (elf, &shstrndx) != 0) + return false; + const char *sname = elf_strptr (elf, shstrndx, destshdr->sh_name); + if (sname != NULL + && (strcmp (sname, ".got") == 0 || strcmp (sname, ".got.plt") == 0)) + { + Elf_Scn *scn = NULL; + while ((scn = elf_nextscn (elf, scn)) != NULL) + { + GElf_Shdr shdr_mem; + GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); + if (shdr != NULL) + { + sname = elf_strptr (elf, shstrndx, shdr->sh_name); + if (sname != NULL && strcmp (sname, ".got") == 0) + return (sym->st_value >= shdr->sh_addr + && sym->st_value < shdr->sh_addr + shdr->sh_size); + } + } + } + } + + return false; +} -- 1.8.3.1