From 795bc6b3eac9e3f80279df69c05d70fc44eaaa4c Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 12 Feb 2014 16:44:36 +1030 Subject: [PATCH] Enable ppc476 workaround for ld -r. 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 | 7 +++++++ bfd/elf32-ppc.c | 17 +++++++++++------ bfd/elf32-ppc.h | 2 +- ld/ChangeLog | 6 ++++++ ld/emultempl/ppc32elf.em | 13 ++++++++----- 5 files changed, 33 insertions(+), 12 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 391099a6ad1..120a2f51329 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2014-02-12 Alan Modra + + * 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 PR gold/15530 diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 0b43b9b9a87..f7c03663162 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 09092455eca..fef177af72c 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/ChangeLog b/ld/ChangeLog index 5331a1ea98c..9ab809e5f8b 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,9 @@ +2014-02-12 Alan Modra + + * 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 * emulparams/aarch64linux32.sh (LIBPATH_SUFFIX): Change to ilp32. diff --git a/ld/emultempl/ppc32elf.em b/ld/emultempl/ppc32elf.em index afa85ffe9cd..8de230a6e77 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, ¶ms); @@ -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; -- 2.30.2