This is the mail archive of the binutils@sources.redhat.com 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]

[arm] Add TARGET2 and PREL31 relocations


The attached patch adds gas, ld and bfd support for the R_ARM_TARGET2 and 
R_ARM_PREL31 relocations. It also add bfd support for R_ARM_GOT_PREL 
relocation.

The R_ARM_TARGET2 relocation maps to either a R_ARM_ABS32 or R_ARM_GOT_PREL 
relocation (or other values in as-yet unsupported targets). We need to know 
which of these the target is using before we scan the input symbols, so that 
we can size the .got section correctly. I moved the setting of th TARGET{1,2} 
meanings from arm_elf_before_allocation to 
arm_elf_create_output_section_statements for this reason.

R_ARM_PREL31 is similar to R_ARM_REL32, but only a 31-bit offset.

Tested with cross to arm-none-elf and building --enable-targets=all.
Ok?

Paul

2004-09-17 Paul Brook  <paul@codesourcery.com>

bfd/
 * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add prototype.
 (bfd_elf32_arm_process_before_allocation): Update prototype.
 * bfd-in2.h: Regenerate.
 * bfd/elf32-arm.h (elf32_arm_link_hash_table): Add target2_reloc.
 (elf32_arm_link_hash_table_create): Set it.
 (bfd_elf32_arm_process_before_allocation): Remove target1_is_rel.
 (bfd_elf32_arm_set_target_relocs): New function.
 (arm_real_reloc_type): New function.
 (elf32_arm_final_link_relocate): Use it.  Handle R_ARM_PREL31 and
 R_ARM_GOT_PREL.  Remove R_ARM_TARGET1.
 (elf32_arm_gc_sweep_hook): Ditto.
 (elf32_arm_check_relocs): Ditto.
 (elf32_arm_relocate_section): Handle R_ARM_GOT_PREL.
 * elfarm-nabi.c (elf32_arm_howto_table): Add R_ARM_PREL31 and
 R_ARM_GOT_TARGET2.
 (elf32_arm_got_prel): New variable.
 (elf32_arm_howto_from_type): New function.
 (elf32_arm_info_to_howto): Use it.
 (elf32_arm_reloc_map): Add BFD_RELOC_ARM_PREL31 and
 BFD_RELOC_ARM_TARGET2.
 * libbfd.h: Regenerate.
 * reloc.c: Add BFD_RELOC_ARM_TARGET2 and BFD_RELOC_ARM_PREL31.
gas/
 * config/tc-arm.c (s_arm_rel31): New funciton.
 (md_pseudo_table): Add .rel31.
 (md_apply_fix3): Handle BFD_RELOC_ARM_TARGET2, 
 BFD_RELOC_32_PCREL and BFD_RELOC_ARM_PREL31.
 (tc_gen_reloc): Handle BFD_RELOC_ARM_PREL31 and BFD_RELOC_ARM_TARGET2.
 (arm_fix_adjustable): Return 0 for BFD_RELOC_ARM_TARGET2.
 (arm_parse_reloc): Add (target2).
gas/testsuite/
 * gas/arm/pic.s: Add (target2).
 * gas/arm/pic.d: Ditto.
include/
 * elf/arm.h: Remove R_ARM_STKCHK and R_ARM_THM_STKCHK.
 Add R_ARM_TARGET2, R_ARM_PREL31, R_ARM_GOT_ABS, R_ARM_GOT_PREL,
 R_ARM_GOT_BREL12, R_ARM_GOTOFF12 and R_ARM_GOTRELAX.
ld/
 * ld.texinfo: Rename arm-specific section.  Document --target*
 * emulparams/armelf_fbsd.sh: Set TARGET2_TYPE.
 * emulparams/armelf_linux.sh: Ditto.
 * emulparams/armelf_nbsd.sh: Ditto.
 * emultempl/armelf.em: Set default for TARGET2_TYPE.
 (target2_type): New variable.
 (arm_elf_before_allocation): Don't pass target1_type.
 (arm_elf_create_output_section_statements): New function.
 (PARSE_AND_LIST_PROLOGUE): Add OPTION_TARGET2.
 (PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS): Add --target=.
 (PARSE_AND_LIST_ARGS_CASES): Handle OPTION_TARGET2.
 (LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS): Set.
 * emultempl/armelf_oabi.em (_before_allocation): Remove extra
 argument to bfd_elf32_arm_process_before_allocation.
ld/testsuite/
 * ld-arm/arm-target1-{abs,rel}.d}: New files.
 * ld-arm/arm-target1.s: New file.
 * ld-arm/arm-target2-{,got-}rel.d: New files.
 * ld-arm/arm-target2.s: New file.
 * ld-arm/arm-rel31.d: New files.
 * ld-arm/arm-rel31.s: New files.
 * ld-arm/arm.ld: New file.
 * ld-arm/arm-elf.exp: Add new tests.
? bfd/doc/bfdint.html
? gas/doc/as.info
? ld/ld.html
? ld/ldint.html
Index: bfd/bfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in.h,v
retrieving revision 1.88
diff -u -p -r1.88 bfd-in.h
--- bfd/bfd-in.h	13 Sep 2004 14:14:23 -0000	1.88
+++ bfd/bfd-in.h	17 Sep 2004 00:49:45 -0000
@@ -814,7 +814,10 @@ extern bfd_boolean bfd_elf32_arm_allocat
   (struct bfd_link_info *);
 
 extern bfd_boolean bfd_elf32_arm_process_before_allocation
-  (bfd *, struct bfd_link_info *, int, int, int);
+  (bfd *, struct bfd_link_info *, int, int);
+
+void bfd_elf32_arm_set_target_relocs
+  (struct bfd_link_info *, int, char *);
 
 extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
   (bfd *, struct bfd_link_info *);
Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.299
diff -u -p -r1.299 bfd-in2.h
--- bfd/bfd-in2.h	13 Sep 2004 14:14:23 -0000	1.299
+++ bfd/bfd-in2.h	17 Sep 2004 00:49:46 -0000
@@ -821,7 +821,10 @@ extern bfd_boolean bfd_elf32_arm_allocat
   (struct bfd_link_info *);
 
 extern bfd_boolean bfd_elf32_arm_process_before_allocation
-  (bfd *, struct bfd_link_info *, int, int, int);
+  (bfd *, struct bfd_link_info *, int, int);
+
+void bfd_elf32_arm_set_target_relocs
+  (struct bfd_link_info *, int, char *);
 
 extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
   (bfd *, struct bfd_link_info *);
@@ -1484,7 +1487,7 @@ void bfd_map_over_sections
 
 asection *bfd_sections_find_if
    (bfd *abfd,
-    bfd_boolean (*func) (bfd *abfd, asection *sect, void *obj),
+    bfd_boolean (*operation) (bfd *abfd, asection *sect, void *obj),
     void *obj);
 
 bfd_boolean bfd_set_section_size
