From 7a9361c00d53bb41c9ae331780226a99b9339920 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 31 Mar 2022 07:41:03 +1030 Subject: [PATCH] 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. --- bfd/elf32-ppc.c | 129 +++++++++++++------------ ld/testsuite/ld-powerpc/abs32-pie.d | 26 +++++ ld/testsuite/ld-powerpc/abs32-pie.r | 9 ++ ld/testsuite/ld-powerpc/abs32-reloc.s | 22 +++++ ld/testsuite/ld-powerpc/abs32-shared.d | 24 +++++ ld/testsuite/ld-powerpc/abs32-shared.r | 13 +++ ld/testsuite/ld-powerpc/abs32-static.d | 26 +++++ ld/testsuite/ld-powerpc/abs32-static.r | 6 ++ ld/testsuite/ld-powerpc/powerpc.exp | 12 +++ 9 files changed, 205 insertions(+), 62 deletions(-) create mode 100644 ld/testsuite/ld-powerpc/abs32-pie.d create mode 100644 ld/testsuite/ld-powerpc/abs32-pie.r create mode 100644 ld/testsuite/ld-powerpc/abs32-reloc.s create mode 100644 ld/testsuite/ld-powerpc/abs32-shared.d create mode 100644 ld/testsuite/ld-powerpc/abs32-shared.r create mode 100644 ld/testsuite/ld-powerpc/abs32-static.d create mode 100644 ld/testsuite/ld-powerpc/abs32-static.r diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 42273ca06fe..6dbb69013aa 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; diff --git a/ld/testsuite/ld-powerpc/abs32-pie.d b/ld/testsuite/ld-powerpc/abs32-pie.d new file mode 100644 index 00000000000..7f9912100b7 --- /dev/null +++ b/ld/testsuite/ld-powerpc/abs32-pie.d @@ -0,0 +1,26 @@ +#source: abs32-reloc.s +#as: -a32 +#ld: -melf32ppc -pie --hash-style=sysv --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x12345678 +#objdump: -dr + +.*: file format .* + +Disassembly of section \.text: + +00000138 <_start>: + 138: (80 fe ff f0|f0 ff fe 80) lwz r7,-16\(r30\) + 13c: (81 1e ff f8|f8 ff 1e 81) lwz r8,-8\(r30\) + 140: (81 3e ff ec|ec ff 3e 81) lwz r9,-20\(r30\) + 144: (81 5e ff f4|f4 ff 5e 81) lwz r10,-12\(r30\) + +Disassembly of section \.got: + +000101d8 <\.got>: + 101d8: (00 00 00 02|02 00 00 00) .* + 101dc: (00 00 00 00|00 00 00 00) .* + 101e0: (12 34 56 78|78 56 34 12) .* + 101e4: (00 00 00 01|01 00 00 00) .* + 101e8: (4e 80 00 21|21 00 80 4e) blrl + +000101ec <_GLOBAL_OFFSET_TABLE_>: + 101ec: (00 01 01 48|48 01 01 00) 00 00 00 00 00 00 00 00 .* diff --git a/ld/testsuite/ld-powerpc/abs32-pie.r b/ld/testsuite/ld-powerpc/abs32-pie.r new file mode 100644 index 00000000000..6a45fbf06f6 --- /dev/null +++ b/ld/testsuite/ld-powerpc/abs32-pie.r @@ -0,0 +1,9 @@ +#source: abs32-reloc.s +#as: -a32 +#ld: -melf32ppc -pie --hash-style=sysv --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x12345678 +#readelf: -rW + +Relocation section '\.rela\.dyn' at offset .* contains 2 entries: + Offset Info Type Sym\. Value Symbol's Name \+ Addend +000101c8 00000016 R_PPC_RELATIVE 101c8 +000101dc 00000016 R_PPC_RELATIVE 101c8 diff --git a/ld/testsuite/ld-powerpc/abs32-reloc.s b/ld/testsuite/ld-powerpc/abs32-reloc.s new file mode 100644 index 00000000000..70776c86411 --- /dev/null +++ b/ld/testsuite/ld-powerpc/abs32-reloc.s @@ -0,0 +1,22 @@ + .globl x + .hidden x + + .data + .p2align 2 +x: + .long x + .long a + .long b + .long c + + .text + .p2align 2 + .globl _start + .type _start,@function +_start: +0: + lwz 7,x@got(30) + lwz 8,a@got(30) + lwz 9,b@got(30) + lwz 10,c@got(30) + .size _start,.-_start diff --git a/ld/testsuite/ld-powerpc/abs32-shared.d b/ld/testsuite/ld-powerpc/abs32-shared.d new file mode 100644 index 00000000000..a08930bb1b9 --- /dev/null +++ b/ld/testsuite/ld-powerpc/abs32-shared.d @@ -0,0 +1,24 @@ +#source: abs32-reloc.s +#as: -a32 +#ld: -melf32ppc -shared --hash-style=sysv --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x12345678 +#objdump: -dr + +.*: file format .* + +Disassembly of section \.text: + +00000160 <_start>: + 160: (80 fe ff f0|f0 ff fe 80) lwz r7,-16\(r30\) + 164: (81 1e ff f8|f8 ff 1e 81) lwz r8,-8\(r30\) + 168: (81 3e ff ec|ec ff 3e 81) lwz r9,-20\(r30\) + 16c: (81 5e ff f4|f4 ff 5e 81) lwz r10,-12\(r30\) + +Disassembly of section \.got: + +000101f0 <\.got>: + 101f0: (00 00 00 02|02 00 00 00) .* + .\.\. + 10200: (4e 80 00 21|21 00 80 4e) blrl + +00010204 <_GLOBAL_OFFSET_TABLE_>: + 10204: (00 01 01 70|70 01 01 00) 00 00 00 00 00 00 00 00 .* diff --git a/ld/testsuite/ld-powerpc/abs32-shared.r b/ld/testsuite/ld-powerpc/abs32-shared.r new file mode 100644 index 00000000000..d0cd80ff717 --- /dev/null +++ b/ld/testsuite/ld-powerpc/abs32-shared.r @@ -0,0 +1,13 @@ +#source: abs32-reloc.s +#as: -a32 +#ld: -melf32ppc -shared --hash-style=sysv --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x12345678 +#readelf: -rW + +Relocation section '\.rela\.dyn' at offset .* contains 6 entries: + Offset Info Type Sym\. Value Symbol's Name \+ Addend +000101e0 00000016 R_PPC_RELATIVE 101e0 +000101f4 00000016 R_PPC_RELATIVE 101e0 +000101e4 00000401 R_PPC_ADDR32 00000001 a \+ 0 +000101fc 00000414 R_PPC_GLOB_DAT 00000001 a \+ 0 +000101ec 00000301 R_PPC_ADDR32 12345678 c \+ 0 +000101f8 00000314 R_PPC_GLOB_DAT 12345678 c \+ 0 diff --git a/ld/testsuite/ld-powerpc/abs32-static.d b/ld/testsuite/ld-powerpc/abs32-static.d new file mode 100644 index 00000000000..f37f1046e87 --- /dev/null +++ b/ld/testsuite/ld-powerpc/abs32-static.d @@ -0,0 +1,26 @@ +#source: abs32-reloc.s +#as: -a32 +#ld: -melf32ppc -static --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x12345678 +#objdump: -dr + +.*: file format .* + +Disassembly of section \.text: + +01800074 <_start>: + 1800074: (80 fe ff f0|f0 ff fe 80) lwz r7,-16\(r30\) + 1800078: (81 1e ff f8|f8 ff 1e 81) lwz r8,-8\(r30\) + 180007c: (81 3e ff ec|ec ff 3e 81) lwz r9,-20\(r30\) + 1800080: (81 5e ff f4|f4 ff 5e 81) lwz r10,-12\(r30\) + +Disassembly of section \.got: + +01810094 <\.got>: + 1810094: (00 00 00 02|02 00 00 00) .* + 1810098: (01 81 00 84|84 00 81 01) .* + 181009c: (12 34 56 78|78 56 34 12) .* + 18100a0: (00 00 00 01|01 00 00 00) .* + 18100a4: (4e 80 00 21|21 00 80 4e) blrl + +018100a8 <_GLOBAL_OFFSET_TABLE_>: + \.\.\. diff --git a/ld/testsuite/ld-powerpc/abs32-static.r b/ld/testsuite/ld-powerpc/abs32-static.r new file mode 100644 index 00000000000..3eca8776817 --- /dev/null +++ b/ld/testsuite/ld-powerpc/abs32-static.r @@ -0,0 +1,6 @@ +#source: abs32-reloc.s +#as: -a32 +#ld: -melf32ppc -static --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x12345678 +#readelf: -rW + +There are no relocations in this file. diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp index 9eff14fc89f..1c7a378aebc 100644 --- a/ld/testsuite/ld-powerpc/powerpc.exp +++ b/ld/testsuite/ld-powerpc/powerpc.exp @@ -173,6 +173,18 @@ set ppcelftests { {{objdump -dr relaxrl.d}} "rrelax"} {"build empty shared library" "-shared" "" "" "empty.s" {} "empty.so"} + {"abs32-static" "-melf32ppc -static --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x12345678" "" + "-a32" {abs32-reloc.s} + {{objdump {-dr} abs32-static.d} + {readelf {-rW} abs32-static.r}} "abs32-static"} + {"abs32-pie" "-melf32ppc -pie --hash-style=sysv --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x12345678" "" + "-a32" {abs32-reloc.s} + {{objdump {-dr} abs32-pie.d} + {readelf {-rW} abs32-pie.r}} "abs32-pie"} + {"abs32-shared" "-melf32ppc -shared --hash-style=sysv --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x12345678" "" + "-a32" {abs32-reloc.s} + {{objdump {-dr} abs32-shared.d} + {readelf {-rW} abs32-shared.r}} "abs32-shared"} } set ppc64elftests {