public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* PowerPC32 treatment of absolute symbols
@ 2022-05-04  5:14 Alan Modra
  0 siblings, 0 replies; only message in thread
From: Alan Modra @ 2022-05-04  5:14 UTC (permalink / raw)
  To: binutils

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.

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 {

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-05-04  5:14 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-04  5:14 PowerPC32 treatment of absolute symbols Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).