This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

powerpc small data relocs


This patch started off as a fairly simple additional check that
_SDA_BASE_ and _SDA2_BASE_ were properly defined in relocate_section,
but grew somewhat when I found a number of untidy areas.  Besides
error checking, this patch:
- removes the assumption that _SDA_BASE_ is at offset 0x8000 in
  .sdata, which may not be true for custom linker scripts,
- allows SDAREL16 relocs in shared libs as per the ABI (*), and,
- downgrades an EMB_SDA2REL error to a warning.

*) Don't try to use this for -msecure-plt code.  .got and .sdata will
likely be too far away.

	PR ld/10406
	* elf32-ppc.c (ppc_elf_howto_raw): Make R_PPC_EMB_SDAI16 and
	R_PPC_EMB_SDA2I16 complain_overflow_signed.
	(create_sdata_sym): Pass info rather than htab.
	Update all callers.  Ensure symbols are hidden.
	(ppc_elf_check_relocs): Allow SDAREL16 when shared.
	(ppc_elf_size_dynamic_sections): When shared, equate _SDA_BASE_ to
	_GLOBAL_OFFSET_TABLE_.
	(elf_finish_pointer_linker_section): Don't assume that sdata base
	symbol is always at 0x8000 offset.  Don't subtract the addend here.
	(is_static_defined): New function.
	(ppc_elf_relocate_section): Verify symbol base used in SDA relocs
	is statically defined.  Clear addend for EMB_SDAI16 and EMB_SDA2I16
	relocs.  Downgrade error on unexpected section for EMB_SDA2REL
	reloc symbols to a warning.

Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.267
diff -u -p -r1.267 elf32-ppc.c
--- bfd/elf32-ppc.c	10 Aug 2009 13:38:44 -0000	1.267
+++ bfd/elf32-ppc.c	18 Sep 2009 12:04:29 -0000
@@ -1300,7 +1300,7 @@ static reloc_howto_type ppc_elf_howto_ra
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_bitfield, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 bfd_elf_generic_reloc,	/* special_function */
 	 "R_PPC_EMB_SDAI16",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -1317,7 +1317,7 @@ static reloc_howto_type ppc_elf_howto_ra
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_bitfield, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 bfd_elf_generic_reloc,	/* special_function */
 	 "R_PPC_EMB_SDA2I16",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -3129,9 +3129,10 @@ ppc_elf_add_symbol_hook (bfd *abfd,
 }
 
 static bfd_boolean
-create_sdata_sym (struct ppc_elf_link_hash_table *htab,
-		  elf_linker_section_t *lsect)
+create_sdata_sym (struct bfd_link_info *info, elf_linker_section_t *lsect)
 {
+  struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info);
+
   lsect->sym = elf_link_hash_lookup (&htab->elf, lsect->sym_name,
 				     TRUE, FALSE, TRUE);
   if (lsect->sym == NULL)
@@ -3139,6 +3140,7 @@ create_sdata_sym (struct ppc_elf_link_ha
   if (lsect->sym->root.type == bfd_link_hash_new)
     lsect->sym->non_elf = 0;
   lsect->sym->ref_regular = 1;
+  _bfd_elf_link_hash_hide_symbol (info, lsect->sym, TRUE);
   return TRUE;
 }
 
@@ -3168,7 +3170,7 @@ ppc_elf_create_linker_section (bfd *abfd
     return FALSE;
   lsect->section = s;
 
-  return create_sdata_sym (htab, lsect);
+  return create_sdata_sym (info, lsect);
 }
 
 /* Find a linker generated pointer with a given addend and type.  */