@@ -2649,6 +2652,14 @@ entries in .init_array sections.  */
 /* Data segment base relative address.  */
   BFD_RELOC_ARM_SBREL32,
 
+/* This reloc is used for References to RTTI dta from exception handling
+tables.  The actual definition depends on the target.  It may be a
+pc-relative or some form of GOT-indirect relocation.  */
+  BFD_RELOC_ARM_TARGET2,
+
+/* 31-bit PC relative address.  */
+  BFD_RELOC_ARM_PREL31,
+
 /* Renesas / SuperH SH relocs.  Not all of these appear in object files.  */
   BFD_RELOC_SH_PCDISP8BY2,
   BFD_RELOC_SH_PCDISP12BY2,
Index: bfd/elf32-arm.h
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.h,v
retrieving revision 1.142
diff -u -p -r1.142 elf32-arm.h
--- bfd/elf32-arm.h	16 Sep 2004 14:52:02 -0000	1.142
+++ bfd/elf32-arm.h	17 Sep 2004 00:49:47 -0000
@@ -186,6 +186,9 @@ struct elf32_arm_link_hash_table
        Nonzero if R_ARM_TARGET1 means R_ARM_ABS32.  */
     int target1_is_rel;
 
+    /* The relocation to use for R_ARM_TARGET2 relocations.  */
+    int target2_reloc;
+
     /* The number of bytes in the initial entry in the PLT.  */
     bfd_size_type plt_header_size;
 
