PowerPC PLT stub alignment fixes
authorAlan Modra <amodra@gmail.com>
Thu, 18 Jan 2018 11:36:40 +0000 (22:06 +1030)
committerAlan Modra <amodra@gmail.com>
Thu, 18 Jan 2018 11:55:21 +0000 (22:25 +1030)
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.

bfd/ChangeLog
bfd/elf32-ppc.c
bfd/elf64-ppc.c
gold/ChangeLog
gold/powerpc.cc
ld/ChangeLog
ld/emultempl/ppc32elf.em
ld/emultempl/ppc64elf.em

index f1c5c413f605c9b6ccca48bcc02bb320e135f185..3c8fcf3ab747a896ce147d9c8de9378ccb774443 100644 (file)
@@ -1,3 +1,9 @@
+2018-01-18  Alan Modra  <amodra@gmail.com>
+
+       * 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.
+
 2018-01-17  Nick Clifton  <nickc@redhat.com>
 
        * po/ru.po: Updated Russian translation.
index 73701d48c6f68359eee1943c6e73c84c31156211..32104a12fdf03bb727f73c4aaedc72eee9fa9d75 100644 (file)
@@ -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)
index 65cf7feb3914a02d65abefe8dbc3b4640222c418..b2d288bd4e77e7e576523643efa410585babc695 100644 (file)
@@ -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)
index ec56a89467422472a58821ce27277ca2fb3e7a02..b833a7b36306bc63df40f17661b22da39fdd20ed 100644 (file)
@@ -1,3 +1,11 @@
+2018-01-18  Alan Modra  <amodra@gmail.com>
+
+       * 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.
+
 2018-01-17  Alan Modra  <amodra@gmail.com>
 
        * options.h (speculate_indirect_jumps): New option.
index 6b65792a66ff11150f348fd0997883532b6c8961..3c38a06e83afa29c210dd5d4900036c058875a4d 100644 (file)
@@ -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;
   }
 
index 9ee555baa7ad20f4f95fa86ee22106c9ce40bf33..380170530266ccf1f4390f90f4820b69c3eb13cc 100644 (file)
@@ -1,3 +1,8 @@
+2018-01-18  Alan Modra  <amodra@gmail.com>
+
+       * emultempl/ppc32elf.em: Support optional --plt-align arg.
+       * emultempl/ppc64elf.em: Support negative --plt-align arg.
+
 2018-01-17  Alan Modra  <amodra@gmail.com>
 
        * emultempl/ppc32elf.em (params): Init new field.
index 4e71a7802cc32dcbcdc5ffbae8bd8f05beeba590..3007fb2f801da834a24ce7ac84247da336f0bc87 100644 (file)
@@ -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:
index c7c27b04152958fabe23d3af6fddda739175088e..0baa424339a61ae03d5fa4fae2c6ad7657825511 100644 (file)
@@ -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;
        }