diff options
author | Alan Modra <amodra@gmail.com> | 2022-03-31 07:41:03 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2022-05-04 14:41:56 +0930 |
commit | 7a9361c00d53bb41c9ae331780226a99b9339920 (patch) | |
tree | 54c42f93b44a60e8956f9b628a3af2072b8010bd /bfd/elf32-ppc.c | |
parent | 24ef0d41ac9632ff85d3781e5852371e39661558 (diff) | |
download | gdb-7a9361c00d53bb41c9ae331780226a99b9339920.zip gdb-7a9361c00d53bb41c9ae331780226a99b9339920.tar.gz gdb-7a9361c00d53bb41c9ae331780226a99b9339920.tar.bz2 |
PowerPC32 treatment of absolute symbols
As already done for PowerPC64, fix dynamic relocs for absolute symbols.
The patch also tidies the dynamic reloc handling code in check_relocs,
removing leftover comments and code from when check_relocs was called
as each object file was read in.
bfd/
* elf32-ppc.c (ppc_elf_check_relocs): Set isym and ifunc earlier.
Rearrange tests for dynamic relocs, handling absolute symbols.
(allocate_dynrelocs): Don't allocate dynamic relocs for locally
defined absolute symbols.
(ppc_elf_size_dynamic_sections): Similarly.
(ppc_elf_relocate_section): Similarly.
ld/
* testsuite/ld-powerpc/abs32-pie.d,
* testsuite/ld-powerpc/abs32-pie.r,
* testsuite/ld-powerpc/abs32-reloc.s,
* testsuite/ld-powerpc/abs32-shared.d,
* testsuite/ld-powerpc/abs32-shared.r,
* testsuite/ld-powerpc/abs32-static.d,
* testsuite/ld-powerpc/abs32-static.r: New tests.
* testsuite/ld-powerpc/powerpc.exp: Run them.
Diffstat (limited to 'bfd/elf32-ppc.c')
-rw-r--r-- | bfd/elf32-ppc.c | 129 |
1 files changed, 67 insertions, 62 deletions
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 42273ca..6dbb690 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -2929,6 +2929,7 @@ ppc_elf_check_relocs (bfd *abfd, unsigned long r_symndx; enum elf_ppc_reloc_type r_type; struct elf_link_hash_entry *h; + Elf_Internal_Sym *isym; int tls_type; struct plt_entry **ifunc; struct plt_entry **pltent; @@ -2936,13 +2937,19 @@ ppc_elf_check_relocs (bfd *abfd, r_symndx = ELF32_R_SYM (rel->r_info); if (r_symndx < symtab_hdr->sh_info) - h = NULL; + { + h = NULL; + isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx); + if (isym == NULL) + return false; + } else { h = sym_hashes[r_symndx - symtab_hdr->sh_info]; while (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; + isym = NULL; } /* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got. @@ -2962,13 +2969,16 @@ ppc_elf_check_relocs (bfd *abfd, tls_type = 0; r_type = ELF32_R_TYPE (rel->r_info); ifunc = NULL; - if (h == NULL && htab->elf.target_os != is_vxworks) + if (h != NULL) + { + if (h->type == STT_GNU_IFUNC) + { + h->needs_plt = 1; + ifunc = &h->plt.plist; + } + } + else if (htab->elf.target_os != is_vxworks) { - Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, - abfd, r_symndx); - if (isym == NULL) - return false; - if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC) { /* Set PLT_IFUNC flag for this sym, no GOT entry yet. */ @@ -3294,12 +3304,10 @@ ppc_elf_check_relocs (bfd *abfd, htab->plt_type = PLT_OLD; htab->old_bfd = abfd; } - if (h != NULL && h->type == STT_GNU_IFUNC) - { - h->needs_plt = 1; - if (!update_plt_info (abfd, &h->plt.plist, NULL, 0)) - return false; - } + if (h != NULL + && ifunc != NULL + && !update_plt_info (abfd, ifunc, NULL, 0)) + return false; break; /* This relocation describes the C++ object vtable hierarchy. @@ -3347,12 +3355,6 @@ ppc_elf_check_relocs (bfd *abfd, reliably deduce the GOT pointer value needed for PLT call stubs. */ asection *s; - Elf_Internal_Sym *isym; - - isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, - abfd, r_symndx); - if (isym == NULL) - return false; s = bfd_section_from_elf_index (abfd, isym->st_shndx); if (s == got2) @@ -3421,38 +3423,21 @@ ppc_elf_check_relocs (bfd *abfd, } dodyn: - /* If we are creating a shared library, and this is a reloc - against a global symbol, or a non PC relative reloc - against a local symbol, then we need to copy the reloc - into the shared library. However, if we are linking with - -Bsymbolic, we do not need to copy a reloc against a - global symbol which is defined in an object we are - including in the link (i.e., DEF_REGULAR is set). At - this point we have not seen all the input files, so it is - possible that DEF_REGULAR is not set now but will be set - later (it is never cleared). In case of a weak definition, - DEF_REGULAR may be cleared later by a strong definition in - a shared library. We account for that possibility below by - storing information in the dyn_relocs field of the hash - table entry. A similar situation occurs when creating - shared libraries and symbol visibility changes render the - symbol local. - - If on the other hand, we are creating an executable, we - may need to keep relocations for symbols satisfied by a - dynamic library if we manage to avoid copy relocs for the - symbol. */ - if ((bfd_link_pic (info) - && (must_be_dyn_reloc (info, r_type) - || (h != NULL - && (!SYMBOLIC_BIND (info, h) - || h->root.type == bfd_link_hash_defweak - || !h->def_regular)))) - || (ELIMINATE_COPY_RELOCS - && !bfd_link_pic (info) - && h != NULL - && (h->root.type == bfd_link_hash_defweak - || !h->def_regular))) + /* Set up information for symbols that might need dynamic + relocations. At this point in linking we have read all + the input files and resolved most symbols, but have not + yet decided whether symbols are dynamic or finalized + symbol flags. In some cases we might be setting dynamic + reloc info for symbols that do not end up needing such. + That's OK, adjust_dynamic_symbol and allocate_dynrelocs + work together with this code. */ + if ((h != NULL + && !SYMBOL_REFERENCES_LOCAL (info, h)) + || (bfd_link_pic (info) + && (h != NULL + ? !bfd_is_abs_symbol (&h->root) + : isym->st_shndx != SHN_ABS) + && must_be_dyn_reloc (info, r_type))) { #ifdef DEBUG fprintf (stderr, @@ -3507,12 +3492,6 @@ ppc_elf_check_relocs (bfd *abfd, bool is_ifunc; asection *s; void *vpp; - Elf_Internal_Sym *isym; - - isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, - abfd, r_symndx); - if (isym == NULL) - return false; s = bfd_section_from_elf_index (abfd, isym->st_shndx); if (s == NULL) @@ -3520,7 +3499,7 @@ ppc_elf_check_relocs (bfd *abfd, vpp = &elf_section_data (s)->local_dynrel; rel_head = (struct ppc_dyn_relocs **) vpp; - is_ifunc = ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC; + is_ifunc = ifunc != NULL; p = *rel_head; if (p != NULL && p->sec == sec && p->ifunc != is_ifunc) p = p->next; @@ -5170,7 +5149,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (((bfd_link_pic (info) && !((eh->tls_mask & TLS_TLS) != 0 && bfd_link_executable (info) - && SYMBOL_REFERENCES_LOCAL (info, &eh->elf))) + && SYMBOL_REFERENCES_LOCAL (info, &eh->elf)) + && !bfd_is_abs_symbol (&h->root)) || (htab->elf.dynamic_sections_created && eh->elf.dynindx != -1 && !SYMBOL_REFERENCES_LOCAL (info, &eh->elf))) @@ -5540,6 +5520,8 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, char *lgot_masks; bfd_size_type locsymcount; Elf_Internal_Shdr *symtab_hdr; + Elf_Internal_Sym *local_syms; + Elf_Internal_Sym *isym; if (!is_ppc_elf (ibfd)) continue; @@ -5596,8 +5578,18 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, local_plt = (struct plt_entry **) end_local_got; end_local_plt = local_plt + locsymcount; lgot_masks = (char *) end_local_plt; + local_syms = (Elf_Internal_Sym *) symtab_hdr->contents; + if (local_syms == NULL && locsymcount != 0) + { + local_syms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, locsymcount, + 0, NULL, NULL, NULL); + if (local_syms == NULL) + return false; + } - for (; local_got < end_local_got; ++local_got, ++lgot_masks) + for (isym = local_syms; + local_got < end_local_got; + ++local_got, ++lgot_masks, ++isym) if (*local_got > 0) { unsigned int need; @@ -5611,7 +5603,8 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, *local_got = allocate_got (htab, need); if (bfd_link_pic (info) && !((*lgot_masks & TLS_TLS) != 0 - && bfd_link_executable (info))) + && bfd_link_executable (info)) + && isym->st_shndx != SHN_ABS) { asection *srel; @@ -5684,6 +5677,15 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, else ent->plt.offset = (bfd_vma) -1; } + + if (local_syms != NULL + && symtab_hdr->contents != (unsigned char *) local_syms) + { + if (!info->keep_memory) + free (local_syms); + else + symtab_hdr->contents = (unsigned char *) local_syms; + } } /* Allocate space for global sym dynamic relocs. */ @@ -7796,7 +7798,10 @@ ppc_elf_relocate_section (bfd *output_bfd, || !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) && !(tls_ty != 0 && bfd_link_executable (info) - && SYMBOL_REFERENCES_LOCAL (info, h)))) + && SYMBOL_REFERENCES_LOCAL (info, h)) + && (h != NULL + ? !bfd_is_abs_symbol (&h->root) + : sym->st_shndx != SHN_ABS))) { asection *rsec = htab->elf.srelgot; bfd_byte * loc; |