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]

better detection of old powerpc bss-plt objects


This patch fixes an irritating feature of the powerpc linker in that
secure-plt is only available on detecting relocs generated by a newer
gcc with -fpic or -fPIC.  This isn't a big deal since secure-plt is
aimed squarely at people who will be using pie executables, however,
there is no real reason a non-pic executable should be forced into
using the old bss-plt.

I also improve the detection of old object files by requiring REL16
relocs to appear in the same object file as PLTREL24 rather than just
somewhere in the input.  This should help in cases where people mix
old-style object files that make PLT calls but don't happen to use the
GOT, with new style libraries or other object files.  Without an
old-style GOT pointer code sequence the linker wouldn't force
bss-plt, and the new plt call stubs would segfault since they require
a GOT pointer.

bfd/
	* elf32-ppc.h (ppc_elf_select_plt_layout): Update prototype.
	(enum ppc_elf_plt_type): Move from..
	* elf32-ppc.c: ..here.
	(struct ppc_elf_obj_tdata): Add makes_plt_call and has_rel16.
	(struct ppc_elf_link_hash_table): Reorder.  Add old_bfd.  Delete
	can_use_new_plt.  Make is_vxworks a bitfield.
	(ppc_elf_link_hash_table_create): Don't clear is_vxworks (again).
	(ppc_elf_check_relocs): Update setting of reloc flags.  Set old_bfd.
	(ppc_elf_select_plt_layout): Modify parameters.  Use bfd reloc
	flags to better detect object files needing old bss-style plt.
	Allow secure plt to be used without rel16 relocs being detected.
	Warn if secure plt request cannot be allowed.
ld/
	* emultempl/ppc32elf.em (plt_style): New variable.
	(old_plt): Delete.
	(ppc_after_open): Adjust ppc_elf_select_plt_layout call.
	(PARSE_AND_LIST_PROLOGUE): Define OPTION_NEW_PLT, renumber
	OPTION_OLD_PLT, OPTION_OLD_GOT and OPTION_STUBSYMS.
	(PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS): Add secure-plt.
	(PARSE_AND_LIST_ARGS_CASES): Handle OPTION_NEW_PLT.
	* ld.texinfo (--secure-plt): Document.

Index: bfd/elf32-ppc.h
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.h,v
retrieving revision 1.9
diff -u -p -r1.9 elf32-ppc.h
--- bfd/elf32-ppc.h	8 Dec 2005 11:41:12 -0000	1.9
+++ bfd/elf32-ppc.h	8 May 2007 01:33:49 -0000
@@ -1,5 +1,5 @@
 /* PowerPC-specific support for 64-bit ELF.
-   Copyright 2003, 2005 Free Software Foundation, Inc.
+   Copyright 2003, 2005, 2007 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -17,7 +17,15 @@ You should have received a copy of the G
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
-int ppc_elf_select_plt_layout (bfd *, struct bfd_link_info *, int, int);
+enum ppc_elf_plt_type {
+  PLT_UNSET,
+  PLT_OLD,
+  PLT_NEW,
+  PLT_VXWORKS
+};
+
+int ppc_elf_select_plt_layout (bfd *, struct bfd_link_info *,
+			       enum ppc_elf_plt_type, int);
 asection *ppc_elf_tls_setup (bfd *, struct bfd_link_info *);
 bfd_boolean ppc_elf_tls_optimize (bfd *, struct bfd_link_info *);
 void ppc_elf_set_sdata_syms (bfd *, struct bfd_link_info *);
Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.213
diff -u -p -r1.213 elf32-ppc.c
--- bfd/elf32-ppc.c	26 Apr 2007 14:46:56 -0000	1.213
+++ bfd/elf32-ppc.c	8 May 2007 01:33:48 -0000
@@ -1712,6 +1712,10 @@ struct ppc_elf_obj_tdata
   /* A mapping from local symbols to offsets into the various linker
      sections added.  This is index by the symbol index.  */
   elf_linker_section_pointers_t **linker_section_pointers;