@@ -378,6 +381,7 @@ elf32_arm_link_hash_table_create (bfd *a
   ret->no_pipeline_knowledge = 0;
   ret->byteswap_code = 0;
   ret->target1_is_rel = 0;
+  ret->target2_reloc = R_ARM_NONE;
 #ifdef FOUR_WORD_PLT
   ret->plt_header_size = 16;
   ret->plt_entry_size = 16;
@@ -757,8 +761,7 @@ bfd_boolean
 bfd_elf32_arm_process_before_allocation (bfd *abfd,
 					 struct bfd_link_info *link_info,
 					 int no_pipeline_knowledge,
-					 int byteswap_code,
-					 int target1_is_rel)
+					 int byteswap_code)
 {
   Elf_Internal_Shdr *symtab_hdr;
   Elf_Internal_Rela *internal_relocs = NULL;
@@ -781,7 +784,7 @@ bfd_elf32_arm_process_before_allocation 
   BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
 
   globals->no_pipeline_knowledge = no_pipeline_knowledge;
-  globals->target1_is_rel = target1_is_rel;
+
   if (byteswap_code && !bfd_big_endian (abfd))
     {
       _bfd_error_handler (_("%B: BE8 images only valid in big-endian mode."),
@@ -906,6 +909,32 @@ error_return:
 }
 #endif
 
+
+#ifndef OLD_ARM_ABI
+/* Set target relocation values needed during linking.  */
+
+void
+bfd_elf32_arm_set_target_relocs (struct bfd_link_info *link_info,
+				 int target1_is_rel,
+				 char * target2_type)
+{
+  struct elf32_arm_link_hash_table *globals;
+
+  globals = elf32_arm_hash_table (link_info);
+
+  globals->target1_is_rel = target1_is_rel;
+  if (strcmp (target2_type, "rel") == 0)
+    globals->target2_reloc = R_ARM_REL32;
+  else if (strcmp (target2_type, "got-rel") == 0)
+    globals->target2_reloc = R_ARM_GOT_PREL;
+  else
+    {
+      _bfd_error_handler (_("Invalid TARGET2 relocation type '%s'."),
+			  target2_type);
+    }
+}
+#endif
+
 /* The thumb form of a long branch is a bit finicky, because the offset
    encoding is split over two fields, each in it's own instruction. They
    can occur in any order. So given a thumb form of long branch, and an
@@ -1151,6 +1180,32 @@ elf32_arm_to_thumb_stub (struct bfd_link
   return TRUE;
 }
 
+
+#ifndef OLD_ARM_ABI
+/* Some relocations map to different relocations depending on the
+   target.  Return the real relocation.  */
+static int
+arm_real_reloc_type (struct elf32_arm_link_hash_table * globals,
+		     int r_type)
+{
+  switch (r_type)
+    {
+    case R_ARM_TARGET1:
+      if (globals->target1_is_rel)
+	return R_ARM_REL32;
+      else
+	return R_ARM_ABS32;
+
+    case R_ARM_TARGET2:
+      return globals->target2_reloc;
+
+    default:
+      return r_type;
+    }
+}
+#endif /* OLD_ARM_ABI */
+
+
 /* Perform a relocation as part of a final link.  */
 
 static bfd_reloc_status_type
@@ -1186,15 +1241,9 @@ elf32_arm_final_link_relocate (reloc_how
 #ifndef OLD_ARM_ABI
   /* Some relocation type map to different relocations depending on the
      target.  We pick the right one here.  */
-  if (r_type == R_ARM_TARGET1)
-    {
-      if (globals->target1_is_rel)
-	r_type = R_ARM_REL32;
-      else
-	r_type = R_ARM_ABS32;
-      
-      howto = &elf32_arm_howto_table[r_type];
-    }
+  r_type = arm_real_reloc_type (globals, r_type);
+  if (r_type != howto->type)
+    howto = elf32_arm_howto_from_type (r_type);
 #endif /* OLD_ARM_ABI */
 
   /* If the start address has been set, then set the EF_ARM_HASENTRY
@@ -1245,6 +1294,7 @@ elf32_arm_final_link_relocate (reloc_how
     case R_ARM_REL32:
 #ifndef OLD_ARM_ABI
     case R_ARM_XPC25:
+    case R_ARM_PREL31:
 #endif
     case R_ARM_PLT32:
       /* r_symndx will be zero only for relocs against symbols
@@ -1257,7 +1307,11 @@ elf32_arm_final_link_relocate (reloc_how
 	 will use the symbol's value, which may point to a PLT entry, but we
 	 don't need to handle that here.  If we created a PLT entry, all
 	 branches in this object should go to it.  */
-      if ((r_type != R_ARM_ABS32 && r_type != R_ARM_REL32)
+      if ((r_type != R_ARM_ABS32 && r_type != R_ARM_REL32
+#ifndef OLD_ARM_ABI
+	   && r_type != R_ARM_PREL31
+#endif
+	   )
 	  && h != NULL
 	  && splt != NULL
 	  && h->plt.offset != (bfd_vma) -1)
@@ -1279,8 +1333,11 @@ elf32_arm_final_link_relocate (reloc_how
 	 into the output file to be resolved at run time.  */
       if (info->shared
 	  && (input_section->flags & SEC_ALLOC)
-	  && (r_type != R_ARM_REL32
-	      || !SYMBOL_CALLS_LOCAL (info, h))
+	  && ((r_type != R_ARM_REL32
+#ifndef OLD_ARM_ABI
+	      && r_type != R_ARM_PREL31
+#endif
+	      ) || !SYMBOL_CALLS_LOCAL (info, h))
 	  && (h == NULL
 	      || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
 	      || h->root.type != bfd_link_hash_undefweak)
@@ -1480,6 +1537,24 @@ elf32_arm_final_link_relocate (reloc_how
 		    + input_section->output_offset + rel->r_offset);
 	  value += addend;
 	  break;
+
+#ifndef OLD_ARM_ABI
+	case R_ARM_PREL31:
+	  value -= (input_section->output_section->vma
+		    + input_section->output_offset + rel->r_offset);
+	  value += signed_addend;
+	  if (! h || h->root.type != bfd_link_hash_undefweak)
+	    {
+	      /* Check for overflow */
+	      if ((value ^ (value >> 1)) & (1 << 30))
+		return bfd_reloc_overflow;
+	    }
+	  value &= 0x7fffffff;
+	  value |= (bfd_get_32 (input_bfd, hit_data) & 0x80000000);
+	  if (sym_flags == STT_ARM_TFUNC)
+	    value |= 1;
+	  break;
+#endif
 	}
 
       bfd_put_32 (input_bfd, value, hit_data);
@@ -1769,6 +1844,9 @@ elf32_arm_final_link_relocate (reloc_how
 				       (bfd_vma) 0);
 
     case R_ARM_GOT32:
+#ifndef OLD_ARM_ABI
+    case R_ARM_GOT_PREL:
+#endif
       /* Relocation is to the entry for this symbol in the
          global offset table.  */
       if (sgot == NULL)
@@ -1857,6 +1935,8 @@ elf32_arm_final_link_relocate (reloc_how
 
 	  value = sgot->output_offset + off;
 	}
+      if (r_type != R_ARM_GOT32)
+	value += sgot->output_section->vma;
 
       return _bfd_final_link_relocate (howto, input_bfd, input_section,
 				       contents, rel->r_offset, value,
@@ -2130,6 +2210,9 @@ elf32_arm_relocate_section (bfd *       
 		  break;
 
 	        case R_ARM_GOT32:
+#ifndef OLD_ARM_ABI
+		case R_ARM_GOT_PREL:
+#endif
 	          if ((WILL_CALL_FINISH_DYNAMIC_SYMBOL
 		       (elf_hash_table (info)->dynamic_sections_created,
 			info->shared, h))
@@ -2726,6 +2809,9 @@ elf32_arm_gc_sweep_hook (bfd *          
   const Elf_Internal_Rela *rel, *relend;
   unsigned long r_symndx;
   struct elf_link_hash_entry *h;
+  struct elf32_arm_link_hash_table * globals;
+
+  globals = elf32_arm_hash_table (info);
 
   elf_section_data (sec)->local_dynrel = NULL;
 
@@ -2735,66 +2821,77 @@ elf32_arm_gc_sweep_hook (bfd *          
 
   relend = relocs + sec->reloc_count;
   for (rel = relocs; rel < relend; rel++)
-    switch (ELF32_R_TYPE (rel->r_info))
-      {
-      case R_ARM_GOT32:
-	r_symndx = ELF32_R_SYM (rel->r_info);
-	if (r_symndx >= symtab_hdr->sh_info)
-	  {
-	    h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-	    if (h->got.refcount > 0)
-	      h->got.refcount -= 1;
-	  }
-	else if (local_got_refcounts != NULL)
-	  {
-	    if (local_got_refcounts[r_symndx] > 0)
-	      local_got_refcounts[r_symndx] -= 1;
-	  }
-	break;
+    {
+      int r_type;
 
-      case R_ARM_ABS32:
-      case R_ARM_REL32:
+      r_type = ELF32_R_TYPE (rel->r_info);
 #ifndef OLD_ARM_ABI
-      case R_ARM_TARGET1:
+      r_type = arm_real_reloc_type (globals, r_type);
 #endif
-      case R_ARM_PC24:
-      case R_ARM_PLT32:
-	r_symndx = ELF32_R_SYM (rel->r_info);
-	if (r_symndx >= symtab_hdr->sh_info)
-	  {
-	    struct elf32_arm_link_hash_entry *eh;
-	    struct elf32_arm_relocs_copied **pp;
-	    struct elf32_arm_relocs_copied *p;
+      switch (r_type)
+	{
+	case R_ARM_GOT32:
+#ifndef OLD_ARM_ABI
+	case R_ARM_GOT_PREL:
+#endif
+	  r_symndx = ELF32_R_SYM (rel->r_info);
+	  if (r_symndx >= symtab_hdr->sh_info)
+	    {
+	      h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+	      if (h->got.refcount > 0)
+		h->got.refcount -= 1;
+	    }
+	  else if (local_got_refcounts != NULL)
+	    {
+	      if (local_got_refcounts[r_symndx] > 0)
+		local_got_refcounts[r_symndx] -= 1;
+	    }
+	  break;
+
+	case R_ARM_ABS32:
+	case R_ARM_REL32:
+	case R_ARM_PC24:
+	case R_ARM_PLT32:
+#ifndef OLD_ARM_ABI
+	case R_ARM_PREL31:
+#endif
+	  r_symndx = ELF32_R_SYM (rel->r_info);
+	  if (r_symndx >= symtab_hdr->sh_info)
+	    {
+	      struct elf32_arm_link_hash_entry *eh;
+	      struct elf32_arm_relocs_copied **pp;
+	      struct elf32_arm_relocs_copied *p;
 
-	    h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+	      h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 
-	    if (h->plt.refcount > 0)
-	      h->plt.refcount -= 1;
+	      if (h->plt.refcount > 0)
+		h->plt.refcount -= 1;
 
-	    if (ELF32_R_TYPE (rel->r_info) == R_ARM_ABS32
+	      if (r_type == R_ARM_ABS32
 #ifndef OLD_ARM_ABI
-		|| ELF32_R_TYPE (rel->r_info) == R_ARM_TARGET1
+		  || r_type == R_ARM_PREL31
 #endif
-		|| ELF32_R_TYPE (rel->r_info) == R_ARM_REL32)
-	      {
-		eh = (struct elf32_arm_link_hash_entry *) h;
+		  || r_type == R_ARM_REL32)
+		{
+		  eh = (struct elf32_arm_link_hash_entry *) h;
 
-		for (pp = &eh->relocs_copied; (p = *pp) != NULL;
-		     pp = &p->next)
-		if (p->section == sec)
-		  {
-		    p->count -= 1;
-		    if (p->count == 0)
-		      *pp = p->next;
-		    break;
-		  }
-	      }
-	  }
-	break;
+		  for (pp = &eh->relocs_copied; (p = *pp) != NULL;
+		       pp = &p->next)
+		  if (p->section == sec)
+		    {
+		      p->count -= 1;
+		      if (p->count == 0)
+			*pp = p->next;
+		      break;
+		    }
+		}
+	    }
+	  break;
 
-      default:
-	break;
-      }
+	default:
+	  break;
+	}
+    }
 
   return TRUE;
 }
@@ -2837,16 +2934,24 @@ elf32_arm_check_relocs (bfd *abfd, struc
     {
       struct elf_link_hash_entry *h;
       unsigned long r_symndx;
+      int r_type;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
+      r_type = ELF32_R_TYPE (rel->r_info);
+#ifndef OLD_ARM_ABI
+      r_type = arm_real_reloc_type (htab, r_type);
+#endif
       if (r_symndx < symtab_hdr->sh_info)
         h = NULL;
       else
         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 
-      switch (ELF32_R_TYPE (rel->r_info))
+      switch (r_type)
         {
 	  case R_ARM_GOT32:
+#ifndef OLD_ARM_ABI
+	  case R_ARM_GOT_PREL:
+#endif
 	    /* This symbol requires a global offset table entry.  */
 	    if (h != NULL)
 	      {
@@ -2871,7 +2976,9 @@ elf32_arm_check_relocs (bfd *abfd, struc
 		  }
 		local_got_refcounts[r_symndx] += 1;
 	      }
-	    break;
+	    if (r_type == R_ARM_GOT32)
+	      break;
+	    /* Fall through.  */
 
 	  case R_ARM_GOTOFF:
 	  case R_ARM_GOTPC:
@@ -2886,11 +2993,11 @@ elf32_arm_check_relocs (bfd *abfd, struc
 
 	  case R_ARM_ABS32:
 	  case R_ARM_REL32:
-#ifndef OLD_ARM_ABI
-	  case R_ARM_TARGET1:
-#endif
 	  case R_ARM_PC24:
 	  case R_ARM_PLT32:
+#ifndef OLD_ARM_ABI
+	  case R_ARM_PREL31:
+#endif
 	    if (h != NULL)
 	      {
 		/* If this reloc is in a read-only section, we might
@@ -2906,8 +3013,8 @@ elf32_arm_check_relocs (bfd *abfd, struc
 		   refers to is in a different object.  We can't tell for
 		   sure yet, because something later might force the
 		   symbol local.  */
-		if (ELF32_R_TYPE (rel->r_info) == R_ARM_PC24
-		    || ELF32_R_TYPE (rel->r_info) == R_ARM_PLT32)
+		if (r_type == R_ARM_PC24
+		    || r_type == R_ARM_PLT32)
 		  h->needs_plt = 1;
 
 		/* If we create a PLT entry, this relocation will reference
@@ -2929,12 +3036,12 @@ elf32_arm_check_relocs (bfd *abfd, struc
                relocs_copied field of the hash table entry.  */
 	    if (info->shared
 		&& (sec->flags & SEC_ALLOC) != 0
-		&& ((ELF32_R_TYPE (rel->r_info) != R_ARM_PC24
-		     && ELF32_R_TYPE (rel->r_info) != R_ARM_PLT32
+		&& ((r_type != R_ARM_PC24
+		     && r_type != R_ARM_PLT32
 #ifndef OLD_ARM_ABI
-		     && ELF32_R_TYPE (rel->r_info) != R_ARM_TARGET1
+		     && r_type != R_ARM_PREL31
 #endif
-		     && ELF32_R_TYPE (rel->r_info) != R_ARM_REL32)
+		     && r_type != R_ARM_REL32)
 		    || (h != NULL
 			&& (! info->symbolic
 			    || !h->def_regular))))
@@ -3017,11 +3124,11 @@ elf32_arm_check_relocs (bfd *abfd, struc
 		    p->count = 0;
 		  }
 
-		if (ELF32_R_TYPE (rel->r_info) == R_ARM_ABS32
+		if (r_type == R_ARM_ABS32
 #ifndef OLD_ARM_ABI
-		    || ELF32_R_TYPE (rel->r_info) == R_ARM_TARGET1
+		    || r_type == R_ARM_PREL31
 #endif
-		    || ELF32_R_TYPE (rel->r_info) == R_ARM_REL32)
+		    || r_type == R_ARM_REL32)
 		  p->count += 1;
 	      }
 	    break;
Index: bfd/elfarm-nabi.c
===================================================================
RCS file: /cvs/src/src/bfd/elfarm-nabi.c,v
retrieving revision 1.23
diff -u -p -r1.23 elfarm-nabi.c
--- bfd/elfarm-nabi.c	13 Sep 2004 14:14:23 -0000	1.23
+++ bfd/elfarm-nabi.c	17 Sep 2004 00:49:48 -0000
@@ -636,6 +636,34 @@ static reloc_howto_type elf32_arm_howto_
 	 0xffffffff,		/* src_mask */
 	 0xffffffff,		/* dst_mask */
 	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_ARM_TARGET2,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_ARM_TARGET2",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_ARM_PREL31,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 31,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_ARM_PREL31",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x7fffffff,		/* src_mask */
+	 0x7fffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
 };
 
   /* GNU extension to record C++ vtable hierarchy */
@@ -702,52 +730,67 @@ static reloc_howto_type elf32_arm_thm_pc
 	 0x000000ff,		/* dst_mask */
 	 TRUE);			/* pcrel_offset */
 
-static void elf32_arm_info_to_howto
-  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
+/* Place relative GOT-indirect.  */
+static reloc_howto_type elf32_arm_got_prel =
+  HOWTO (R_ARM_GOT_PREL,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_ARM_GOT_PREL",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 TRUE);			/* pcrel_offset */
 
-static void
-elf32_arm_info_to_howto (abfd, bfd_reloc, elf_reloc)
-     bfd * abfd ATTRIBUTE_UNUSED;
-     arelent * bfd_reloc;
-     Elf_Internal_Rela * elf_reloc;
+static reloc_howto_type *
+elf32_arm_howto_from_type (unsigned int r_type)
 {
-  unsigned int r_type;
-
-  r_type = ELF32_R_TYPE (elf_reloc->r_info);
-
+  if (r_type < NUM_ELEM (elf32_arm_howto_table))
+    return &elf32_arm_howto_table[r_type];
+    
   switch (r_type)
     {
+    case R_ARM_GOT_PREL:
+      return &elf32_arm_got_prel;
+
     case R_ARM_GNU_VTINHERIT:
-      bfd_reloc->howto = & elf32_arm_vtinherit_howto;
-      break;
+      return &elf32_arm_vtinherit_howto;
 
     case R_ARM_GNU_VTENTRY:
-      bfd_reloc->howto = & elf32_arm_vtentry_howto;
-      break;
+      return &elf32_arm_vtentry_howto;
 
     case R_ARM_THM_PC11:
-      bfd_reloc->howto = & elf32_arm_thm_pc11_howto;
-      break;
+      return &elf32_arm_thm_pc11_howto;
 
     case R_ARM_THM_PC9:
-      bfd_reloc->howto = & elf32_arm_thm_pc9_howto;
-      break;
+      return &elf32_arm_thm_pc9_howto;
 
     default:
-      if (r_type >= NUM_ELEM (elf32_arm_howto_table))
-	bfd_reloc->howto = NULL;
-      else
-        bfd_reloc->howto = & elf32_arm_howto_table[r_type];
-      break;
+      return NULL;
     }
 }
 
+static void
+elf32_arm_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED, arelent * bfd_reloc,
+			 Elf_Internal_Rela * elf_reloc)
+{
+  unsigned int r_type;
+
+  r_type = ELF32_R_TYPE (elf_reloc->r_info);
+  bfd_reloc->howto = elf32_arm_howto_from_type (r_type);
+}
+
 struct elf32_arm_reloc_map
   {
     bfd_reloc_code_real_type  bfd_reloc_val;
     unsigned char             elf_reloc_val;
   };
 
+/* All entries in this list must also be present in elf32_arm_howto_table.  */
 static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] =
   {
     {BFD_RELOC_NONE,                 R_ARM_NONE},
@@ -771,7 +814,9 @@ static const struct elf32_arm_reloc_map 
     {BFD_RELOC_ARM_PLT32,            R_ARM_PLT32},
     {BFD_RELOC_ARM_TARGET1,	     R_ARM_TARGET1},
     {BFD_RELOC_ARM_ROSEGREL32,	     R_ARM_ROSEGREL32},
-    {BFD_RELOC_ARM_SBREL32,	     R_ARM_SBREL32}
+    {BFD_RELOC_ARM_SBREL32,	     R_ARM_SBREL32},
+    {BFD_RELOC_ARM_PREL31,	     R_ARM_PREL31},
+    {BFD_RELOC_ARM_TARGET2,	     R_ARM_TARGET2}
   };
 
 static reloc_howto_type *
Index: bfd/libbfd.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd.h,v
retrieving revision 1.124
diff -u -p -r1.124 libbfd.h
--- bfd/libbfd.h	13 Sep 2004 14:14:23 -0000	1.124
+++ bfd/libbfd.h	17 Sep 2004 00:49:48 -0000
@@ -1137,6 +1137,8 @@ static const char *const bfd_reloc_code_
   "BFD_RELOC_ARM_TARGET1",
   "BFD_RELOC_ARM_ROSEGREL32",
   "BFD_RELOC_ARM_SBREL32",
+  "BFD_RELOC_ARM_TARGET2",
+  "BFD_RELOC_ARM_PREL31",
   "BFD_RELOC_SH_PCDISP8BY2",
   "BFD_RELOC_SH_PCDISP12BY2",
   "BFD_RELOC_SH_IMM3",
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/src/src/bfd/reloc.c,v
retrieving revision 1.112
diff -u -p -r1.112 reloc.c
--- bfd/reloc.c	13 Sep 2004 14:14:23 -0000	1.112
+++ bfd/reloc.c	17 Sep 2004 00:49:49 -0000
@@ -2621,6 +2621,16 @@ ENUM
   BFD_RELOC_ARM_SBREL32
 ENUMDOC
   Data segment base relative address.
+ENUM
+  BFD_RELOC_ARM_TARGET2
+ENUMDOC
+  This reloc is used for References to RTTI dta from exception handling
+  tables.  The actual definition depends on the target.  It may be a
+  pc-relative or some form of GOT-indirect relocation.
+ENUM
+  BFD_RELOC_ARM_PREL31
+ENUMDOC
+  31-bit PC relative address.
 
 ENUM
   BFD_RELOC_SH_PCDISP8BY2
Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.176
diff -u -p -r1.176 tc-arm.c
--- gas/config/tc-arm.c	13 Sep 2004 14:14:26 -0000	1.176
+++ gas/config/tc-arm.c	17 Sep 2004 00:49:52 -0000
@@ -2445,6 +2445,7 @@ static void s_thumb_func PARAMS ((int));
 static void s_thumb_set PARAMS ((int));
 #ifdef OBJ_ELF
 static void s_arm_elf_cons PARAMS ((int));
+static void s_arm_rel31 (int nbytes);
 #endif
 
 static int my_get_expression PARAMS ((expressionS *, char **));
@@ -2468,6 +2469,7 @@ const pseudo_typeS md_pseudo_table[] =
 #ifdef OBJ_ELF
   { "word",        s_arm_elf_cons, 4 },
   { "long",        s_arm_elf_cons, 4 },
+  { "rel31",       s_arm_rel31,   0 },
 #else
   { "word",        cons, 4},
 #endif
@@ -12481,6 +12483,7 @@ md_apply_fix3 (fixP, valP, seg)
 #ifdef OBJ_ELF
     case BFD_RELOC_ARM_GOT32:
     case BFD_RELOC_ARM_GOTOFF:
+    case BFD_RELOC_ARM_TARGET2:
       md_number_to_chars (buf, 0, 4);
       break;
 #endif
@@ -12490,6 +12493,7 @@ md_apply_fix3 (fixP, valP, seg)
     case BFD_RELOC_ARM_TARGET1:
     case BFD_RELOC_ARM_ROSEGREL32:
     case BFD_RELOC_ARM_SBREL32:
+    case BFD_RELOC_32_PCREL:
       if (fixP->fx_done || fixP->fx_pcrel)
 	md_number_to_chars (buf, value, 4);
 #ifdef OBJ_ELF
@@ -12502,6 +12506,20 @@ md_apply_fix3 (fixP, valP, seg)
       break;
 
 #ifdef OBJ_ELF
+    case BFD_RELOC_ARM_PREL31:
+      if (fixP->fx_done || fixP->fx_pcrel)
+	{
+	  newval = md_chars_to_number (buf, 4) & 0x80000000;
+	  if ((value ^ (value >> 1)) & 0x40000000)
+	    {
+	      as_bad_where (fixP->fx_file, fixP->fx_line,
+			    _("rel31 relocation overflow"));
+	    }
+	  newval |= value & 0x7fffffff;
+	  md_number_to_chars (buf, newval, 4);
+	}
+      break;
+
     case BFD_RELOC_ARM_PLT32:
       /* It appears the instruction is fully prepared at this point.  */
       break;
@@ -12780,6 +12798,8 @@ tc_gen_reloc (section, fixp)
     case BFD_RELOC_ARM_TARGET1:
     case BFD_RELOC_ARM_ROSEGREL32:
     case BFD_RELOC_ARM_SBREL32:
+    case BFD_RELOC_ARM_PREL31:
+    case BFD_RELOC_ARM_TARGET2:
       code = fixp->fx_r_type;
       break;
 #endif
@@ -14090,7 +14110,8 @@ arm_fix_adjustable (fixP)
   /* Don't allow symbols to be discarded on GOT related relocs.  */
   if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
       || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
-      || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
+      || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
+      || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
     return 0;
 
   return 1;
@@ -14151,6 +14172,7 @@ arm_parse_reloc ()
     MAP ("(plt)",    BFD_RELOC_ARM_PLT32),
     MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
     MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
+    MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
     { NULL, 0,         BFD_RELOC_UNUSED }
 #undef MAP
   };
@@ -14225,6 +14247,50 @@ s_arm_elf_cons (nbytes)
   demand_empty_rest_of_line ();
 }
 
+
+/* Parse a .rel31 directive.  */
+
+static void
+s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
+{
+  expressionS exp;
+  char *p;
+  valueT highbit;
+    
+  SKIP_WHITESPACE ();
+
+  highbit = 0;
+  if (*input_line_pointer == '1')
+    highbit = 0x80000000;
+  else if (*input_line_pointer != '0')
+    as_bad (_("expected 0 or 1"));
+
+  input_line_pointer++;
+  SKIP_WHITESPACE ();
+  if (*input_line_pointer != ',')
+    as_bad (_("missing comma"));
+  input_line_pointer++;
+
+#ifdef md_flush_pending_output
+  md_flush_pending_output ();
+#endif
+
+#ifdef md_cons_align
+  md_cons_align (4);
+#endif
+
+  mapping_state (MAP_DATA);
+
+  expression (&exp);
+
+  p = frag_more (4);
+  md_number_to_chars (p, highbit, 4);
+  fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
+	       BFD_RELOC_ARM_PREL31);
+
+  demand_empty_rest_of_line ();
+}
+
 #endif /* OBJ_ELF */
 
 /* This is called from HANDLE_ALIGN in write.c.  Fill in the contents
Index: gas/testsuite/gas/arm/pic.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/pic.d,v
retrieving revision 1.7
diff -u -p -r1.7 pic.d
--- gas/testsuite/gas/arm/pic.d	13 Sep 2004 14:14:28 -0000	1.7
+++ gas/testsuite/gas/arm/pic.d	17 Sep 2004 00:49:52 -0000
@@ -17,3 +17,4 @@ Disassembly of section .text:
 			14: R_ARM_GOTPC	_GLOBAL_OFFSET_TABLE_
 			18: R_ARM_TARGET1	foo2
 			1c: R_ARM_SBREL32	foo3
+			20: R_ARM_TARGET2	foo4
Index: gas/testsuite/gas/arm/pic.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/pic.s,v
retrieving revision 1.3
diff -u -p -r1.3 pic.s
--- gas/testsuite/gas/arm/pic.s	13 Sep 2004 14:14:28 -0000	1.3
+++ gas/testsuite/gas/arm/pic.s	17 Sep 2004 00:49:52 -0000
@@ -11,3 +11,4 @@
 	.word	_GLOBAL_OFFSET_TABLE_ - 1b
 	.word foo2(TARGET1)
 	.word foo3(SBREL)
+	.word foo4(TARGET2)
Index: include/elf/arm.h
===================================================================
RCS file: /cvs/src/src/include/elf/arm.h,v
retrieving revision 1.15
diff -u -p -r1.15 arm.h
--- include/elf/arm.h	13 Sep 2004 14:14:30 -0000	1.15
+++ include/elf/arm.h	17 Sep 2004 00:49:52 -0000
@@ -130,10 +130,15 @@ START_RELOC_NUMBERS (elf_arm_reloc_type)
   RELOC_NUMBER (R_ARM_TARGET1,         38)
   RELOC_NUMBER (R_ARM_ROSEGREL32,      39)
   RELOC_NUMBER (R_ARM_V4BX,            40)
-  RELOC_NUMBER (R_ARM_STKCHK,          41)
-  RELOC_NUMBER (R_ARM_THM_STKCHK,      42)
+  RELOC_NUMBER (R_ARM_TARGET2,	       41)
+  RELOC_NUMBER (R_ARM_PREL31,	       42)
   FAKE_RELOC   (FIRST_INVALID_RELOC2,  43)
-  FAKE_RELOC   (LAST_INVALID_RELOC2,   99)
+  FAKE_RELOC   (LAST_INVALID_RELOC2,   94)
+  RELOC_NUMBER (R_ARM_GOT_ABS,	       95)
+  RELOC_NUMBER (R_ARM_GOT_PREL,	       96)
+  RELOC_NUMBER (R_ARM_GOT_BREL12,      97)
+  RELOC_NUMBER (R_ARM_GOTOFF12,	       98)
+  RELOC_NUMBER (R_ARM_GOTRELAX,	       99)
   RELOC_NUMBER (R_ARM_GNU_VTENTRY,    100)
   RELOC_NUMBER (R_ARM_GNU_VTINHERIT,  101)
   RELOC_NUMBER (R_ARM_THM_PC11,       102)   /* Cygnus extension to abi: Thumb unconditional branch.  */
Index: ld/ld.texinfo
===================================================================
RCS file: /cvs/src/src/ld/ld.texinfo,v
retrieving revision 1.120
diff -u -p -r1.120 ld.texinfo
--- ld/ld.texinfo	2 Aug 2004 20:03:41 -0000	1.120
+++ ld/ld.texinfo	17 Sep 2004 00:49:55 -0000
@@ -4877,7 +4877,7 @@ point to the function trampoline.
 @end ifset
 
 @node ARM
-@section @command{ld}'s Support for Interworking Between ARM and Thumb Code
+@section @command{ld} and the ARM family
 
 @cindex ARM interworking support
 @kindex --support-old-code
@@ -4907,6 +4907,26 @@ The @samp{--be8} switch instructs @comma
 executables.  This option is only valid when linking big-endian objects.
 The resulting image will contain big-endian data and little-endian code.
 
+@cindex TARGET1
+@kindex --target1-rel
+@kindex --target1-abs
+The @samp{R_ARM_TARGET1} relocation is typically used for entries in the
+@samp{.init_array} section.  It is interpreted as either @samp{R_ARM_REL32}
+or @samp{R_ARM_ABS32}, depending on the target.  The @samp{--target1-rel}
+and @samp{--target1-abs} switches override the default.
+
+@cindex TARGET2
+@kindex --target2=@var{type}
+The @samp{--target2=type} switch overrides the default definition of the
+@samp{R_ARM_TARGET2} relocation.  Valid values for @samp{type}, their
+meanings, and target defaults are as follows:
+@table @samp
+@item rel
+@samp{R_ARM_REL32} (arm*-*-symbianelf, arm*-*-elf, arm*-*-eabi)
+@item got-rel
+@samp{R_ARM_GOT_PREL} (arm*-*-linux, arm*-*-*bsd)
+@end table
+
 @ifclear GENERIC
 @lowersections
 @end ifclear
Index: ld/emulparams/armelf_fbsd.sh
===================================================================
RCS file: /cvs/src/src/ld/emulparams/armelf_fbsd.sh,v
retrieving revision 1.1
diff -u -p -r1.1 armelf_fbsd.sh
--- ld/emulparams/armelf_fbsd.sh	18 Feb 2002 09:38:01 -0000	1.1
+++ ld/emulparams/armelf_fbsd.sh	17 Sep 2004 00:49:55 -0000
@@ -1,2 +1,3 @@
 . ${srcdir}/emulparams/armelf.sh
 . ${srcdir}/emulparams/elf_fbsd.sh
+TARGET2_TYPE=got-rel
Index: ld/emulparams/armelf_linux.sh
===================================================================
RCS file: /cvs/src/src/ld/emulparams/armelf_linux.sh,v
retrieving revision 1.11
diff -u -p -r1.11 armelf_linux.sh
--- ld/emulparams/armelf_linux.sh	9 Feb 2004 18:06:20 -0000	1.11
+++ ld/emulparams/armelf_linux.sh	17 Sep 2004 00:49:55 -0000
@@ -16,6 +16,7 @@ OTHER_BSS_END_SYMBOLS='_bss_end__ = . ; 
 OTHER_SECTIONS='.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }'
 
 TEXT_START_ADDR=0x00008000
+TARGET2_TYPE=got-rel
 
 # ARM does not support .s* sections.
 NO_SMALL_DATA=yes
Index: ld/emulparams/armelf_nbsd.sh
===================================================================
RCS file: /cvs/src/src/ld/emulparams/armelf_nbsd.sh,v
retrieving revision 1.1
diff -u -p -r1.1 armelf_nbsd.sh
--- ld/emulparams/armelf_nbsd.sh	20 Dec 2001 03:19:43 -0000	1.1
+++ ld/emulparams/armelf_nbsd.sh	17 Sep 2004 00:49:55 -0000
@@ -1,6 +1,7 @@
 . ${srcdir}/emulparams/armelf.sh
 MAXPAGESIZE=0x8000
 TEXT_START_ADDR=0x00008000
+TARGET2_TYPE=got-rel
 
 unset STACK_ADDR
 unset EMBEDDED
Index: ld/emultempl/armelf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/armelf.em,v
retrieving revision 1.39
diff -u -p -r1.39 armelf.em
--- ld/emultempl/armelf.em	13 Sep 2004 14:14:32 -0000	1.39
+++ ld/emultempl/armelf.em	17 Sep 2004 00:49:55 -0000
@@ -22,6 +22,7 @@
 # This file is sourced from elf32.em, and defines extra arm-elf
 # specific routines.
 #
+test -z $TARGET2_TYPE && TARGET2_TYPE="rel"
 cat >>e${EMULATION_NAME}.c <<EOF
 
 static int no_pipeline_knowledge = 0;
@@ -29,6 +30,7 @@ static char *thumb_entry_symbol = NULL;
 static bfd *bfd_for_interwork;
 static int byteswap_code = 0;
 static int target1_is_rel = 0${TARGET1_IS_REL};
+static char *target2_type = "${TARGET2_TYPE}";
 
 static void
 gld${EMULATION_NAME}_before_parse (void)
@@ -121,8 +123,7 @@ arm_elf_before_allocation (void)
       {
 	if (!bfd_elf32_arm_process_before_allocation (is->the_bfd, & link_info,
 						      no_pipeline_knowledge,
-						      byteswap_code,
-						      target1_is_rel))
+						      byteswap_code))
 	  {
 	    /* xgettext:c-format */
 	    einfo (_("Errors encountered processing file %s"), is->filename);
@@ -182,6 +183,14 @@ arm_elf_finish (void)
 	   thumb_entry_symbol);
 }
 
+/* This is a convenitent point to tell BFD about target specific flags.
+   After the output has been created, but before inputs are read.  */
+static void
+arm_elf_create_output_section_statements (void)
+{
+  bfd_elf32_arm_set_target_relocs (&link_info, target1_is_rel, target2_type);
+}
+
 EOF
 
 # Define some shell vars to insert bits of code into the standard elf
@@ -192,6 +201,7 @@ PARSE_AND_LIST_PROLOGUE='
 #define OPTION_BE8			302
 #define OPTION_TARGET1_REL		303
 #define OPTION_TARGET1_ABS		304
+#define OPTION_TARGET2			305
 '
 
 PARSE_AND_LIST_SHORTOPTS=p
@@ -202,14 +212,16 @@ PARSE_AND_LIST_LONGOPTS='
   { "be8", no_argument, NULL, OPTION_BE8},
   { "target1-rel", no_argument, NULL, OPTION_TARGET1_REL},
   { "target1-abs", no_argument, NULL, OPTION_TARGET1_ABS},
+  { "target2", required_argument, NULL, OPTION_TARGET2},
 '
 
 PARSE_AND_LIST_OPTIONS='
   fprintf (file, _("  -p --no-pipeline-knowledge  Stop the linker knowing about the pipeline length\n"));
   fprintf (file, _("     --thumb-entry=<sym>      Set the entry point to be Thumb symbol <sym>\n"));
   fprintf (file, _("     --be8                    Oputput BE8 format image\n"));
-  fprintf (file, _("     --target1-rel            Interpret R_ARM_TARGET1 as R_ARM_REL32\n"));
-  fprintf (file, _("     --target1-abs            Interpret R_ARM_TARGET1 as R_ARM_ABS32\n"));
+  fprintf (file, _("     --target1=rel            Interpret R_ARM_TARGET1 as R_ARM_REL32\n"));
+  fprintf (file, _("     --target1=abs            Interpret R_ARM_TARGET1 as R_ARM_ABS32\n"));
+  fprintf (file, _("     --target2=<type>         Specify definition of R_ARM_TARGET2\n"));
 '
 
 PARSE_AND_LIST_ARGS_CASES='
@@ -232,12 +244,17 @@ PARSE_AND_LIST_ARGS_CASES='
     case OPTION_TARGET1_ABS:
       target1_is_rel = 0;
       break;
+
+    case OPTION_TARGET2:
+      target2_type = optarg;
+      break;
 '
 
 # We have our own after_open and before_allocation functions, but they call
 # the standard routines, so give them a different name.
 LDEMUL_AFTER_OPEN=arm_elf_after_open
 LDEMUL_BEFORE_ALLOCATION=arm_elf_before_allocation
+LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=arm_elf_create_output_section_statements
 
 # Replace the elf before_parse function with our own.
 LDEMUL_BEFORE_PARSE=gld"${EMULATION_NAME}"_before_parse
Index: ld/emultempl/armelf_oabi.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/armelf_oabi.em,v
retrieving revision 1.16
diff -u -p -r1.16 armelf_oabi.em
--- ld/emultempl/armelf_oabi.em	16 Sep 2004 12:49:56 -0000	1.16
+++ ld/emultempl/armelf_oabi.em	17 Sep 2004 00:49:55 -0000
@@ -69,7 +69,7 @@ gld${EMULATION_NAME}_before_allocation (
     LANG_FOR_EACH_INPUT_STATEMENT (is)
       {
 	if (!bfd_elf32_arm_process_before_allocation (is->the_bfd, &link_info,
-						      0, 0, 0))
+						      0, 0))
 	  {
 	    /* xgettext:c-format */
 	    einfo (_("Errors encountered processing file %s"), is->filename);
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.3
diff -u -p -r1.3 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp	23 Jan 2004 16:51:39 -0000	1.3
+++ ld/testsuite/ld-arm/arm-elf.exp	17 Sep 2004 00:49:55 -0000
@@ -47,6 +47,21 @@ set armelftests {
     {"Non-pcrel function reference" "tmpdir/arm-lib.so" "" {arm-app-abs32.s}
      {{objdump -fdw arm-app-abs32.d} {objdump -Rw arm-app-abs32.r}}
      "arm-app-abs32"}
+    {"target1-abs" "-static --target1-abs -T arm.ld" "" {arm-target1.s}
+     {{objdump -s arm-target1-abs.d}}
+     "arm-target1-abs"}
+    {"target1-rel" "-static --target1-rel -T arm.ld" "" {arm-target1.s}
+     {{objdump -s arm-target1-rel.d}}
+     "arm-target1-rel"}
+    {"target2-rel" "-static --target2=rel -T arm.ld" "" {arm-target2.s}
+     {{objdump -s arm-target2-rel.d}}
+     "arm-target2-rel"}
+    {"target2-got-rel" "-static --target2=got-rel -T arm.ld" "" {arm-target2.s}
+     {{objdump -s arm-target2-got-rel.d}}
+     "arm-target2-got-rel"}
+    {"arm-rel31" "-static -T arm.ld" "" {arm-rel31.s}
+     {{objdump -s arm-rel31.d}}
+     "arm-rel31"}
 }
 
 run_ld_link_tests $armelftests
Index: ld/testsuite/ld-arm/arm-rel31.d
===================================================================
RCS file: ld/testsuite/ld-arm/arm-rel31.d
diff -N ld/testsuite/ld-arm/arm-rel31.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/arm-rel31.d	17 Sep 2004 00:49:55 -0000
@@ -0,0 +1,5 @@
+
+.*:     file format.*
+
+Contents of section .text:
+ 8000 (10000000 fcffff7f 08000080 f4ffffff|00000010 7ffffffc 80000008 fffffff4) .*
Index: ld/testsuite/ld-arm/arm-rel31.s
===================================================================
RCS file: ld/testsuite/ld-arm/arm-rel31.s
diff -N ld/testsuite/ld-arm/arm-rel31.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/arm-rel31.s	17 Sep 2004 00:49:55 -0000
@@ -0,0 +1,11 @@
+# Test the R_ARM_REL31 relocation
+	.section .before
+	.global _start
+_start:
+	.text
+	.rel31 0, foo
+	.rel31 0, _start
+	.rel31 1, foo
+	.rel31 1, _start
+	.section .after
+foo:
Index: ld/testsuite/ld-arm/arm-target1-abs.d
===================================================================
RCS file: ld/testsuite/ld-arm/arm-target1-abs.d
diff -N ld/testsuite/ld-arm/arm-target1-abs.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/arm-target1-abs.d	17 Sep 2004 00:49:55 -0000
@@ -0,0 +1,5 @@
+
+.*:     file format.*
+
+Contents of section .text:
+ 8000 (04800000|00008004) .*
Index: ld/testsuite/ld-arm/arm-target1-rel.d
===================================================================
RCS file: ld/testsuite/ld-arm/arm-target1-rel.d
diff -N ld/testsuite/ld-arm/arm-target1-rel.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/arm-target1-rel.d	17 Sep 2004 00:49:55 -0000
@@ -0,0 +1,5 @@
+
+.*:     file format .*
+
+Contents of section .text:
+ 8000 (04000000|00000004) .*
Index: ld/testsuite/ld-arm/arm-target1.s
===================================================================
RCS file: ld/testsuite/ld-arm/arm-target1.s
diff -N ld/testsuite/ld-arm/arm-target1.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/arm-target1.s	17 Sep 2004 00:49:55 -0000
@@ -0,0 +1,6 @@
+# Test the R_ARM_TARGET1 relocation
+	.text
+	.global _start
+_start:
+	.word foo(target1)
+foo:
Index: ld/testsuite/ld-arm/arm-target2-got-rel.d
===================================================================
RCS file: ld/testsuite/ld-arm/arm-target2-got-rel.d
diff -N ld/testsuite/ld-arm/arm-target2-got-rel.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/arm-target2-got-rel.d	17 Sep 2004 00:49:55 -0000
@@ -0,0 +1,7 @@
+
+.*:     file format.*
+
+Contents of section .text:
+ 8000 (00100000|00001000) .*
+Contents of section .got:
+ 9000 (04800000|00008004) .*
Index: ld/testsuite/ld-arm/arm-target2-rel.d
===================================================================
RCS file: ld/testsuite/ld-arm/arm-target2-rel.d
diff -N ld/testsuite/ld-arm/arm-target2-rel.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/arm-target2-rel.d	17 Sep 2004 00:49:55 -0000
@@ -0,0 +1,5 @@
+
+.*:     file format.*
+
+Contents of section .text:
+ 8000 (04000000|00000004) .*
Index: ld/testsuite/ld-arm/arm-target2.s
===================================================================
RCS file: ld/testsuite/ld-arm/arm-target2.s
diff -N ld/testsuite/ld-arm/arm-target2.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/arm-target2.s	17 Sep 2004 00:49:55 -0000
@@ -0,0 +1,6 @@
+# Test the R_ARM_TARGET2 relocation
+	.text
+	.global _start
+_start:
+	.word foo(target2)
+foo:
Index: ld/testsuite/ld-arm/arm.ld
===================================================================
RCS file: ld/testsuite/ld-arm/arm.ld
diff -N ld/testsuite/ld-arm/arm.ld
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/arm.ld	17 Sep 2004 00:49:55 -0000
@@ -0,0 +1,16 @@
+/* Script for ld testsuite */
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = 0x8000); . = 0x8000;
+  .text           :
+  {
+    *(.before)
+    *(.text)
+    *(.after)
+  } =0
+  . = 0x9000;
+  .got            : { *(.got) *(.got.plt)}
+}

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