From: Roland McGrath Date: Sat, 13 Aug 2005 03:26:06 +0000 (+0000) Subject: libebl/ X-Git-Tag: elfutils-0.120~125 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f8873cb86317d18399593eb95947e0c543bc9d72;p=thirdparty%2Felfutils.git libebl/ 2005-08-12 Roland McGrath * ppc_symbol.c (find_dyn_got): New function, broken out of ... (ppc_bss_plt_p): ... here. Call that. (ppc_check_special_symbol): Use find_dyn_got to fetch value to check against _GLOBAL_OFFSET_TABLE_. --- diff --git a/libebl/ChangeLog b/libebl/ChangeLog index 68ec22178..3e6c6937d 100644 --- a/libebl/ChangeLog +++ b/libebl/ChangeLog @@ -1,5 +1,10 @@ 2005-08-12 Roland McGrath + * ppc_symbol.c (find_dyn_got): New function, broken out of ... + (ppc_bss_plt_p): ... here. Call that. + (ppc_check_special_symbol): Use find_dyn_got to fetch value to check + against _GLOBAL_OFFSET_TABLE_. + * libeblP.h (struct ebl): Add bss_plt_p hook. * eblopenbackend.c (default_bss_plt_p): New function. (fill_defaults): Use it. diff --git a/libebl/ppc64_symbol.c b/libebl/ppc64_symbol.c index ef0f5f70f..12188a98f 100644 --- a/libebl/ppc64_symbol.c +++ b/libebl/ppc64_symbol.c @@ -245,7 +245,8 @@ ppc64_copy_reloc_p (int reloc) } -/* Check whether given symbol's st_size is ok despite normal check failing. */ +/* Check whether given symbol's st_value and st_size are OK despite failing + normal checks. */ bool ppc64_check_special_symbol (Elf *elf, const GElf_Sym *sym __attribute__ ((unused)), diff --git a/libebl/ppc_symbol.c b/libebl/ppc_symbol.c index 8afabba2f..d642a7104 100644 --- a/libebl/ppc_symbol.c +++ b/libebl/ppc_symbol.c @@ -203,7 +203,40 @@ ppc_copy_reloc_p (int reloc) return reloc == R_PPC_COPY; } -/* Check whether given symbol's value is ok despite failing normal checks. */ +/* Look for DT_PPC_GOT. */ +static bool +find_dyn_got (Elf *elf, GElf_Addr *addr) +{ + 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 && shdr->sh_type == SHT_DYNAMIC) + { + Elf_Data *data = elf_getdata (scn, NULL); + if (data == NULL) + break; + for (unsigned int i = 0; i < shdr->sh_size / shdr->sh_entsize; ++i) + { + GElf_Dyn dyn_mem; + GElf_Dyn *dyn = gelf_getdyn (data, i, &dyn_mem); + if (dyn == NULL) + break; + if (dyn->d_tag == DT_PPC_GOT) + { + *addr = dyn->d_un.d_ptr; + return true; + } + } + } + } + + return false; +} + +/* Check whether given symbol's st_value and st_size are OK despite failing + normal checks. */ bool ppc_check_special_symbol (Elf *elf, const GElf_Sym *sym, @@ -215,6 +248,9 @@ ppc_check_special_symbol (Elf *elf, if (!strcmp (name, "_GLOBAL_OFFSET_TABLE_")) { + GElf_Addr gotaddr; + if (find_dyn_got (elf, &gotaddr)) + return sym->st_value == gotaddr; return sym->st_value == destshdr->sh_addr + 4; } @@ -243,27 +279,6 @@ ppc_check_special_symbol (Elf *elf, bool ppc_bss_plt_p (Elf *elf) { - 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 && shdr->sh_type == SHT_DYNAMIC) - { - Elf_Data *data = elf_getdata (scn, NULL); - if (data == NULL) - break; - for (unsigned int i = 0; i < shdr->sh_size / shdr->sh_entsize; ++i) - { - GElf_Dyn dyn_mem; - GElf_Dyn *dyn = gelf_getdyn (data, i, &dyn_mem); - if (dyn == NULL) - break; - if (dyn->d_tag == DT_PPC_GOT) - return false; - } - } - } - - return true; + GElf_Addr addr; + return ! find_dyn_got (elf, &addr); }