+
+  /* Flags used to auto-detect plt type.  */
+  unsigned int makes_plt_call : 1;
+  unsigned int has_rel16 : 1;
 };
 
 #define ppc_elf_tdata(bfd) \
@@ -2381,13 +2385,6 @@ struct ppc_elf_link_hash_entry
 
 #define ppc_elf_hash_entry(ent) ((struct ppc_elf_link_hash_entry *) (ent))
 
-enum ppc_elf_plt_type {
-  PLT_UNSET,
-  PLT_OLD,
-  PLT_NEW,
-  PLT_VXWORKS
-};
-
 /* PPC ELF linker hash table.  */
 
 struct ppc_elf_link_hash_table
@@ -2407,9 +2404,18 @@ struct ppc_elf_link_hash_table
   elf_linker_section_t sdata[2];
   asection *sbss;
 
+  /* The (unloaded but important) .rela.plt.unloaded on VxWorks.  */
+  asection *srelplt2;
+
+  /* The .got.plt section (VxWorks only)*/
+  asection *sgotplt;
+
   /* Shortcut to .__tls_get_addr.  */
   struct elf_link_hash_entry *tls_get_addr;
 
+  /* The bfd that forced an old-style PLT.  */
+  bfd *old_bfd;
+ 
   /* TLS local dynamic got entry handling.  */
   union {
     bfd_signed_vma refcount;
@@ -2427,23 +2433,11 @@ struct ppc_elf_link_hash_table
   /* The type of PLT we have chosen to use.  */
   enum ppc_elf_plt_type plt_type;
 
-  /* Whether we can use the new PLT layout.  */
-  unsigned int can_use_new_plt:1;
-
   /* Set if we should emit symbols for stubs.  */
   unsigned int emit_stub_syms:1;
 
-  /* Small local sym to section mapping cache.  */
-  struct sym_sec_cache sym_sec;
-
-  /* The (unloaded but important) .rela.plt.unloaded on VxWorks.  */
-  asection *srelplt2;
-
-  /* The .got.plt section (VxWorks only)*/
-  asection *sgotplt;
-
   /* True if the target system is VxWorks.  */
-  int is_vxworks;
+  unsigned int is_vxworks:1;
 
   /* The size of PLT entries.  */
   int plt_entry_size;
@@ -2451,6 +2445,9 @@ struct ppc_elf_link_hash_table
   int plt_slot_size;
   /* The size of the first PLT entry.  */
   int plt_initial_entry_size;
+
+  /* Small local sym to section mapping cache.  */
+  struct sym_sec_cache sym_sec;
 };
 
 /* Get the PPC ELF linker hash table from a link_info structure.  */
@@ -2522,8 +2519,6 @@ ppc_elf_link_hash_table_create (bfd *abf
   ret->plt_entry_size = 12;
   ret->plt_slot_size = 8;
   ret->plt_initial_entry_size = 72;
-  
-  ret->is_vxworks = 0;
 
   return &ret->elf.root;
 }
