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]

[PATCH] Fix IA-64 -pie support


Hi!

Current IA-64 ld cannot link even trivial -pie applications, such as
int main () { } - it gets some assertion failures and finally segfaults.
This patch attempts to fix it.

While working on this, I've noticed that assembling and linking into shlib
of the following
addl r2 = @ltoff(@fptr(foobar)), gp
addl r3 = @ltoff(foobar), gp
creates only one .got entry, as if both relocations were @ltoff(@fptr()).
Is that on purpose? IMHO either linker should emit an error in this case,
or it should create 2 .got entries.

This patch also fixes (not just on ia64, but other arches as well) emitting
undefined symbol errors in -pie. Before ld would silently create e.g. a
PIE which did not have main function defined, which of course would segfault
when run.

2003-07-02  Jakub Jelinek  <jakub@redhat.com>

bfd/
	* elfxx-ia64.c (struct elfNN_ia64_link_hash_table): Add rel_fptr_sec.
	(elfNN_ia64_dynamic_symbol_p): Change info->shared into
	!info->executable.
	(get_fptr): For -pie create .opd as writable section and create
	.rela.opd as well.
	(elfNN_ia64_check_relocs): Change info->shared into
	!info->executable.
	(allocate_fptr): Likewise.
	(allocate_dynrel_entries): Account for a relative reloc for -pie
	@fptr().  Don't account for a relative reloc if -pie want_ltoff_fptr
	for undefweak symbol.  Account for an IPLT reloc in .rela.opd
	section if -pie.
	(set_got_entry): Don't create a relative reloc if -pie
	want_ltoff_fptr for undefweak symbol.
	(set_fptr_entry): Emit an IPLT reloc in .rela.opd for -pie.
	(elfNN_ia64_relocate_section): Emit a relative reloc for -pie
	@fptr().

	* elfxx-ia64.c (elfNN_ia64_relocate_section): Issue undefined_symbol
	even if -pie.
	* elf32-i386.c (elf_i386_relocate_section): Likewise.
	* elf64-x86-64.c (elf64_x86_64_relocate_section): Likewise.
	* elf64-sparc.c (sparc64_elf_relocate_section): Likewise.
	* elf64-s390.c (elf_s390_relocate_section): Likewise.
	* elf64-ppc.c (ppc64_elf_relocate_section): Likewise.
	* elf64-alpha.c (elf64_alpha_relocate_section): Likewise.
	* elf32-sparc.c (elf32_sparc_relocate_section): Likewise.
	* elf32-s390.c (elf_s390_relocate_section): Likewise.
	* elf32-ppc.c (ppc_elf_relocate_section): Likewise.
ld/
	* emulparams/elf64_ia64.sh (OTHER_READONLY_SECTIONS): Don't include
	.opd if -pie.
	(OTHER_READWRITE_SECTIONS): Include .opd if -pie.
	* scripttempl/elf.sc: Use SHLIB_DATA_ADDR instead of DATA_ADDR
	if -pie.

--- bfd/elfxx-ia64.c.jj	2003-07-01 07:14:13.000000000 -0400
+++ bfd/elfxx-ia64.c	2003-07-02 08:04:08.000000000 -0400
@@ -143,6 +143,7 @@ struct elfNN_ia64_link_hash_table
   asection *got_sec;		/* the linkage table section (or NULL) */
   asection *rel_got_sec;	/* dynamic relocation section for same */
   asection *fptr_sec;		/* function descriptor table (or NULL) */
+  asection *rel_fptr_sec;	/* dynamic relocation section for same */
   asection *plt_sec;		/* the primary plt section (or NULL) */
   asection *pltoff_sec;		/* private descriptors for plt (or NULL) */
   asection *rel_pltoff_sec;	/* dynamic relocation section for same */
@@ -1652,7 +1653,7 @@ elfNN_ia64_dynamic_symbol_p (h, info)
       || h->root.type == bfd_link_hash_defweak)
     return TRUE;
 
-  if ((info->shared && (!info->symbolic || info->allow_shlib_undefined))
+  if ((!info->executable && (!info->symbolic || info->allow_shlib_undefined))
       || ((h->elf_link_hash_flags
 	   & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))
 	  == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)))
