Enable ppc476 workaround for ld -r

Alan Modra amodra@gmail.com
Wed Feb 12 11:36:00 GMT 2014


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.

diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 0b43b9b..f7c0366 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -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)
diff --git a/bfd/elf32-ppc.h b/bfd/elf32-ppc.h
index 0909245..fef177a 100644
--- a/bfd/elf32-ppc.h
+++ b/bfd/elf32-ppc.h
@@ -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 *);
diff --git a/ld/emultempl/ppc32elf.em b/ld/emultempl/ppc32elf.em
index afa85ff..8de230a 100644
--- a/ld/emultempl/ppc32elf.em
+++ b/ld/emultempl/ppc32elf.em
@@ -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;

-- 
Alan Modra
Australia Development Lab, IBM



More information about the Binutils mailing list