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


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

PowerPC PLT stub alignment fixes


Asking for ppc32 plt call stubs to be aligned at 32 byte boundaries
didn't quite work.  For ld.bfd they were spaced 32 bytes apart, but
only started on a 16 byte boundary.  ld.gold also didn't get it right.

Finding that bug made me check over the ppc64 plt stub alignment,
where I found that negative values for alignment (meaning align to
minimize boundary crossing) were not accepted.  Since no one has
complained about that, I guess I could have removed the feature from
ld.bfd documentation, but I've opted instead to correct the code.

I've also added an optional alignment paramenter for ppc32
--plt-align, for some consistency with gold and ppc64 ld.bfd.

bfd/
	* elf32-ppc.c (ppc_elf_create_glink): Correct alignment of .glink.
	* elf64-ppc.c (ppc64_elf_size_stubs): Handle negative plt_stub_align.
	(ppc64_elf_build_stubs): Likewise.
gold/
	* powerpc.cc (param_plt_align): New function supplying default
	--plt-align values.  Use it..
	(Stub_table::plt_call_align): ..here, and..
	(Output_data_glink::global_entry_align): ..here.
	(Stub_table::stub_align): Correct 32-bit minimum alignment.
ld/
	* emultempl/ppc32elf.em: Support optional --plt-align arg.
	* emultempl/ppc64elf.em: Support negative --plt-align arg.

diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 73701d4..32104a1 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -3475,14 +3475,17 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info)
   struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info);
   asection *s;
   flagword flags;
+  int p2align;
 
   flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY | SEC_HAS_CONTENTS
 	   | SEC_IN_MEMORY | SEC_LINKER_CREATED);
   s = bfd_make_section_anyway_with_flags (abfd, ".glink", flags);
   htab->glink = s;
+  p2align = htab->params->ppc476_workaround ? 6 : 4;
+  if (p2align < htab->params->plt_stub_align)
+    p2align = htab->params->plt_stub_align;
   if (s == NULL
-      || !bfd_set_section_alignment (abfd, s,
-				     htab->params->ppc476_workaround ? 6 : 4))
+      || !bfd_set_section_alignment (abfd, s, p2align))
     return FALSE;
 
   if (!info->no_ld_generated_unwind_info)
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 65cf7fe..b2d288b 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -12743,9 +12743,11 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
       if (htab->params->plt_stub_align != 0)
 	for (group = htab->group; group != NULL; group = group->next)
 	  if (group->stub_sec != NULL)
-	    group->stub_sec->size = ((group->stub_sec->size
-				      + (1 << htab->params->plt_stub_align) - 1)
-				     & -(1 << htab->params->plt_stub_align));
+	    {
+	      int align = abs (htab->params->plt_stub_align);
+	      group->stub_sec->size
+		= (group->stub_sec->size + (1 << align) - 1) & -(1 << align);
+	    }
 
       for (group = htab->group; group != NULL; group = group->next)
 	if (group->stub_sec != NULL
@@ -13285,9 +13287,10 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
   if (htab->params->plt_stub_align != 0)
     for (group = htab->group; group != NULL; group = group->next)
       if ((stub_sec = group->stub_sec) != NULL)
-	stub_sec->size = ((stub_sec->size
-			   + (1 << htab->params->plt_stub_align) - 1)
-			  & -(1 << htab->params->plt_stub_align));
+	{
+	  int align = abs (htab->params->plt_stub_align);
+	  stub_sec->size = (stub_sec->size + (1 << align) - 1) & -(1 << align);
+	}
 
   for (group = htab->group; group != NULL; group = group->next)
     if ((stub_sec = group->stub_sec) != NULL)
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index 6b65792..3c38a06 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -4186,6 +4186,15 @@ output_bctr(unsigned char* p)
   return p;
 }
 
+template<int size>
+static inline unsigned int
+param_plt_align()
+{
+  if (!parameters->options().user_set_plt_align())
+    return size == 64 ? 32 : 8;
+  return 1 << parameters->options().plt_align();
+}
+
 // Stub_table holds information about plt and long branch stubs.
 // Stubs are built in an area following some input section determined
 // by group_sections().  This input section is converted to a relaxed
@@ -4412,9 +4421,7 @@ class Stub_table : public Output_relaxed_input_section
   unsigned int
   stub_align() const
   {
-    unsigned int min_align = 4;
-    if (!parameters->options().user_set_plt_align())
-      return size == 64 ? 32 : min_align;
+    unsigned int min_align = size == 64 ? 32 : 16;
     unsigned int user_align = 1 << parameters->options().plt_align();
     return std::max(user_align, min_align);
   }
@@ -4483,7 +4490,7 @@ class Stub_table : public Output_relaxed_input_section
   unsigned int
   plt_call_align(unsigned int bytes) const
   {
-    unsigned int align = this->stub_align();
+    unsigned int align = param_plt_align<size>();
     return (bytes + align - 1) & -align;
   }
 
@@ -4926,9 +4933,7 @@ class Output_data_glink : public Output_section_data
   unsigned int
   global_entry_align(unsigned int off) const
   {
-    unsigned int align = 1 << parameters->options().plt_align();
-    if (!parameters->options().user_set_plt_align())
-      align = size == 64 ? 32 : 4;
+    unsigned int align = param_plt_align<size>();
     return (off + align - 1) & -align;
   }
 
diff --git a/ld/emultempl/ppc32elf.em b/ld/emultempl/ppc32elf.em
index 4e71a78..3007fb2 100644
--- a/ld/emultempl/ppc32elf.em
+++ b/ld/emultempl/ppc32elf.em
@@ -271,7 +271,7 @@ if test -z "$VXWORKS_BASE_EM_FILE" ; then
   { "bss-plt", no_argument, NULL, OPTION_OLD_PLT },
   { "speculate-indirect-jumps", no_argument, NULL, OPTION_SPECULATE_INDIRECT_JUMPS },
   { "no-speculate-indirect-jumps", no_argument, NULL, OPTION_NO_SPECULATE_INDIRECT_JUMPS },
-  { "plt-align", no_argument, NULL, OPTION_PLT_ALIGN },
+  { "plt-align", optional_argument, NULL, OPTION_PLT_ALIGN },
   { "no-plt-align", no_argument, NULL, OPTION_NO_PLT_ALIGN },
   { "sdata-got", no_argument, NULL, OPTION_OLD_GOT },'
 fi
@@ -369,7 +369,16 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}'
       break;
 
     case OPTION_PLT_ALIGN:
-      params.plt_stub_align = 5;
+      if (optarg != NULL)
+	{
+	  char *end;
+	  unsigned long val = strtoul (optarg, &end, 0);
+	  if (*end || val > 5)
+	    einfo (_("%P%F: invalid --plt-align `%s'\''\n"), optarg);
+	  params.plt_stub_align = val;
+	}
+      else
+	params.plt_stub_align = 5;
       break;
 
     case OPTION_NO_PLT_ALIGN:
diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em
index c7c27b0..0baa424 100644
--- a/ld/emultempl/ppc64elf.em
+++ b/ld/emultempl/ppc64elf.em
@@ -872,8 +872,8 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}'
       if (optarg != NULL)
 	{
 	  char *end;
-	  unsigned long val = strtoul (optarg, &end, 0);
-	  if (*end || val > 8)
+	  long val = strtol (optarg, &end, 0);
+	  if (*end || (unsigned long) val + 8 > 16)
 	    einfo (_("%P%F: invalid --plt-align `%s'\''\n"), optarg);
 	  params.plt_stub_align = val;
 	}

-- 
Alan Modra
Australia Development Lab, IBM


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