@@ -2063,7 +2064,7 @@ get_got (abfd, info, ia64_info)
 static asection *
 get_fptr (abfd, info, ia64_info)
      bfd *abfd;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+     struct bfd_link_info *info;
      struct elfNN_ia64_link_hash_table *ia64_info;
 {
   asection *fptr;
@@ -2083,7 +2084,7 @@ get_fptr (abfd, info, ia64_info)
 				      | SEC_LOAD
 				      | SEC_HAS_CONTENTS
 				      | SEC_IN_MEMORY
-				      | SEC_READONLY
+				      | (info->pie ? 0 : SEC_READONLY)
 				      | SEC_LINKER_CREATED))
 	  || !bfd_set_section_alignment (abfd, fptr, 4))
 	{
@@ -2092,6 +2093,26 @@ get_fptr (abfd, info, ia64_info)
 	}
 
       ia64_info->fptr_sec = fptr;
+
+      if (info->pie)
+	{
+	  asection *fptr_rel;
+	  fptr_rel = bfd_make_section(abfd, ".rela.opd");
+	  if (fptr_rel == NULL
+	      || !bfd_set_section_flags (abfd, fptr_rel,
+					 (SEC_ALLOC | SEC_LOAD
+					  | SEC_HAS_CONTENTS
+					  | SEC_IN_MEMORY
+					  | SEC_LINKER_CREATED
+					  | SEC_READONLY))
+	      || !bfd_set_section_alignment (abfd, fptr_rel, 3))
+	    {
+	      BFD_ASSERT (0);
+	      return NULL;
+	    }
+
+	  ia64_info->rel_fptr_sec = fptr_rel;
+	}
     }
 
   return fptr;