@@ -3633,13 +3635,8 @@ ppc_elf_check_relocs (bfd *abfd,
 	  break;
 
 	case R_PPC_SDAREL16:
-	  if (info->shared)
-	    {
-	      bad_shared_reloc (abfd, r_type);
-	      return FALSE;
-	    }
 	  if (htab->sdata[0].sym == NULL
-	      && !create_sdata_sym (htab, &htab->sdata[0]))
+	      && !create_sdata_sym (info, &htab->sdata[0]))
 	    return FALSE;
 	  if (h != NULL)
 	    {
@@ -3655,7 +3652,7 @@ ppc_elf_check_relocs (bfd *abfd,
 	      return FALSE;
 	    }
 	  if (htab->sdata[1].sym == NULL
-	      && !create_sdata_sym (htab, &htab->sdata[1]))
+	      && !create_sdata_sym (info, &htab->sdata[1]))
 	    return FALSE;
 	  if (h != NULL)
 	    {
@@ -3672,10 +3669,10 @@ ppc_elf_check_relocs (bfd *abfd,
 	      return FALSE;
 	    }
 	  if (htab->sdata[0].sym == NULL
-	      && !create_sdata_sym (htab, &htab->sdata[0]))
+	      && !create_sdata_sym (info, &htab->sdata[0]))
 	    return FALSE;
 	  if (htab->sdata[1].sym == NULL
-	      && !create_sdata_sym (htab, &htab->sdata[1]))
+	      && !create_sdata_sym (info, &htab->sdata[1]))
 	    return FALSE;
 	  if (h != NULL)
 	    {
@@ -5660,6 +5657,18 @@ ppc_elf_size_dynamic_sections (bfd *outp
 
       htab->elf.hgot->root.u.def.value = g_o_t;
     }
+  if (info->shared)
+    {
+      struct elf_link_hash_entry *sda = htab->sdata[0].sym;
+      if (sda != NULL
+	  && !(sda->root.type == bfd_link_hash_defined
+	       || sda->root.type == bfd_link_hash_defweak))
+	{
+	  sda->root.type = bfd_link_hash_defined;
+	  sda->root.u.def.section = htab->elf.hgot->root.u.def.section;
+	  sda->root.u.def.value = htab->elf.hgot->root.u.def.value;
+	}
+    }
 
   if (htab->glink != NULL
       && htab->glink->size != 0
@@ -6446,9 +6455,10 @@ elf_finish_pointer_linker_section (bfd *
       linker_section_ptr->offset += 1;
     }
 
-  relocation = (lsect->section->output_offset
+  relocation = (lsect->section->output_section->vma
+		+ lsect->section->output_offset
 		+ linker_section_ptr->offset - 1
-		- 0x8000);
+		- SYM_VAL (lsect->sym));
 
 #ifdef DEBUG
   fprintf (stderr,
@@ -6456,9 +6466,7 @@ elf_finish_pointer_linker_section (bfd *
 	   lsect->name, (long) relocation, (long) relocation);
 #endif
 
-  /* Subtract out the addend, because it will get added back in by the normal
-     processing.  */
-  return relocation - linker_section_ptr->addend;
+  return relocation;
 }
 
 #define PPC_LO(v) ((v) & 0xffff)
@@ -6528,6 +6536,17 @@ write_glink_stub (struct plt_entry *ent,
     }
 }
 
+/* Return true if symbol is defined statically.  */
+
+static bfd_boolean
+is_static_defined (struct elf_link_hash_entry *h)
+{
+  return ((h->root.type == bfd_link_hash_defined
+	   || h->root.type == bfd_link_hash_defweak)
+	  && h->root.u.def.section != NULL
+	  && h->root.u.def.section->output_section != NULL);
+}
+
 /* The RELOCATE_SECTION function is called by the ELF backend linker
    to handle the relocations for a section.
 
@@ -7629,17 +7648,29 @@ ppc_elf_relocate_section (bfd *output_bf
 	  /* Indirect .sdata relocation.  */
 	case R_PPC_EMB_SDAI16:
 	  BFD_ASSERT (htab->sdata[0].section != NULL);
+	  if (!is_static_defined (htab->sdata[0].sym))
+	    {
+	      unresolved_reloc = TRUE;
+	      break;
+	    }
 	  relocation
 	    = elf_finish_pointer_linker_section (input_bfd, &htab->sdata[0],
 						 h, relocation, rel);
+	  addend = 0;
 	  break;
 
 	  /* Indirect .sdata2 relocation.  */
 	case R_PPC_EMB_SDA2I16:
 	  BFD_ASSERT (htab->sdata[1].section != NULL);
+	  if (!is_static_defined (htab->sdata[1].sym))
+	    {
+	      unresolved_reloc = TRUE;
+	      break;
+	    }
 	  relocation
 	    = elf_finish_pointer_linker_section (input_bfd, &htab->sdata[1],
 						 h, relocation, rel);
+	  addend = 0;
 	  break;
 
 	  /* Handle the TOC16 reloc.  We want to use the offset within the .got
@@ -7692,12 +7723,16 @@ ppc_elf_relocate_section (bfd *output_bf
 	case R_PPC_SDAREL16:
 	  {
 	    const char *name;
+	    struct elf_link_hash_entry *sda = htab->sdata[0].sym;
 
-	    if (sec == NULL || sec->output_section == NULL)
+	    if (sec == NULL
+		|| sec->output_section == NULL
+		|| !is_static_defined (sda))
 	      {
 		unresolved_reloc = TRUE;
 		break;
 	      }
+	    addend -= SYM_VAL (sda);
 
 	    name = bfd_get_section_name (abfd, sec->output_section);
 	    if (! ((CONST_STRNEQ (name, ".sdata")
@@ -7713,7 +7748,6 @@ ppc_elf_relocate_section (bfd *output_bf
 		   howto->name,
 		   name);
 	      }
-	    addend -= SYM_VAL (htab->sdata[0].sym);
 	  }
 	  break;
 
@@ -7721,12 +7755,16 @@ ppc_elf_relocate_section (bfd *output_bf
 	case R_PPC_EMB_SDA2REL:
 	  {
 	    const char *name;
+	    struct elf_link_hash_entry *sda = htab->sdata[1].sym;
 
-	    if (sec == NULL || sec->output_section == NULL)
+	    if (sec == NULL
+		|| sec->output_section == NULL
+		|| !is_static_defined (sda))
 	      {
 		unresolved_reloc = TRUE;
 		break;
 	      }
+	    addend -= SYM_VAL (sda);
 
 	    name = bfd_get_section_name (abfd, sec->output_section);
 	    if (! (CONST_STRNEQ (name, ".sdata2")
@@ -7739,12 +7777,7 @@ ppc_elf_relocate_section (bfd *output_bf
 		   sym_name,
 		   howto->name,
 		   name);
-
-		bfd_set_error (bfd_error_bad_value);
-		ret = FALSE;
-		continue;
 	      }
-	    addend -= SYM_VAL (htab->sdata[1].sym);
 	  }
 	  break;
 
@@ -7754,6 +7787,7 @@ ppc_elf_relocate_section (bfd *output_bf
 	  {
 	    const char *name;
 	    int reg;
+	    struct elf_link_hash_entry *sda = NULL;
 
 	    if (sec == NULL || sec->output_section == NULL)
 	      {
@@ -7768,13 +7802,13 @@ ppc_elf_relocate_section (bfd *output_bf
 		     && (name[5] == 0 || name[5] == '.'))))
 	      {
 		reg = 13;
-		addend -= SYM_VAL (htab->sdata[0].sym);
+		sda = htab->sdata[0].sym;
 	      }
 	    else if (CONST_STRNEQ (name, ".sdata2")
 		     || CONST_STRNEQ (name, ".sbss2"))
 	      {
 		reg = 2;
-		addend -= SYM_VAL (htab->sdata[1].sym);
+		sda = htab->sdata[1].sym;
 	      }
 	    else if (strcmp (name, ".PPC.EMB.sdata0") == 0
 		     || strcmp (name, ".PPC.EMB.sbss0") == 0)
@@ -7796,6 +7830,16 @@ ppc_elf_relocate_section (bfd *output_bf
 		continue;
 	      }
 
+	    if (sda != NULL)
+	      {
+		if (!is_static_defined (sda))
+		  {
+		    unresolved_reloc = TRUE;
+		    break;
+		  }
+		addend -= SYM_VAL (sda);
+	      }
+
 	    if (r_type == R_PPC_EMB_SDA21)
 	      {			/* fill in register field */
 		insn = bfd_get_32 (output_bfd, contents + rel->r_offset);

-- 
Alan Modra
Australia Development Lab, IBM


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]