diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f1c5c413f60..3c8fcf3ab74 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2018-01-18 Alan Modra + + * 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 * po/ru.po: Updated Russian translation. diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 73701d48c6f..32104a12fdf 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 65cf7feb391..b2d288bd4e7 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/ChangeLog b/gold/ChangeLog index ec56a894674..b833a7b3630 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,11 @@ +2018-01-18 Alan Modra + + * 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 * options.h (speculate_indirect_jumps): New option. diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 6b65792a66f..3c38a06e83a 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -4186,6 +4186,15 @@ output_bctr(unsigned char* p) return p; } +template +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(); 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(); return (off + align - 1) & -align; } diff --git a/ld/ChangeLog b/ld/ChangeLog index 9ee555baa7a..38017053026 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,8 @@ +2018-01-18 Alan Modra + + * emultempl/ppc32elf.em: Support optional --plt-align arg. + * emultempl/ppc64elf.em: Support negative --plt-align arg. + 2018-01-17 Alan Modra * emultempl/ppc32elf.em (params): Init new field. diff --git a/ld/emultempl/ppc32elf.em b/ld/emultempl/ppc32elf.em index 4e71a7802cc..3007fb2f801 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 c7c27b04152..0baa424339a 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; }