@@ -2278,7 +2299,7 @@ elfNN_ia64_check_relocs (abfd, info, sec
 	 have yet been processed.  Do something with what we know, as
 	 this may help reduce memory usage and processing time later.  */
       maybe_dynamic = FALSE;
-      if (h && ((info->shared
+      if (h && ((!info->executable
 		      && (!info->symbolic || info->allow_shlib_undefined))
 		|| ! (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
 		|| h->root.type == bfd_link_hash_defweak
@@ -2638,7 +2659,7 @@ allocate_fptr (dyn_i, data)
 	       || h->root.type == bfd_link_hash_warning)
 	  h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
-      if ((x->info->shared
+      if ((!x->info->executable
 	   && (!h
 	       || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
 	       || h->root.type != bfd_link_hash_undefweak))
@@ -2788,10 +2809,11 @@ allocate_dynrel_entries (dyn_i, data)
       switch (rent->type)
 	{
 	case R_IA64_FPTR64LSB:
-	  /* Allocate one iff !want_fptr, which by this point will
-	     be true only if we're actually allocating one statically
-	     in the main executable.  */
-	  if (dyn_i->want_fptr)
+	  /* Allocate one iff !want_fptr and not PIE, which by this point
+	     will be true only if we're actually allocating one statically
+	     in the main executable.  Position independent executables
+	     need a relative reloc.  */
+	  if (dyn_i->want_fptr && !x->info->pie)
 	    continue;
 	  break;
 	case R_IA64_PCREL64LSB:
@@ -2828,13 +2850,24 @@ allocate_dynrel_entries (dyn_i, data)
       || (dyn_i->want_ltoff_fptr
 	  && dyn_i->h
 	  && dyn_i->h->dynindx != -1))
-    ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
+    {
+      if (!dyn_i->want_ltoff_fptr
+	  || !x->info->pie
+	  || dyn_i->h == NULL
+	  || dyn_i->h->root.type != bfd_link_hash_undefweak)
+	ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
+    }
   if ((dynamic_symbol || shared) && dyn_i->want_tprel)
     ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
   if (dynamic_symbol && dyn_i->want_dtpmod)
     ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
   if (dynamic_symbol && dyn_i->want_dtprel)
     ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
+  if (ia64_info->rel_fptr_sec && dyn_i->want_fptr)
+    {
+      if (dyn_i->h == NULL || dyn_i->h->root.type != bfd_link_hash_undefweak)
+	ia64_info->rel_fptr_sec->_raw_size += sizeof (ElfNN_External_Rela);
+    }
 
   if (!resolved_zero && dyn_i->want_pltoff)
     {
@@ -3444,14 +3477,18 @@ set_got_entry (abfd, info, dyn_i, dynind
       bfd_put_64 (abfd, value, got_sec->contents + got_offset);
 
       /* Install a dynamic relocation if needed.  */
-      if ((info->shared
-	   && (!dyn_i->h
-	       || ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT
-	       || dyn_i->h->root.type != bfd_link_hash_undefweak)
-	   && dyn_r_type != R_IA64_DTPREL64LSB)
-          || elfNN_ia64_dynamic_symbol_p (dyn_i->h, info)
-	  || elfNN_ia64_aix_vec (abfd->xvec)
-	  || (dynindx != -1 && dyn_r_type == R_IA64_FPTR64LSB))
+      if (((info->shared
+	    && (!dyn_i->h
+		|| ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT
+		|| dyn_i->h->root.type != bfd_link_hash_undefweak)
+	    && dyn_r_type != R_IA64_DTPREL64LSB)
+           || elfNN_ia64_dynamic_symbol_p (dyn_i->h, info)
+	   || elfNN_ia64_aix_vec (abfd->xvec)
+	   || (dynindx != -1 && dyn_r_type == R_IA64_FPTR64LSB))
+	  && (!dyn_i->want_ltoff_fptr
+	      || !info->pie
+	      || !dyn_i->h
+	      || dyn_i->h->root.type != bfd_link_hash_undefweak))
 	{
 	  if (dynindx == -1
 	      && dyn_r_type != R_IA64_TPREL64LSB
@@ -3530,6 +3567,24 @@ set_fptr_entry (abfd, info, dyn_i, value
       bfd_put_64 (abfd, value, fptr_sec->contents + dyn_i->fptr_offset);
       bfd_put_64 (abfd, _bfd_get_gp_value (abfd),
 		  fptr_sec->contents + dyn_i->fptr_offset + 8);
+      if (ia64_info->rel_fptr_sec)
+	{
+	  Elf_Internal_Rela outrel;
+	  bfd_byte *loc;
+
+	  if (bfd_little_endian (abfd))
+	    outrel.r_info = ELFNN_R_INFO (0, R_IA64_IPLTLSB);
+	  else
+	    outrel.r_info = ELFNN_R_INFO (0, R_IA64_IPLTMSB);
+	  outrel.r_addend = value;
+	  outrel.r_offset = (fptr_sec->output_section->vma
+			     + fptr_sec->output_offset
+			     + dyn_i->fptr_offset);
+	  loc = ia64_info->rel_fptr_sec->contents;
+	  loc += ia64_info->rel_fptr_sec->reloc_count++
+		 * sizeof (ElfNN_External_Rela);
+	  bfd_elfNN_swap_reloca_out (abfd, &outrel, loc);
+	}
     }
 
   /* Return the descriptor's address.  */
@@ -3986,7 +4041,7 @@ elfNN_ia64_relocate_section (output_bfd,
 	    }
 	  else if (h->root.type == bfd_link_hash_undefweak)
 	    undef_weak_ref = TRUE;
-	  else if (info->shared
+	  else if (! info->executable
 		   && !info->no_undefined
 		   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
 	    ;
@@ -4146,14 +4201,36 @@ elfNN_ia64_relocate_section (output_bfd,
 	      if (!undef_weak_ref)
 		value = set_fptr_entry (output_bfd, info, dyn_i, value);
 	    }
-	  else
+	  if (!dyn_i->want_fptr || info->pie)
 	    {
 	      long dynindx;
+	      unsigned int dyn_r_type = r_type;
+	      bfd_vma addend = rel->r_addend;
 
 	      /* Otherwise, we expect the dynamic linker to create
 		 the entry.  */
 
-	      if (h)
+	      if (dyn_i->want_fptr)
+		{
+		  if (r_type == R_IA64_FPTR64I)
+		    {
+		      /* We can't represent this without a dynamic symbol.
+			 Adjust the relocation to be against an output
+			 section symbol, which are always present in the
+			 dynamic symbol table.  */
+		      /* ??? People shouldn't be doing non-pic code in
+			 shared libraries.  Hork.  */
+		      (*_bfd_error_handler)
+			(_("%s: linking non-pic code in a position independent executable"),
+			 bfd_archive_filename (input_bfd));
+		      ret_val = FALSE;
+		      continue;
+		    }
+		  dynindx = 0;
+		  addend = value;
+		  dyn_r_type = r_type + R_IA64_REL64LSB - R_IA64_FPTR64LSB;
+		}
+	      else if (h)
 		{
 		  if (h->dynindx != -1)
 		    dynindx = h->dynindx;
@@ -4161,17 +4238,18 @@ elfNN_ia64_relocate_section (output_bfd,
 		    dynindx = (_bfd_elf_link_lookup_local_dynindx
 			       (info, h->root.u.def.section->owner,
 				global_sym_index (h)));
+		  value = 0;
 		}
 	      else
 		{
 		  dynindx = (_bfd_elf_link_lookup_local_dynindx
 			     (info, input_bfd, (long) r_symndx));
+		  value = 0;
 		}
 
 	      elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
-					    srel, rel->r_offset, r_type,
-					    dynindx, rel->r_addend);
-	      value = 0;
+					    srel, rel->r_offset, dyn_r_type,
+					    dynindx, addend);
 	    }
 
 	  r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
--- bfd/elf32-i386.c.jj	2003-05-30 11:19:17.000000000 -0400
+++ bfd/elf32-i386.c	2003-07-02 08:04:34.000000000 -0400
@@ -2274,7 +2274,7 @@ elf_i386_relocate_section (output_bfd, i
 	    }
 	  else if (h->root.type == bfd_link_hash_undefweak)
 	    ;
-	  else if (info->shared
+	  else if (!info->executable
 		   && !info->no_undefined
 		   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
 	    ;
--- bfd/elf64-x86-64.c.jj	2003-05-30 11:19:17.000000000 -0400
+++ bfd/elf64-x86-64.c	2003-07-02 08:04:56.000000000 -0400
@@ -1947,7 +1947,7 @@ elf64_x86_64_relocate_section (output_bf
 	    }
 	  else if (h->root.type == bfd_link_hash_undefweak)
 	    relocation = 0;
-	  else if (info->shared
+	  else if (!info->executable
 		   && !info->no_undefined
 		   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
 	    relocation = 0;
--- bfd/elf64-sparc.c.jj	2003-05-30 11:19:17.000000000 -0400
+++ bfd/elf64-sparc.c	2003-07-02 08:05:13.000000000 -0400
@@ -2097,7 +2097,7 @@ sparc64_elf_relocate_section (output_bfd
 	    }
 	  else if (h->root.type == bfd_link_hash_undefweak)
 	    ;
-	  else if (info->shared
+	  else if (!info->executable
 		   && !info->no_undefined
 		   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
 	    ;
--- bfd/elf64-s390.c.jj	2003-05-30 11:19:17.000000000 -0400
+++ bfd/elf64-s390.c	2003-07-02 08:05:32.000000000 -0400
@@ -2244,7 +2244,7 @@ elf_s390_relocate_section (output_bfd, i
 	    }
 	  else if (h->root.type == bfd_link_hash_undefweak)
 	    relocation = 0;
-	  else if (info->shared
+	  else if (!info->executable
 		   && !info->no_undefined
 		   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
 	    relocation = 0;
--- bfd/elf64-ppc.c.jj	2003-06-18 08:39:36.000000000 -0400
+++ bfd/elf64-ppc.c	2003-07-02 08:05:48.000000000 -0400
@@ -7347,7 +7347,7 @@ ppc64_elf_relocate_section (output_bfd, 
 	    }
 	  else if (h->root.type == bfd_link_hash_undefweak)
 	    ;
-	  else if (info->shared
+	  else if (!info->executable
 		   && !info->no_undefined
 		   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
 	    ;
--- bfd/elf64-alpha.c.jj	2003-05-30 11:19:17.000000000 -0400
+++ bfd/elf64-alpha.c	2003-07-02 08:06:09.000000000 -0400
@@ -4504,7 +4504,7 @@ elf64_alpha_relocate_section (output_bfd
 	    }
 	  else if (h->root.root.type == bfd_link_hash_undefweak)
 	    undef_weak_ref = TRUE;
-	  else if (info->shared
+	  else if (!info->executable
 		   && !info->no_undefined
 		   && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
 	    ;
--- bfd/elf32-sparc.c.jj	2003-05-30 11:19:17.000000000 -0400
+++ bfd/elf32-sparc.c	2003-07-02 08:06:27.000000000 -0400
@@ -2206,7 +2206,7 @@ elf32_sparc_relocate_section (output_bfd
 	    }
 	  else if (h->root.type == bfd_link_hash_undefweak)
 	    ;
-	  else if (info->shared
+	  else if (!info->executable
 		   && !info->no_undefined
 		   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
 	    ;
--- bfd/elf32-s390.c.jj	2003-05-30 11:19:17.000000000 -0400
+++ bfd/elf32-s390.c	2003-07-02 08:06:56.000000000 -0400
@@ -2273,7 +2273,7 @@ elf_s390_relocate_section (output_bfd, i
 	    }
 	  else if (h->root.type == bfd_link_hash_undefweak)
 	    relocation = 0;
-	  else if (info->shared
+	  else if (!info->executable
 		   && !info->no_undefined
 		   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
 	    relocation = 0;
--- bfd/elf32-ppc.c.jj	2003-05-30 18:22:31.000000000 -0400
+++ bfd/elf32-ppc.c	2003-07-02 08:07:26.000000000 -0400
@@ -4387,7 +4387,7 @@ ppc_elf_relocate_section (output_bfd, in
 	    }
 	  else if (h->root.type == bfd_link_hash_undefweak)
 	    ;
-	  else if (info->shared
+	  else if (!info->executable
 		   && !info->no_undefined
 		   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
 	    ;
--- ld/emulparams/elf64_ia64.sh.jj	2003-05-30 11:19:17.000000000 -0400
+++ ld/emulparams/elf64_ia64.sh	2003-07-01 14:16:16.000000000 -0400
@@ -22,7 +22,12 @@ OTHER_GOT_SECTIONS="
   .IA_64.pltoff ${RELOCATING-0} : { *(.IA_64.pltoff) }"
 OTHER_PLT_RELOC_SECTIONS="
   .rela.IA_64.pltoff ${RELOCATING-0} : { *(.rela.IA_64.pltoff) }"
-OTHER_READONLY_SECTIONS="
-  .opd          ${RELOCATING-0} : { *(.opd) }
+OTHER_READONLY_SECTIONS=
+OTHER_READWRITE_SECTIONS=
+test -z "$CREATE_PIE" && OTHER_READONLY_SECTIONS="
+  .opd          ${RELOCATING-0} : { *(.opd) }"
+test -n "$CREATE_PIE" && OTHER_READWRITE_SECTIONS="
+  .opd          ${RELOCATING-0} : { *(.opd) }"
+OTHER_READONLY_SECTIONS="${OTHER_READONLY_SECTIONS}
   .IA_64.unwind_info ${RELOCATING-0} : { *(.IA_64.unwind_info${RELOCATING+* .gnu.linkonce.ia64unwi.*}) }
   .IA_64.unwind ${RELOCATING-0} : { *(.IA_64.unwind${RELOCATING+* .gnu.linkonce.ia64unw.*}) }"
--- ld/scripttempl/elf.sc.jj	2003-06-03 18:25:09.000000000 -0400
+++ ld/scripttempl/elf.sc	2003-07-01 12:17:12.000000000 -0400
@@ -72,8 +72,8 @@ if [ -z "$MACHINE" ]; then OUTPUT_ARCH=$
 test -z "${ELFSIZE}" && ELFSIZE=32
 test -z "${ALIGNMENT}" && ALIGNMENT="${ELFSIZE} / 8"
 test "$LD_FLAG" = "N" && DATA_ADDR=.
-test -n "$CREATE_SHLIB" && test -n "$SHLIB_DATA_ADDR" && COMMONPAGESIZE=""
-test -z "$CREATE_SHLIB" && test -n "$DATA_ADDR" && COMMONPAGESIZE=""
+test -n "$CREATE_SHLIB$CREATE_PIE" && test -n "$SHLIB_DATA_ADDR" && COMMONPAGESIZE=""
+test -z "$CREATE_SHLIB$CREATE_PIE" && test -n "$DATA_ADDR" && COMMONPAGESIZE=""
 DATA_SEGMENT_ALIGN="ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} - 1))"
 DATA_SEGMENT_END=""
 if test -n "${COMMONPAGESIZE}"; then
@@ -285,8 +285,9 @@ cat <<EOF
 
   /* Adjust the address for the data segment.  We want to adjust up to
      the same address within the page on the next page up.  */
-  ${CREATE_SHLIB-${RELOCATING+. = ${DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}
+  ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+. = ${DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}}
   ${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}
+  ${CREATE_PIE+${RELOCATING+. = ${SHLIB_DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}
 
   /* Ensure the __preinit_array_start label is properly aligned.  We
      could instead move the label definition inside the section, but

	Jakub


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