Enable ppc476 workaround for ld -r.
authorAlan Modra <amodra@gmail.com>
Wed, 12 Feb 2014 06:14:36 +0000 (16:44 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 12 Feb 2014 11:40:09 +0000 (22:10 +1030)
The Linux kernel builds modules using ld -r.  These might need the
ppc476 workaround, so enable it for ld -r if sections have sufficient
alignment to tell location within a page.

bfd/
* elf32-ppc.c (ppc_elf_relax_section): Enable ppc476 workaround
for ld -r, when code sections are sufficiently aligned.
* elf32-ppc.h (struct ppc_elf_params): Delete pagesize.  Add
pagesize_p2.
ld/
* emultempl/ppc32elf.em (pagesize): New static var.
(ppc_after_open_output): Set params.pagesize_p2 from pagesize.
(PARSE_AND_LIST_ARGS_CASES): Adjust to use pagesize.

bfd/ChangeLog
bfd/elf32-ppc.c
bfd/elf32-ppc.h
ld/ChangeLog
ld/emultempl/ppc32elf.em

index 391099a6ad12b2f924adb2e9331fcf27e4f3de8b..120a2f5132944a3984537a816ce799c40afe9da1 100644 (file)
@@ -1,3 +1,10 @@
+2014-02-12  Alan Modra  <amodra@gmail.com>
+
+       * elf32-ppc.c (ppc_elf_relax_section): Enable ppc476 workaround
+       for ld -r, when code sections are sufficiently aligned.
+       * elf32-ppc.h (struct ppc_elf_params): Delete pagesize.  Add
+       pagesize_p2.
+
 2014-02-12  Alan Modra  <amodra@gmail.com>
 
        PR gold/15530
index 0b43b9b9a87a42b3399a0975f75c921c75ae2e3e..f7c03663162457c1d4415d425362d35b7a08ccf9 100644 (file)
@@ -6690,7 +6690,7 @@ ppc_elf_relax_section (bfd *abfd,
      do anything.  The linker doesn't support mixing -shared and -r
      anyway.  */
   if (link_info->relocatable && link_info->shared)
-     return TRUE;
+    return TRUE;
 
   htab = ppc_elf_hash_table (link_info);
   if (htab == NULL)
@@ -7060,16 +7060,18 @@ ppc_elf_relax_section (bfd *abfd,
 
   workaround_change = FALSE;
   newsize = trampoff;
-  if (htab->params->ppc476_workaround)
+  if (htab->params->ppc476_workaround
+      && (!link_info->relocatable
+         || isec->output_section->alignment_power >= htab->params->pagesize_p2))
     {
       bfd_vma addr, end_addr;
       unsigned int crossings;
-      unsigned int pagesize = htab->params->pagesize;
+      bfd_vma pagesize = (bfd_vma) 1 << htab->params->pagesize_p2;
 
       addr = isec->output_section->vma + isec->output_offset;
       end_addr = addr + trampoff - 1;
       addr &= -pagesize;
-      crossings = ((end_addr & -pagesize) - addr) / pagesize;
+      crossings = ((end_addr & -pagesize) - addr) >> htab->params->pagesize_p2;
       if (crossings != 0)
        {
          /* Keep space aligned, to ensure the patch code itself does
@@ -9134,11 +9136,14 @@ ppc_elf_relocate_section (bfd *output_bfd,
     }
 
   if (htab->params->ppc476_workaround
-      && input_section->sec_info_type == SEC_INFO_TYPE_TARGET)
+      && input_section->sec_info_type == SEC_INFO_TYPE_TARGET
+      && (!info->relocatable
+         || (input_section->output_section->alignment_power
+             >= htab->params->pagesize_p2)))
     {
       struct ppc_elf_relax_info *relax_info;
       bfd_vma start_addr, end_addr, addr;
-      unsigned int pagesize = htab->params->pagesize;
+      bfd_vma pagesize = (bfd_vma) 1 << htab->params->pagesize_p2;
 
       relax_info = elf_section_data (input_section)->sec_info;
       if (relax_info->workaround_size != 0)
index 09092455ecaea4ca952fde329ac14f6f2dd88904..fef177af72c9f0dc581f829acb0401adfb57b4b7 100644 (file)
@@ -43,7 +43,7 @@ struct ppc_elf_params
 
   /* Avoid execution falling into new page.  */
   int ppc476_workaround;
-  int pagesize;
+  unsigned int pagesize_p2;
 };
 
 void ppc_elf_link_params (struct bfd_link_info *, struct ppc_elf_params *);
index 5331a1ea98c3398c6cd6ed2242bb730172fde8d4..9ab809e5f8bf50b73c8d061d66fd2a43b6b6ee23 100644 (file)
@@ -1,3 +1,9 @@
+2014-02-12  Alan Modra  <amodra@gmail.com>
+
+       * emultempl/ppc32elf.em (pagesize): New static var.
+       (ppc_after_open_output): Set params.pagesize_p2 from pagesize.
+       (PARSE_AND_LIST_ARGS_CASES): Adjust to use pagesize.
+
 2014-02-11  Andrew Pinski  <apinski@cavium.com>
 
        * emulparams/aarch64linux32.sh (LIBPATH_SUFFIX): Change to ilp32.
index afa85ffe9cd46b35f371d07556edccb351769b66..8de230a6e771272389a4ea0d6ca95562260521e6 100644 (file)
@@ -39,6 +39,8 @@ static int notlsopt = 0;
 /* Choose the correct place for .got.  */
 static int old_got = 0;
 
+static bfd_vma pagesize = 0;
+
 static struct ppc_elf_params params = { PLT_UNSET, -1, 0, 0, 0, 0 };
 
 static void
@@ -46,8 +48,9 @@ ppc_after_open_output (void)
 {
   if (params.emit_stub_syms < 0)
     params.emit_stub_syms = link_info.emitrelocations || link_info.shared;
-  if (params.pagesize == 0)
-    params.pagesize = config.commonpagesize;
+  if (pagesize == 0)
+    pagesize = config.commonpagesize;
+  params.pagesize_p2 = bfd_log2 (pagesize);
   if (link_info.relocatable)
     params.ppc476_workaround = 0;
   ppc_elf_link_params (&link_info, &params);
@@ -267,10 +270,10 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}'
       if (optarg != NULL)
        {
          char *end;
-         params.pagesize = strtoul (optarg, &end, 0);
+         pagesize = strtoul (optarg, &end, 0);
          if (*end
-             || (params.pagesize < 4096 && params.pagesize != 0)
-             || params.pagesize != (params.pagesize & -params.pagesize))
+             || (pagesize < 4096 && pagesize != 0)
+             || pagesize != (pagesize & -pagesize))
            einfo (_("%P%F: invalid pagesize `%s'\''\n"), optarg);
        }
       break;