summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2022-03-31 07:41:03 +1030
committerAlan Modra <amodra@gmail.com>2022-05-04 14:41:56 +0930
commit7a9361c00d53bb41c9ae331780226a99b9339920 (patch)
tree54c42f93b44a60e8956f9b628a3af2072b8010bd
parent24ef0d41ac9632ff85d3781e5852371e39661558 (diff)
downloadbinutils-gdb-7a9361c00d53bb41c9ae331780226a99b9339920.tar.gz
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.
-rw-r--r--bfd/elf32-ppc.c129
-rw-r--r--ld/testsuite/ld-powerpc/abs32-pie.d26
-rw-r--r--ld/testsuite/ld-powerpc/abs32-pie.r9
-rw-r--r--ld/testsuite/ld-powerpc/abs32-reloc.s22
-rw-r--r--ld/testsuite/ld-powerpc/abs32-shared.d24
-rw-r--r--ld/testsuite/ld-powerpc/abs32-shared.r13
-rw-r--r--ld/testsuite/ld-powerpc/abs32-static.d26
-rw-r--r--ld/testsuite/ld-powerpc/abs32-static.r6
-rw-r--r--ld/testsuite/ld-powerpc/powerpc.exp12
9 files changed, 205 insertions, 62 deletions
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 {