[ARM] Initialize GOT slot for local symbol in non-PIC link

Message ID 4574704.TTjcuOGBxn@polaris
State New
Headers show
Series
  • [ARM] Initialize GOT slot for local symbol in non-PIC link
Related show

Commit Message

Eric Botcazou July 13, 2018, 8:50 p.m.
Hi,

the context is as follows: on ARM/VxWorks 7, the R_ARM_TARGET2 relocation used 
for exception handling is R_ARM_GOT_PREL; moreover in Ada you can define local 
exceptions. In this case, you may end up with a GOT relocation against a local 
symbol in a non-PIC link and the ARM linker leaves the GOT slot uninitialized, 
unlike for example the i386 or the SPARC linkers in the same situation.

The attached patch fixes that by mimicing what the linker does for a global 
symbol that binds locally in the same situation (it also contains a small 
cleanup for this case).

Tested on ARM/VxWorks 7 and ARM/EABI, OK for the trunk?


2018-07-13  Eric Botcazou  <ebotcazou@adacore.com>

bfd/
	* elf32-arm.c (elf32_arm_final_link_relocate) <R_ARM_GOT32>: Small
	cleanup for the case of a global symbol that binds locally.  Also
	install a value in the GOT slot in the case of a local symbol in
	a non-PIC link.

-- 
Eric Botcazou

Comments

Nick Clifton July 18, 2018, 9:39 a.m. | #1
Hi Eric,

> Tested on ARM/VxWorks 7 and ARM/EABI, OK for the trunk?

> 

> 2018-07-13  Eric Botcazou  <ebotcazou@adacore.com>

> 

> bfd/

> 	* elf32-arm.c (elf32_arm_final_link_relocate) <R_ARM_GOT32>: Small

> 	cleanup for the case of a global symbol that binds locally.  Also

> 	install a value in the GOT slot in the case of a local symbol in

> 	a non-PIC link.

> 


Approved - please apply.

Cheers
  Nick

Patch

diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 9c611813c6..c5077a5308 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -11502,37 +11502,39 @@  elf32_arm_final_link_relocate (reloc_howto_type *	    howto,
 			   && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
 			       || h->root.type != bfd_link_hash_undefweak))
 		    outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
-		  else if (globals->fdpic_p)
-		    isrofixup = 1;
 		  else
-		    outrel.r_info = 0;
+		    {
+		      outrel.r_info = 0;
+		      if (globals->fdpic_p)
+			isrofixup = 1;
+		    }
 		  outrel.r_addend = dynreloc_value;
 		}
 
 	      /* The GOT entry is initialized to zero by default.
 		 See if we should install a different value.  */
 	      if (outrel.r_addend != 0
-		  && (outrel.r_info == 0 || globals->use_rel || isrofixup))
+		  && (globals->use_rel || outrel.r_info == 0))
 		{
 		  bfd_put_32 (output_bfd, outrel.r_addend,
 			      sgot->contents + off);
 		  outrel.r_addend = 0;
 		}
 
-	      if (outrel.r_info != 0 && !isrofixup)
+	      if (isrofixup)
+		arm_elf_add_rofixup (output_bfd,
+				     elf32_arm_hash_table(info)->srofixup,
+				     sgot->output_section->vma
+				     + sgot->output_offset + off);
+
+	      else if (outrel.r_info != 0)
 		{
 		  outrel.r_offset = (sgot->output_section->vma
 				     + sgot->output_offset
 				     + off);
 		  elf32_arm_add_dynreloc (output_bfd, info, srelgot, &outrel);
 		}
-	      else if (isrofixup)
-		{
-		  arm_elf_add_rofixup(output_bfd,
-				      elf32_arm_hash_table(info)->srofixup,
-				      sgot->output_section->vma
-				      + sgot->output_offset + off);
-		}
+
 	      h->got.offset |= 1;
 	    }
 	  value = sgot->output_offset + off;
@@ -11553,31 +11555,39 @@  elf32_arm_final_link_relocate (reloc_howto_type *	    howto,
 	    off &= ~1;
 	  else
 	    {
-	      if (globals->use_rel)
-		bfd_put_32 (output_bfd, dynreloc_value, sgot->contents + off);
+	      Elf_Internal_Rela outrel;
+	      int isrofixup = 0;
 
-	      if (bfd_link_pic (info) || dynreloc_st_type == STT_GNU_IFUNC)
+	      if (dynreloc_st_type == STT_GNU_IFUNC)
+		outrel.r_info = ELF32_R_INFO (0, R_ARM_IRELATIVE);
+	      else if (bfd_link_pic (info))
+		outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
+	      else
 		{
-		  Elf_Internal_Rela outrel;
+		  outrel.r_info = 0;
+		  if (globals->fdpic_p)
+		    isrofixup = 1;
+		}
+
+	      /* The GOT entry is initialized to zero by default.
+		 See if we should install a different value.  */
+	      if (globals->use_rel || outrel.r_info == 0)
+		bfd_put_32 (output_bfd, dynreloc_value, sgot->contents + off);
+
+	      if (isrofixup)
+		arm_elf_add_rofixup (output_bfd,
+				     globals->srofixup,
+				     sgot->output_section->vma
+				     + sgot->output_offset + off);
 
+	      else if (outrel.r_info != 0)
+		{
 		  outrel.r_addend = addend + dynreloc_value;
 		  outrel.r_offset = (sgot->output_section->vma
 				     + sgot->output_offset
 				     + off);
-		  if (dynreloc_st_type == STT_GNU_IFUNC)
-		    outrel.r_info = ELF32_R_INFO (0, R_ARM_IRELATIVE);
-		  else
-		    outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
 		  elf32_arm_add_dynreloc (output_bfd, info, srelgot, &outrel);
 		}
-	      else if (globals->fdpic_p)
-		{
-		  /* For FDPIC executables, we use rofixup to fix
-		     address at runtime.  */
-		  arm_elf_add_rofixup(output_bfd, globals->srofixup,
-				      sgot->output_section->vma + sgot->output_offset
-				      + off);
-		}
 
 	      local_got_offsets[r_symndx] |= 1;
 	    }