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]

Re: 2.15 branch merge


On Apr 12, 2004, Alan Modra <amodra@bigpond.net.au> wrote:

> On Sat, Apr 10, 2004 at 12:47:15AM -0300, Alexandre Oliva wrote:
>> I suppose I could create a new bfd arch used for object files that
>> have the EF_FRV_FDPIC bit set, but this would suck in terms of
>> duplication of code :-(

> grep will show you a number of other architectures that include
> elf32-target two or more times.  Doing that in elf32-frv.c, and making a
> few tweaks here and there should let you do what you want without much
> duplication.

Ah, yes!  Cool, I'd forgotten we could do that.  It's exactly what I
needed.

This big patch implements your suggestion.  While at that, I thought
I'd rename all FDPIC-specific identifiers to make it clear that
they're FDPIC-only, which made the patch huge.  I attach a separate,
smaller patch-lookalike that shows all non-mechanical changes
contained in the patch.  Having a separate BFD vector has enabled
several simplifications.

I also include a bug fix: when linking a shared library, we wouldn't
relocate contents of debugging sections properly.

I also noticed that the non-PCREL exception handling patch is missing
from the 2.15 branch.  This means FDPIC is pretty much broken, at
least for C++, so there's little point in even trying to fix it in the
branch.  I attach a patch for the branch anyway, after the patch for
mainline.  They're equivalent except for the changes to the EH-related
functions that didn't exist in the branch.

I adjusted the testsuite to accept both bfd vector names, such that
they'd pass in both frv-elf and frv-uclinux.  The latter defaults to
-mfdpic in the assembler now; previously, the linker used the
elf32frvfd emulation but object files assembled directly from source
didn't get the FDPIC bit set, which could be confusing.

No regressions in mainline or branch, both frv-elf and frv-uclinux
tested, the former with --enable-targets=all.

Is the first bzip2ed attachment ok for mainline?  Is the second ok for
the branch?

--- bfd/elf32-frv.c
+++ bfd/elf32-frv.c
@@ -1,5 +1,5 @@
 /* FRV-specific support for 32-bit ELF.
-   Copyright 2002, 2003 Free Software Foundation, Inc.
+   Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -583,6 +583,8 @@ static const struct frv_reloc_map frv_re
 };
 #endif
 
+extern const bfd_target bfd_elf32_frv_vec;
+#define IS_FDPIC(bfd) ((bfd)->xvec == &bfd_elf32_frv_vec)
 
 /* An extension of the elf hash table data structure, containing some
    additional FRV-specific data.  */
@@ -1871,19 +1897,19 @@ elf32_frv_relocate_section (output_bfd, 
 
   isec_segment = _frv_osec_to_segment (output_bfd,
 				       input_section->output_section);
-  if (frv_got_section (info))
+  if (IS_FDPIC (output_bfd) && frv_got_section (info))
     got_segment = _frv_osec_to_segment (output_bfd,
 					frv_got_section (info)
 					->output_section);
   else
     got_segment = -1;
-  if (frv_gotfixup_section (info))
+  if (IS_FDPIC (output_bfd) && frv_gotfixup_section (info))
     gprel_segment = _frv_osec_to_segment (output_bfd,
 					  frv_gotfixup_section (info)
 					  ->output_section);
   else
     gprel_segment = -1;
-  if (elf_hash_table (info)->dynamic_sections_created)
+  if (IS_FDPIC (output_bfd) && elf_hash_table (info)->dynamic_sections_created)
     plt_segment = _frv_osec_to_segment (output_bfd,
 					frv_plt_section (info)
 					->output_section);
@@ -1977,6 +2003,9 @@ elf32_frv_relocate_section (output_bfd, 
 	{
 	case R_FRV_LABEL24:
 	case R_FRV_32:
+	  if (! IS_FDPIC (output_bfd))
+	    goto non_fdpic;
+
 	case R_FRV_GOT12:
 	case R_FRV_GOTHI:
 	case R_FRV_GOTLO:
 	    return FALSE;
 
 	  if (!_frv_emit_got_relocs_plt_entries (picrel, output_bfd, info,
-						 osec, sym, rel->r_addend))
+						      osec, sym,
+						      rel->r_addend))
 	    {
-	      info->callbacks->warning
-		(info, _("Dynamic relocation references symbol with nonzero addend"),
-		 name, input_bfd, input_section, rel->r_offset);
+	      (*_bfd_error_handler)
+		(_("%s: relocation at `%s+0x%x' references symbol `%s' with nonzero addend"),
+		 bfd_archive_filename (input_bfd), input_section->name,
+		 rel->r_offset, name);
 	      return FALSE;
 
 	    }
@@ -2018,6 +2049,7 @@ elf32_frv_relocate_section (output_bfd, 
 	  break;
 
 	default:
+	non_fdpic:
 	  picrel = NULL;
 	  if (h && ! FRV_SYM_LOCAL (info, h))
 	    {
@@ -2033,7 +2065,9 @@ elf32_frv_relocate_section (output_bfd, 
 	{
 	case R_FRV_LABEL24:
 	  check_segment[0] = isec_segment;
-	  if (picrel->plt)
+	  if (! IS_FDPIC (output_bfd))
+	    check_segment[1] = isec_segment;
+	  else if (picrel->plt)
 	    {
 	      relocation = frv_plt_section (info)->output_section->vma
 		+ frv_plt_section (info)->output_offset
@@ -2181,14 +2219,18 @@ elf32_frv_relocate_section (output_bfd, 
 					+ input_section->output_offset,
 					r_type, dynindx, addend, picrel);
 		  }
+		else
+		  addend += frv_got_section (info)->output_section->vma;
 	      }
 
 	    /* We want the addend in-place because dynamic
@@ -2200,6 +2242,12 @@ elf32_frv_relocate_section (output_bfd, 
 	  break;
 
 	case R_FRV_32:
+	  if (! IS_FDPIC (output_bfd))
+	    {
+	      check_segment[0] = check_segment[1] = -1;
+	      break;
+	    }
+	  /* Fall through.  */
 	case R_FRV_FUNCDESC_VALUE:
 	  {
 	    int dynindx;
@@ -2239,7 +2291,7 @@ elf32_frv_relocate_section (output_bfd, 
 	      {
 		if (osec)
 		  addend += osec->output_section->vma;
-		if ((elf_elfheader (input_bfd)->e_flags & EF_FRV_FDPIC)
+		if (IS_FDPIC (input_bfd)
 		    && (bfd_get_section_flags (output_bfd,
 					       input_section->output_section)
 			& (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
@@ -2294,14 +2346,18 @@ elf32_frv_relocate_section (output_bfd, 
 					+ input_section->output_offset,
 					r_type, dynindx, addend, picrel);
 		  }
+		else if (osec)
+		  addend += osec->output_section->vma;
 		/* We want the addend in-place because dynamic
 		   relocations are REL.  Setting relocation to it
 		   should arrange for it to be installed.  */
@@ -2357,10 +2414,10 @@ elf32_frv_relocate_section (output_bfd, 
 	  break;
 	}
 
-      if (check_segment[0] != check_segment[1]
-	  && (elf_elfheader (output_bfd)->e_flags & EF_FRV_FDPIC))
+      if (check_segment[0] != check_segment[1] && IS_FDPIC (output_bfd))
 	{
-#if 1
+#if 1 /* If you take this out, remove the #error from fdpic-static-6.d
+	 in the ld testsuite.  */
 	  /* This helps catch problems in GCC while we can't do more
 	     than static linking.  The idea is to test whether the
 	     input file basename is crt0.o only once.  */
@@ -2417,7 +2474,7 @@ elf32_frv_relocate_section (output_bfd, 
       switch (r_type)
 	{
 	case R_FRV_LABEL24:
-	  if (! picrel->plt)
+	  if (! IS_FDPIC (output_bfd) || ! picrel->plt)
 	    break;
 	  /* Fall through.  */
 	  
@@ -2614,6 +2671,7 @@ elf32_frv_add_symbol_hook (abfd, info, s
 
   return TRUE;
 }
+
 /* Create a .got section, as well as its additional info field.  This
    is almost entirely copied from
    elflink.c:_bfd_elf_create_got_section().  */
@@ -2627,6 +2685,7 @@ _frv_create_got_section (bfd *abfd, stru
   struct bfd_link_hash_entry *bh;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   int ptralign;
+  int offset;
 
   /* This function may be called more than once.  */
   s = bfd_get_section_by_name (abfd, ".got");
@@ -2686,6 +2745,8 @@ _frv_create_got_section (bfd *abfd, stru
 
   /* This is the machine-specific part.  Create and initialize section
      data for the got.  */
+  if (IS_FDPIC (abfd))
+    {
   frv_got_section (info) = s;
   frv_relocs_info (info) = htab_try_create (1, frv_pic_relocs_info_hash,
 					    frv_pic_relocs_info_eq,
@@ -2709,13 +2770,21 @@ _frv_create_got_section (bfd *abfd, stru
     return FALSE;
 
   frv_gotfixup_section (info) = s;
+      offset = -2048;
+      flags = BSF_GLOBAL;
+    }
+  else
+    {
+      offset = 2048;
+      flags = BSF_GLOBAL | BSF_WEAK;
+    }
 
-  /* Define _gp in .rofixup, for FDPIC.  If it turns out that
-     we're linking with a different linker script, the linker script
-     will override it.  */
+  /* Define _gp in .rofixup, for FDPIC, or .got otherwise.  If it
+     turns out that we're linking with a different linker script, the
+     linker script will override it.  */
   bh = NULL;
   if (!(_bfd_generic_link_add_one_symbol
-	(info, abfd, "_gp", BSF_GLOBAL, s, -2048, (const char *) NULL, FALSE,
+	(info, abfd, "_gp", flags, s, offset, (const char *) NULL, FALSE,
 	 bed->collect, &bh)))
     return FALSE;
   h = (struct elf_link_hash_entry *) bh;
@@ -2723,7 +2792,7 @@ _frv_create_got_section (bfd *abfd, stru
   h->type = STT_OBJECT;
 
   /* Machine-specific: we want the symbol for executables as well.  */
-  if (! _bfd_elf_link_record_dynamic_symbol (info, h))
+  if (IS_FDPIC (abfd) && ! _bfd_elf_link_record_dynamic_symbol (info, h))
     return FALSE;
   
   return TRUE;
@@ -3454,8 +3534,7 @@ elf32_frvfdpic_size_dynamic_sections (bf
 	return FALSE;
     }
 
-  if (elf_elfheader (output_bfd)->e_flags & EF_FRV_FDPIC)
-    frvfdpic_gotfixup_section (info)->_raw_size = (gpinfo.g.fixups + 1) * 4;
+  frvfdpic_gotfixup_section (info)->_raw_size = (gpinfo.g.fixups + 1) * 4;
   if (frvfdpic_gotfixup_section (info)->_raw_size == 0)
     frvfdpic_gotfixup_section (info)->flags |= SEC_EXCLUDE;
   else
@@ -3559,8 +3639,7 @@ static bfd_boolean
 elf32_frv_always_size_sections (bfd *output_bfd,
 				struct bfd_link_info *info)
 {
-  if (!info->relocatable
-      && elf_elfheader (output_bfd)->e_flags & EF_FRV_FDPIC)
+  if (!info->relocatable)
     {
       struct elf_link_hash_entry *h;
       asection *sec;
@@ -3605,8 +3684,6 @@ static bfd_boolean
 elf32_frv_modify_segment_map (bfd *output_bfd,
 			      struct bfd_link_info *info)
 {
-  if (elf_elfheader (output_bfd)->e_flags & EF_FRV_FDPIC)
-    {
       struct elf_segment_map *m;
 
       for (m = elf_tdata (output_bfd)->segment_map; m != NULL; m = m->next)
@@ -3642,7 +3719,6 @@ elf32_frv_modify_segment_map (bfd *outpu
 	      m->count++;
 	    }
 	}
-    }
 
   return TRUE;
 }
@@ -3650,6 +3726,14 @@ elf32_frv_modify_segment_map (bfd *outpu
 /* Fill in code and data in dynamic sections.  */
 
 static bfd_boolean
+elf32_frv_finish_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+				   struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+  /* Nothing to be done for non-FDPIC.  */
+  return TRUE;
+}
+
+static bfd_boolean
 elf32_frv_finish_dynamic_sections (bfd *output_bfd,
 				   struct bfd_link_info *info)
 {
@@ -3666,8 +3750,6 @@ elf32_frv_finish_dynamic_sections (bfd *
 
       if (frv_gotfixup_section (info))
 	{
-	  if (elf_elfheader (output_bfd)->e_flags & EF_FRV_FDPIC)
-	    {
 	      struct elf_link_hash_entry *hgot = elf_hash_table (info)->hgot;
 	      bfd_vma got_value = hgot->root.u.def.value
 		+ hgot->root.u.def.section->output_section->vma
@@ -3675,29 +3757,14 @@ elf32_frv_finish_dynamic_sections (bfd *
 
 	      _frv_add_rofixup (output_bfd, frv_gotfixup_section (info),
 				got_value, 0);
-	    }
 
 	  if (frv_gotfixup_section (info)->_raw_size
 	      != (frv_gotfixup_section (info)->reloc_count * 4))
 	    {
-	      if (frv_gotfixup_section (info)->_raw_size
-		  < frv_gotfixup_section (info)->reloc_count * 4)
-		{
-		  info->callbacks->warning
-		    (info, "LINKER BUG: .rofixup section size mismatch",
-		     ".rofixup", NULL, NULL, 0);
-		  abort ();
-		  return FALSE;
-		}
-	      else if (!elf_hash_table (info)->dynamic_sections_created)
-		{
-		  info->callbacks->warning
-		    (info, "no dynamic sections, missing -melf32frvfd?",
-		     ".rofixup", NULL, NULL, 0);
+	      (*_bfd_error_handler)
+		("LINKER BUG: .rofixup section size mismatch");
 		  return FALSE;
 		}
-	      BFD_ASSERT (0);
-	    }
 	}
     }
   if (elf_hash_table (info)->dynamic_sections_created)
@@ -3807,14 +3877,11 @@ frv_elf_use_relative_eh_frame
 			       asection *eh_frame_section ATTRIBUTE_UNUSED)
 {
   /* We can't use PC-relative encodings in FDPIC binaries, in general.  */
-  if (elf_elfheader (input_bfd)->e_flags & EF_FRV_FDPIC)
-    return FALSE;
-
-  return TRUE;
+  return FALSE;
 }
 
@@ -3829,11 +3896,6 @@ frv_elf_encode_eh_address (bfd *abfd,
 {
   struct elf_link_hash_entry *h;
 
-  /* Non-FDPIC binaries can use PC-relative encodings.  */
-  if (! (elf_elfheader (abfd)->e_flags & EF_FRV_FDPIC))
-    return _bfd_elf_encode_eh_address (abfd, info, osec, offset,
-				       loc_sec, loc_offset, encoded);
-
   h = elf_hash_table (info)->hgot;
   BFD_ASSERT (h && h->root.type == bfd_link_hash_defined);
 
@@ -3996,8 +4058,6 @@ elf32_frv_check_relocs (abfd, info, sec,
 
       switch (ELF32_R_TYPE (rel->r_info))
 	{
-	case R_FRV_LABEL24:
-	case R_FRV_32:
 	case R_FRV_GOT12:
 	case R_FRV_GOTHI:
 	case R_FRV_GOTLO:
@@ -4012,12 +4072,26 @@ elf32_frv_check_relocs (abfd, info, sec,
 	case R_FRV_FUNCDESC_GOTOFFLO:
 	case R_FRV_FUNCDESC:
 	case R_FRV_FUNCDESC_VALUE:
+	  if (! IS_FDPIC (abfd))
+	    goto bad_reloc;
+	  /* Fall through.  */
+	case R_FRV_GPREL12:
+	case R_FRV_GPRELU12:
+	case R_FRV_GPRELHI:
+	case R_FRV_GPRELLO:
+	case R_FRV_LABEL24:
+	case R_FRV_32:
 	  if (! dynobj)
 	    {
 	      elf_hash_table (info)->dynobj = dynobj = abfd;
 	      if (! _frv_create_got_section (abfd, info))
 		return FALSE;
 	    }
+	  if (! IS_FDPIC (abfd))
+	    {
+	      picrel = NULL;
+	      break;
+	    }
 	  if (h != NULL)
 	    {
 	      if (h->dynindx == -1)
@@ -4051,6 +4125,7 @@ elf32_frv_check_relocs (abfd, info, sec,
       switch (ELF32_R_TYPE (rel->r_info))
         {
 	case R_FRV_LABEL24:
+	  if (IS_FDPIC (abfd))
 	  picrel->call = 1;
 	  break;
 		
@@ -4059,7 +4134,11 @@ elf32_frv_check_relocs (abfd, info, sec,
 	  if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
 	    picrel->relocs32--;
 	  /* Fall through.  */
+
 	case R_FRV_32:
+	  if (! IS_FDPIC (abfd))
+	    break;
+
 	  picrel->sym = 1;
 	  if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
 	    picrel->relocs32++;
@@ -4116,6 +4195,23 @@ elf32_frv_check_relocs (abfd, info, sec,
           if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
             return FALSE;
           break;
+
+	case R_FRV_LABEL16:
+	case R_FRV_LO16:
+	case R_FRV_HI16:
+	case R_FRV_GPREL12:
+	case R_FRV_GPRELU12:
+	case R_FRV_GPREL32:
+	case R_FRV_GPRELHI:
+	case R_FRV_GPRELLO:
+	  break;
+
+	default:
+	bad_reloc:
+	  (*_bfd_error_handler)
+	    (_("%s: unsupported relocation type %i"),
+	     bfd_archive_filename (abfd), ELF32_R_TYPE (rel->r_info));
+	  return FALSE;
         }
     }
 
@@ -4152,7 +4248,8 @@ elf32_frv_object_p (abfd)
      bfd *abfd;
 {
   bfd_default_set_arch_mach (abfd, bfd_arch_frv, elf32_frv_machine (abfd));
-  return TRUE;
+  return (((elf_elfheader (abfd)->e_flags & EF_FRV_FDPIC) != 0)
+	  == (IS_FDPIC (abfd)));
 }
 
 /* Function to set the ELF flag bits.  */
@@ -4460,6 +4557,20 @@ frv_elf_merge_private_bfd_data (ibfd, ob
   if (old_partial != (old_flags & EF_FRV_CPU_MASK))
     bfd_default_set_arch_mach (obfd, bfd_arch_frv, elf32_frv_machine (obfd));
 
+  if (((new_flags & EF_FRV_FDPIC) == 0)
+      != (! IS_FDPIC (ibfd)))
+    {
+      error = TRUE;
+      if (IS_FDPIC (obfd))
+	(*_bfd_error_handler)
+	  (_("%s: cannot link non-fdpic object file into fdpic executable"),
+	   bfd_get_filename (ibfd));
+      else
+	(*_bfd_error_handler)
+	  (_("%s: cannot link fdpic object file into non-fdpic executable"),
+	   bfd_get_filename (ibfd));
+    }
+
   if (error)
     bfd_set_error (bfd_error_bad_value);
 
@@ -4557,7 +4668,6 @@ frv_elf_print_private_bfd_data (abfd, pt
 #define TARGET_BIG_SYM          bfd_elf32_frv_vec
 #define TARGET_BIG_NAME		"elf32-frv"
 
-#define elf_info_to_howto_rel			frv_info_to_howto_rel
 #define elf_info_to_howto			frv_info_to_howto_rela
 #define elf_backend_relocate_section		elf32_frv_relocate_section
 #define elf_backend_gc_mark_hook		elf32_frv_gc_mark_hook
@@ -4575,39 +4685,73 @@ frv_elf_print_private_bfd_data (abfd, pt
 #define bfd_elf32_bfd_merge_private_bfd_data	frv_elf_merge_private_bfd_data
 #define bfd_elf32_bfd_print_private_bfd_data	frv_elf_print_private_bfd_data
 
-#define bfd_elf32_bfd_link_hash_table_create  frv_elf_link_hash_table_create
+#define elf_backend_want_got_sym	1
+#define elf_backend_got_header_size	0
+#define elf_backend_want_got_plt	0
+#define elf_backend_plt_readonly	1
+#define elf_backend_want_plt_sym	0
+#define elf_backend_plt_header_size	0
+
+#define elf_backend_finish_dynamic_sections \
+		elf32_frv_finish_dynamic_sections
+
+#include "elf32-target.h"
+
+#undef ELF_MAXPAGESIZE
+#define ELF_MAXPAGESIZE		0x4000
+
+#undef TARGET_BIG_SYM
+#define TARGET_BIG_SYM          bfd_elf32_frv_vec
+#undef TARGET_BIG_NAME
+#define TARGET_BIG_NAME		"elf32-frv"
+#undef	elf32_bed
+#define	elf32_bed		elf32_frv_bed
+
+#undef elf_info_to_howto_rel
+#define elf_info_to_howto_rel	frv_info_to_howto_rel
+
+#undef bfd_elf32_bfd_link_hash_table_create
+#define bfd_elf32_bfd_link_hash_table_create \
+		frv_elf_link_hash_table_create
+#undef elf_backend_always_size_sections
 #define elf_backend_always_size_sections \
 		elf32_frv_always_size_sections
+#undef elf_backend_modify_segment_map
 #define elf_backend_modify_segment_map \
 		elf32_frv_modify_segment_map
 
+#undef elf_backend_create_dynamic_sections
 #define elf_backend_create_dynamic_sections \
 		elf32_frv_create_dynamic_sections
+#undef elf_backend_adjust_dynamic_symbol
 #define elf_backend_adjust_dynamic_symbol \
 		elf32_frv_adjust_dynamic_symbol
+#undef elf_backend_size_dynamic_sections
 #define elf_backend_size_dynamic_sections \
 		elf32_frv_size_dynamic_sections
+#undef elf_backend_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_symbol \
 		elf32_frv_finish_dynamic_symbol
+#undef elf_backend_finish_dynamic_sections
 #define elf_backend_finish_dynamic_sections \
 		elf32_frv_finish_dynamic_sections
 
-#define elf_backend_want_got_sym	1
-#define elf_backend_got_header_size	0
-#define elf_backend_want_got_plt	0
-#define elf_backend_plt_readonly	1
-#define elf_backend_want_plt_sym	0
-#define elf_backend_plt_header_size	0
-
+#undef elf_backend_can_make_relative_eh_frame
 #define elf_backend_can_make_relative_eh_frame \
 		frv_elf_use_relative_eh_frame
+#undef elf_backend_can_make_lsda_relative_eh_frame
 #define elf_backend_can_make_lsda_relative_eh_frame \
 		frv_elf_use_relative_eh_frame
-#define elf_backend_encode_eh_address	frv_elf_encode_eh_address
+#undef elf_backend_encode_eh_address
+#define elf_backend_encode_eh_address \
+		frv_elf_encode_eh_address
 
+#undef elf_backend_may_use_rel_p
 #define elf_backend_may_use_rel_p       1
+#undef elf_backend_may_use_rela_p
 #define elf_backend_may_use_rela_p      1
 /* We use REL for dynamic relocations only.  */
+#undef elf_backend_default_use_rela_p
 #define elf_backend_default_use_rela_p  1
 
 #include "elf32-target.h"

Attachment: frvfdpic-bfdvec.patch.bz2
Description: BZip2 compressed data

Attachment: frvfdpic-bfdvec.patch.bz2
Description: BZip2 compressed data

-- 
Alexandre Oliva             http://www.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

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