@@ -3293,8 +3288,13 @@ ppc_elf_check_relocs (bfd *abfd,
 	    }
 	  else
 	    {
-	      bfd_vma addend = r_type == R_PPC_PLTREL24 ? rel->r_addend : 0;
+	      bfd_vma addend = 0;
 
+	      if (r_type == R_PPC_PLTREL24)
+		{
+		  ppc_elf_tdata (abfd)->makes_plt_call = 1;
+		  addend = rel->r_addend;
+		}
 	      h->needs_plt = 1;
 	      if (!update_plt_info (abfd, h, got2, addend))
 		return FALSE;
@@ -3319,7 +3319,7 @@ ppc_elf_check_relocs (bfd *abfd,
 	case R_PPC_REL16_LO:
 	case R_PPC_REL16_HI:
 	case R_PPC_REL16_HA:
-	  htab->can_use_new_plt = 1;
+	  ppc_elf_tdata (abfd)->has_rel16 = 1;
 	  break;
 
 	  /* These are just markers.  */
@@ -3348,7 +3348,10 @@ ppc_elf_check_relocs (bfd *abfd,
 	  /* This refers only to functions defined in the shared library.  */
 	case R_PPC_LOCAL24PC:
 	  if (h && h == htab->elf.hgot && htab->plt_type == PLT_UNSET)
-	    htab->plt_type = PLT_OLD;
+	    {
+	      htab->plt_type = PLT_OLD;
+	      htab->old_bfd = abfd;
+	    }
 	  break;
 
 	  /* This relocation describes the C++ object vtable hierarchy.
@@ -3402,7 +3405,10 @@ ppc_elf_check_relocs (bfd *abfd,
 	      s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, sec,
 					     r_symndx);
 	      if (s == got2)
-		htab->plt_type = PLT_OLD;
+		{
+		  htab->plt_type = PLT_OLD;
+		  htab->old_bfd = abfd;
+		}
 	    }
 	  if (h == NULL || h == htab->elf.hgot)
 	    break;
@@ -3417,7 +3423,10 @@ ppc_elf_check_relocs (bfd *abfd,
 	  if (h == htab->elf.hgot)
 	    {
 	      if (htab->plt_type == PLT_UNSET)
-		htab->plt_type = PLT_OLD;
+		{
+		  htab->plt_type = PLT_OLD;
+		  htab->old_bfd = abfd;
+		}
 	      break;
 	    }
 	  /* fall through */
@@ -3671,7 +3680,7 @@ ppc_elf_merge_private_bfd_data (bfd *ibf
 int
 ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED,
 			   struct bfd_link_info *info,
-			   int force_old_plt,
+			   enum ppc_elf_plt_type plt_style,
 			   int emit_stub_syms)
 {
   struct ppc_elf_link_hash_table *htab;
@@ -3680,8 +3689,37 @@ ppc_elf_select_plt_layout (bfd *output_b
   htab = ppc_elf_hash_table (info);
 
   if (htab->plt_type == PLT_UNSET)
-    htab->plt_type = (force_old_plt || !htab->can_use_new_plt
-		      ? PLT_OLD : PLT_NEW);
+    {
+      if (plt_style == PLT_OLD)
+	htab->plt_type = PLT_OLD;
+      else
+	{
+	  bfd *ibfd;
+	  enum ppc_elf_plt_type plt_type = plt_style;
+
+	  /* Look through the reloc flags left by ppc_elf_check_relocs.
+	     Use the old style bss plt if a file makes plt calls
+	     without using the new relocs, and if ld isn't given
+	     --secure-plt and we never see REL16 relocs.  */
+	  if (plt_type == PLT_UNSET)
+	    plt_type = PLT_OLD;
+	  for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->next)
+	    if (is_ppc_elf_target (ibfd->xvec))
+	      {
+		if (ppc_elf_tdata (ibfd)->has_rel16)
+		  plt_type = PLT_NEW;
+		else if (ppc_elf_tdata (ibfd)->makes_plt_call)
+		  {
+		    plt_type = PLT_OLD;
+		    htab->old_bfd = ibfd;
+		    break;
+		  }
+	      }
+	  htab->plt_type = plt_type;
+	}
+    }
+  if (htab->plt_type == PLT_OLD && plt_style == PLT_NEW)
+    info->callbacks->info (_("Using bss-plt due to %B"), htab->old_bfd);
 
   htab->emit_stub_syms = emit_stub_syms;
 
Index: ld/emultempl/ppc32elf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/ppc32elf.em,v
retrieving revision 1.12
diff -u -p -r1.12 ppc32elf.em
--- ld/emultempl/ppc32elf.em	26 Mar 2007 11:10:44 -0000	1.12
+++ ld/emultempl/ppc32elf.em	8 May 2007 01:34:19 -0000
@@ -45,7 +45,7 @@ static int notlsopt = 0;
 static int emit_stub_syms = 0;
 
 /* Chooses the correct place for .plt and .got.  */
-static int old_plt = 0;
+static enum ppc_elf_plt_type plt_style = PLT_UNSET;
 static int old_got = 0;
 
 static void
@@ -62,7 +62,7 @@ ppc_after_open (void)
       lang_output_section_statement_type *got_os[2];
 
       emit_stub_syms |= link_info.emitrelocations;
-      new_plt = ppc_elf_select_plt_layout (output_bfd, &link_info, old_plt,
+      new_plt = ppc_elf_select_plt_layout (output_bfd, &link_info, plt_style,
 					   emit_stub_syms);
       if (new_plt < 0)
 	einfo ("%X%P: select_plt_layout problem %E\n");
@@ -148,14 +148,16 @@ fi
 #
 PARSE_AND_LIST_PROLOGUE='
 #define OPTION_NO_TLS_OPT		301
-#define OPTION_OLD_PLT			302
-#define OPTION_OLD_GOT			303
-#define OPTION_STUBSYMS			304
+#define OPTION_NEW_PLT			302
+#define OPTION_OLD_PLT			303
+#define OPTION_OLD_GOT			304
+#define OPTION_STUBSYMS			305
 '
 
 PARSE_AND_LIST_LONGOPTS='
   { "emit-stub-syms", no_argument, NULL, OPTION_STUBSYMS },
   { "no-tls-optimize", no_argument, NULL, OPTION_NO_TLS_OPT },
+  { "secure-plt", no_argument, NULL, OPTION_NEW_PLT },
   { "bss-plt", no_argument, NULL, OPTION_OLD_PLT },
   { "sdata-got", no_argument, NULL, OPTION_OLD_GOT },
 '
@@ -164,6 +166,7 @@ PARSE_AND_LIST_OPTIONS='
   fprintf (file, _("\
   --emit-stub-syms      Label linker stubs with a symbol.\n\
   --no-tls-optimize     Don'\''t try to optimize TLS accesses.\n\
+  --secure-plt          Use new-style PLT if possible.\n\
   --bss-plt             Force old-style BSS PLT.\n\
   --sdata-got           Force GOT location just before .sdata.\n"
 		   ));
@@ -178,8 +181,12 @@ PARSE_AND_LIST_ARGS_CASES='
       notlsopt = 1;
       break;
 
+    case OPTION_NEW_PLT:
+      plt_style = PLT_NEW;
+      break;
+
     case OPTION_OLD_PLT:
-      old_plt = 1;
+      plt_style = PLT_OLD;
       break;
 
     case OPTION_OLD_GOT:
Index: ld/ld.texinfo
===================================================================
RCS file: /cvs/src/src/ld/ld.texinfo,v
retrieving revision 1.194
diff -u -p -r1.194 ld.texinfo
--- ld/ld.texinfo	3 May 2007 09:24:16 -0000	1.194
+++ ld/ld.texinfo	11 May 2007 06:05:13 -0000
@@ -5699,6 +5699,14 @@ PLT, if all input files (including start
 compiled with @samp{-msecure-plt}.  @samp{--bss-plt} forces the old
 BSS PLT (and GOT layout) which can give slightly better performance.
 
+@kindex --secure-plt
+@item --secure-plt
+@command{ld} will use the new PLT and GOT layout if it is linking new
+@samp{-fpic} or @samp{-fPIC} code, but does not do so automatically
+when linking non-PIC code.  This option requests the new PLT and GOT
+layout.  A warning will be given if some object file requires the old
+style BSS PLT.
+
 @cindex PowerPC GOT
 @kindex --sdata-got
 @item --sdata-got

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


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