From: Alan Modra Date: Mon, 17 Feb 2014 06:38:00 +0000 (+1030) Subject: Consolidate ppc64 ld/bfd communication X-Git-Tag: gdb-7.8-release~1307 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e7d1c40ce59ff355d2a51ff64a657c772eabbbfe;p=external%2Fbinutils.git Consolidate ppc64 ld/bfd communication Moves assorted variables used to communicate between ld and bfd into a struct, hooks it into the bfd link_hash_table early, and removes all other places where such variables were passed piecemeal. bfd/ * elf64-ppc.h (struct ppc64_elf_params): Define. (ppc64_elf_init_stub_bfd, ppc64_elf_edit_opd, ppc64_elf_tls_setup, ppc64_elf_setup_section_lists, ppc64_elf_size_stubs, ppc64_elf_build_stubs): Update prototype. * elf64-ppp.c (struct ppc_link_hash_table): Add params, delete other fields now in params. Adjust code throughout file. (ppc64_elf_init_stub_bfd): Delete "abfd" parameter, add "params". Save params pointer in htab. (ppc64_elf_edit_opd, ppc64_elf_tls_setup, ppc64_elf_setup_section_lists, ppc64_elf_size_stubs, ppc64_elf_build_stubs): Remove parameters now in "params". ld/ * emultemps/ppc64elf.em (params): New static struct replacing various other static vars. Adjust code throughout file. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 86f9d84..75cf244 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,19 @@ 2014-02-17 Alan Modra + * elf64-ppc.h (struct ppc64_elf_params): Define. + (ppc64_elf_init_stub_bfd, ppc64_elf_edit_opd, ppc64_elf_tls_setup, + ppc64_elf_setup_section_lists, ppc64_elf_size_stubs, + ppc64_elf_build_stubs): Update prototype. + * elf64-ppp.c (struct ppc_link_hash_table): Add params, delete other + fields now in params. Adjust code throughout file. + (ppc64_elf_init_stub_bfd): Delete "abfd" parameter, add "params". + Save params pointer in htab. + (ppc64_elf_edit_opd, ppc64_elf_tls_setup, + ppc64_elf_setup_section_lists, ppc64_elf_size_stubs, + ppc64_elf_build_stubs): Remove parameters now in "params". + +2014-02-17 Alan Modra + * elf32-ppc.c (ppc_elf_relocate_section): Move relocs on insns patched for ppc476 workaround. Reapply branch taken/not taken relocs. diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 5d77961..795d093 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -3873,12 +3873,8 @@ struct ppc_link_hash_table /* Hash table for function prologue tocsave. */ htab_t tocsave_htab; - /* Linker stub bfd. */ - bfd *stub_bfd; - - /* Linker call-backs. */ - asection * (*add_stub_section) (const char *, asection *); - void (*layout_sections_again) (void); + /* Various options and other info passed from the linker. */ + struct ppc64_elf_params *params; /* Array to keep track of which stub sections have been created, and information on stub grouping. */ @@ -3930,24 +3926,9 @@ struct ppc_link_hash_table /* Number of stubs against global syms. */ unsigned long stub_globals; - /* Alignment of PLT call stubs. */ - unsigned int plt_stub_align:4; - /* Set if we're linking code with function descriptors. */ unsigned int opd_abi:1; - /* Set if PLT call stubs should load r11. */ - unsigned int plt_static_chain:1; - - /* Set if PLT call stubs need a read-read barrier. */ - unsigned int plt_thread_safe:1; - - /* Set if we should emit symbols for stubs. */ - unsigned int emit_stub_syms:1; - - /* Set if __tls_get_addr optimization should not be done. */ - unsigned int no_tls_get_addr_opt:1; - /* Support for multiple toc sections. */ unsigned int do_multi_toc:1; unsigned int multi_toc_needed:1; @@ -4303,11 +4284,12 @@ create_linkage_sections (bfd *dynobj, struct bfd_link_info *info) /* Satisfy the ELF linker by filling in some fields in our fake bfd. */ bfd_boolean -ppc64_elf_init_stub_bfd (bfd *abfd, struct bfd_link_info *info) +ppc64_elf_init_stub_bfd (struct bfd_link_info *info, + struct ppc64_elf_params *params) { struct ppc_link_hash_table *htab; - elf_elfheader (abfd)->e_ident[EI_CLASS] = ELFCLASS64; + elf_elfheader (params->stub_bfd)->e_ident[EI_CLASS] = ELFCLASS64; /* Always hook our dynamic sections into the first bfd, which is the linker created stub bfd. This ensures that the GOT header is at @@ -4315,8 +4297,8 @@ ppc64_elf_init_stub_bfd (bfd *abfd, struct bfd_link_info *info) htab = ppc_hash_table (info); if (htab == NULL) return FALSE; - htab->stub_bfd = abfd; - htab->elf.dynobj = abfd; + htab->elf.dynobj = params->stub_bfd; + htab->params = params; if (info->relocatable) return TRUE; @@ -4441,13 +4423,13 @@ ppc_add_stub (const char *stub_name, namelen = strlen (link_sec->name); len = namelen + sizeof (STUB_SUFFIX); - s_name = bfd_alloc (htab->stub_bfd, len); + s_name = bfd_alloc (htab->params->stub_bfd, len); if (s_name == NULL) return NULL; memcpy (s_name, link_sec->name, namelen); memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX)); - stub_sec = (*htab->add_stub_section) (s_name, link_sec); + stub_sec = (*htab->params->add_stub_section) (s_name, link_sec); if (stub_sec == NULL) return NULL; htab->stub_group[link_sec->id].stub_sec = stub_sec; @@ -7514,11 +7496,16 @@ dec_dynrel_count (bfd_vma r_info, applications. */ bfd_boolean -ppc64_elf_edit_opd (struct bfd_link_info *info, bfd_boolean non_overlapping) +ppc64_elf_edit_opd (struct bfd_link_info *info) { bfd *ibfd; bfd_boolean some_edited = FALSE; asection *need_pad = NULL; + struct ppc_link_hash_table *htab; + + htab = ppc_hash_table (info); + if (htab == NULL) + return FALSE; for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) { @@ -7671,7 +7658,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info, bfd_boolean non_overlapping) goto broken_opd; } - add_aux_fields = non_overlapping && cnt_16b > 0; + add_aux_fields = htab->params->non_overlapping_opd && cnt_16b > 0; if (need_edit || add_aux_fields) { @@ -7762,12 +7749,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info, bfd_boolean non_overlapping) if (h != NULL && h->root.root.string[0] == '.') { - struct ppc_link_hash_table *htab; - - htab = ppc_hash_table (info); - if (htab != NULL) - fdh = lookup_fdh ((struct ppc_link_hash_entry *) h, - htab); + fdh = lookup_fdh ((struct ppc_link_hash_entry *) h, htab); if (fdh != NULL && fdh->elf.root.type != bfd_link_hash_defined && fdh->elf.root.type != bfd_link_hash_defweak) @@ -7916,9 +7898,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info, bfd_boolean non_overlapping) /* Set htab->tls_get_addr and call the generic ELF tls_setup function. */ asection * -ppc64_elf_tls_setup (struct bfd_link_info *info, - int no_tls_get_addr_opt, - int *no_multi_toc) +ppc64_elf_tls_setup (struct bfd_link_info *info) { struct ppc_link_hash_table *htab; @@ -7929,10 +7909,10 @@ ppc64_elf_tls_setup (struct bfd_link_info *info, if (abiversion (info->output_bfd) == 1) htab->opd_abi = 1; - if (*no_multi_toc) + if (htab->params->no_multi_toc) htab->do_multi_toc = 0; else if (!htab->do_multi_toc) - *no_multi_toc = 1; + htab->params->no_multi_toc = 1; htab->tls_get_addr = ((struct ppc_link_hash_entry *) elf_link_hash_lookup (&htab->elf, ".__tls_get_addr", @@ -7943,7 +7923,7 @@ ppc64_elf_tls_setup (struct bfd_link_info *info, htab->tls_get_addr_fd = ((struct ppc_link_hash_entry *) elf_link_hash_lookup (&htab->elf, "__tls_get_addr", FALSE, FALSE, TRUE)); - if (!no_tls_get_addr_opt) + if (!htab->params->no_tls_get_addr_opt) { struct elf_link_hash_entry *opt, *opt_fd, *tga, *tga_fd; @@ -8011,9 +7991,8 @@ ppc64_elf_tls_setup (struct bfd_link_info *info, } } else - no_tls_get_addr_opt = TRUE; + htab->params->no_tls_get_addr_opt = TRUE; } - htab->no_tls_get_addr_opt = no_tls_get_addr_opt; return _bfd_elf_tls_setup (info->output_bfd, info); } @@ -9930,7 +9909,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd, return FALSE; } - tls_opt = (!htab->no_tls_get_addr_opt + tls_opt = (!htab->params->no_tls_get_addr_opt && htab->tls_get_addr_fd != NULL && htab->tls_get_addr_fd->elf.plt.plist != NULL); if (tls_opt || !htab->opd_abi) @@ -10102,17 +10081,17 @@ plt_stub_size (struct ppc_link_hash_table *htab, if (htab->opd_abi) { size += 4; - if (htab->plt_static_chain) + if (htab->params->plt_static_chain) size += 4; - if (htab->plt_thread_safe) + if (htab->params->plt_thread_safe) size += 8; - if (PPC_HA (off + 8 + 8 * htab->plt_static_chain) != PPC_HA (off)) + if (PPC_HA (off + 8 + 8 * htab->params->plt_static_chain) != PPC_HA (off)) size += 4; } if (stub_entry->h != NULL && (stub_entry->h == htab->tls_get_addr_fd || stub_entry->h == htab->tls_get_addr) - && !htab->no_tls_get_addr_opt) + && !htab->params->no_tls_get_addr_opt) size += 13 * 4; return size; } @@ -10124,7 +10103,7 @@ plt_stub_pad (struct ppc_link_hash_table *htab, struct ppc_stub_hash_entry *stub_entry, bfd_vma plt_off) { - int stub_align = 1 << htab->plt_stub_align; + int stub_align = 1 << htab->params->plt_stub_align; unsigned stub_size = plt_stub_size (htab, stub_entry, plt_off); bfd_vma stub_off = stub_entry->stub_sec->size; @@ -10141,10 +10120,10 @@ build_plt_stub (struct ppc_link_hash_table *htab, struct ppc_stub_hash_entry *stub_entry, bfd_byte *p, bfd_vma offset, Elf_Internal_Rela *r) { - bfd *obfd = htab->stub_bfd; + bfd *obfd = htab->params->stub_bfd; bfd_boolean plt_load_toc = htab->opd_abi; - bfd_boolean plt_static_chain = htab->plt_static_chain; - bfd_boolean plt_thread_safe = htab->plt_thread_safe; + bfd_boolean plt_static_chain = htab->params->plt_static_chain; + bfd_boolean plt_thread_safe = htab->params->plt_thread_safe; bfd_boolean use_fake_dep = plt_thread_safe; bfd_vma cmp_branch_off = 0; @@ -10154,7 +10133,7 @@ build_plt_stub (struct ppc_link_hash_table *htab, && !(stub_entry->h != NULL && (stub_entry->h == htab->tls_get_addr_fd || stub_entry->h == htab->tls_get_addr) - && !htab->no_tls_get_addr_opt)) + && !htab->params->no_tls_get_addr_opt)) { bfd_vma pltoff = stub_entry->plt_ent->plt.offset & ~1; bfd_vma pltindex = ((pltoff - PLT_INITIAL_ENTRY_SIZE (htab)) @@ -10321,7 +10300,7 @@ build_tls_get_addr_stub (struct ppc_link_hash_table *htab, struct ppc_stub_hash_entry *stub_entry, bfd_byte *p, bfd_vma offset, Elf_Internal_Rela *r) { - bfd *obfd = htab->stub_bfd; + bfd *obfd = htab->params->stub_bfd; bfd_put_32 (obfd, LD_R11_0R3 + 0, p), p += 4; bfd_put_32 (obfd, LD_R12_0R3 + 8, p), p += 4; @@ -10463,20 +10442,21 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) htab->stub_error = TRUE; return FALSE; } - bfd_put_32 (htab->stub_bfd, STD_R2_0R1 + STK_TOC (htab), loc); + bfd_put_32 (htab->params->stub_bfd, STD_R2_0R1 + STK_TOC (htab), loc); loc += 4; size = 12; if (PPC_HA (r2off) != 0) { size = 16; - bfd_put_32 (htab->stub_bfd, ADDIS_R2_R2 | PPC_HA (r2off), loc); + bfd_put_32 (htab->params->stub_bfd, + ADDIS_R2_R2 | PPC_HA (r2off), loc); loc += 4; } - bfd_put_32 (htab->stub_bfd, ADDI_R2_R2 | PPC_LO (r2off), loc); + bfd_put_32 (htab->params->stub_bfd, ADDI_R2_R2 | PPC_LO (r2off), loc); loc += 4; off -= size - 4; } - bfd_put_32 (htab->stub_bfd, B_DOT | (off & 0x3fffffc), loc); + bfd_put_32 (htab->params->stub_bfd, B_DOT | (off & 0x3fffffc), loc); if (off + (1 << 25) >= (bfd_vma) (1 << 26)) { @@ -10501,16 +10481,16 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) unsigned long symndx; struct ppc_link_hash_entry *h; - hashes = elf_sym_hashes (htab->stub_bfd); + hashes = elf_sym_hashes (htab->params->stub_bfd); if (hashes == NULL) { bfd_size_type hsize; hsize = (htab->stub_globals + 1) * sizeof (*hashes); - hashes = bfd_zalloc (htab->stub_bfd, hsize); + hashes = bfd_zalloc (htab->params->stub_bfd, hsize); if (hashes == NULL) return FALSE; - elf_sym_hashes (htab->stub_bfd) = hashes; + elf_sym_hashes (htab->params->stub_bfd) = hashes; htab->stub_globals = 1; } symndx = htab->stub_globals++; @@ -10637,14 +10617,17 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) if (PPC_HA (off) != 0) { size = 16; - bfd_put_32 (htab->stub_bfd, ADDIS_R11_R2 | PPC_HA (off), loc); + bfd_put_32 (htab->params->stub_bfd, + ADDIS_R11_R2 | PPC_HA (off), loc); loc += 4; - bfd_put_32 (htab->stub_bfd, LD_R12_0R11 | PPC_LO (off), loc); + bfd_put_32 (htab->params->stub_bfd, + LD_R12_0R11 | PPC_LO (off), loc); } else { size = 12; - bfd_put_32 (htab->stub_bfd, LD_R12_0R2 | PPC_LO (off), loc); + bfd_put_32 (htab->params->stub_bfd, + LD_R12_0R2 | PPC_LO (off), loc); } } else @@ -10657,36 +10640,40 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) return FALSE; } - bfd_put_32 (htab->stub_bfd, STD_R2_0R1 + STK_TOC (htab), loc); + bfd_put_32 (htab->params->stub_bfd, STD_R2_0R1 + STK_TOC (htab), loc); loc += 4; size = 16; if (PPC_HA (off) != 0) { size += 4; - bfd_put_32 (htab->stub_bfd, ADDIS_R11_R2 | PPC_HA (off), loc); + bfd_put_32 (htab->params->stub_bfd, + ADDIS_R11_R2 | PPC_HA (off), loc); loc += 4; - bfd_put_32 (htab->stub_bfd, LD_R12_0R11 | PPC_LO (off), loc); + bfd_put_32 (htab->params->stub_bfd, + LD_R12_0R11 | PPC_LO (off), loc); } else - bfd_put_32 (htab->stub_bfd, LD_R12_0R2 | PPC_LO (off), loc); + bfd_put_32 (htab->params->stub_bfd, LD_R12_0R2 | PPC_LO (off), loc); if (PPC_HA (r2off) != 0) { size += 4; loc += 4; - bfd_put_32 (htab->stub_bfd, ADDIS_R2_R2 | PPC_HA (r2off), loc); + bfd_put_32 (htab->params->stub_bfd, + ADDIS_R2_R2 | PPC_HA (r2off), loc); } if (PPC_LO (r2off) != 0) { size += 4; loc += 4; - bfd_put_32 (htab->stub_bfd, ADDI_R2_R2 | PPC_LO (r2off), loc); + bfd_put_32 (htab->params->stub_bfd, + ADDI_R2_R2 | PPC_LO (r2off), loc); } } loc += 4; - bfd_put_32 (htab->stub_bfd, MTCTR_R12, loc); + bfd_put_32 (htab->params->stub_bfd, MTCTR_R12, loc); loc += 4; - bfd_put_32 (htab->stub_bfd, BCTR, loc); + bfd_put_32 (htab->params->stub_bfd, BCTR, loc); break; case ppc_stub_plt_call: @@ -10760,7 +10747,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) return FALSE; } - if (htab->plt_stub_align != 0) + if (htab->params->plt_stub_align != 0) { unsigned pad = plt_stub_pad (htab, stub_entry, off); @@ -10775,7 +10762,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) r = get_relocs (stub_entry->stub_sec, ((PPC_HA (off) != 0) + (htab->opd_abi - ? 2 + (htab->plt_static_chain + ? 2 + (htab->params->plt_static_chain && PPC_HA (off + 16) == PPC_HA (off)) : 1))); if (r == NULL) @@ -10788,7 +10775,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) if (stub_entry->h != NULL && (stub_entry->h == htab->tls_get_addr_fd || stub_entry->h == htab->tls_get_addr) - && !htab->no_tls_get_addr_opt) + && !htab->params->no_tls_get_addr_opt) p = build_tls_get_addr_stub (htab, stub_entry, loc, off, r); else p = build_plt_stub (htab, stub_entry, loc, off, r); @@ -10802,7 +10789,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) stub_entry->stub_sec->size += size; - if (htab->emit_stub_syms) + if (htab->params->emit_stub_syms) { struct elf_link_hash_entry *h; size_t len1, len2; @@ -10880,14 +10867,14 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) - htab->stub_group[stub_entry->id_sec->id].toc_off); size = plt_stub_size (htab, stub_entry, off); - if (htab->plt_stub_align) + if (htab->params->plt_stub_align) size += plt_stub_pad (htab, stub_entry, off); if (info->emitrelocations) { stub_entry->stub_sec->reloc_count += ((PPC_HA (off) != 0) + (htab->opd_abi - ? 2 + (htab->plt_static_chain + ? 2 + (htab->params->plt_static_chain && PPC_HA (off + 16) == PPC_HA (off)) : 1)); stub_entry->stub_sec->flags |= SEC_RELOC; @@ -11010,10 +10997,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) 0 when no stubs will be needed, and 1 on success. */ int -ppc64_elf_setup_section_lists - (struct bfd_link_info *info, - asection *(*add_stub_section) (const char *, asection *), - void (*layout_sections_again) (void)) +ppc64_elf_setup_section_lists (struct bfd_link_info *info) { bfd *input_bfd; int top_id, top_index, id; @@ -11024,9 +11008,6 @@ ppc64_elf_setup_section_lists if (htab == NULL) return -1; - /* Stash our params away. */ - htab->add_stub_section = add_stub_section; - htab->layout_sections_again = layout_sections_again; /* Find the top input section id. */ for (input_bfd = info->input_bfds, top_id = 3; @@ -11363,7 +11344,7 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info) } if (done_something) - (*htab->layout_sections_again) (); + (*htab->params->layout_sections_again) (); /* Set up for second pass over toc sections to recalculate elf_gp on input sections. */ @@ -11850,9 +11831,7 @@ maybe_strip_output (struct bfd_link_info *info, asection *isec) instruction. */ bfd_boolean -ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size, - bfd_boolean plt_static_chain, int plt_thread_safe, - int plt_stub_align) +ppc64_elf_size_stubs (struct bfd_link_info *info) { bfd_size_type stub_group_size; bfd_boolean stubs_always_before_branch; @@ -11861,13 +11840,11 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size, if (htab == NULL) return FALSE; - htab->plt_static_chain = plt_static_chain; - htab->plt_stub_align = plt_stub_align; - if (plt_thread_safe == -1 && !info->executable) - plt_thread_safe = 1; + if (htab->params->plt_thread_safe == -1 && !info->executable) + htab->params->plt_thread_safe = 1; if (!htab->opd_abi) - plt_thread_safe = 0; - else if (plt_thread_safe == -1) + htab->params->plt_thread_safe = 0; + else if (htab->params->plt_thread_safe == -1) { static const char *const thread_starter[] = { @@ -11894,17 +11871,16 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size, struct elf_link_hash_entry *h; h = elf_link_hash_lookup (&htab->elf, thread_starter[i], FALSE, FALSE, TRUE); - plt_thread_safe = h != NULL && h->ref_regular; - if (plt_thread_safe) + htab->params->plt_thread_safe = h != NULL && h->ref_regular; + if (htab->params->plt_thread_safe) break; } } - htab->plt_thread_safe = plt_thread_safe; - stubs_always_before_branch = group_size < 0; - if (group_size < 0) - stub_group_size = -group_size; + stubs_always_before_branch = htab->params->group_size < 0; + if (htab->params->group_size < 0) + stub_group_size = -htab->params->group_size; else - stub_group_size = group_size; + stub_group_size = htab->params->group_size; group_sections (htab, stub_group_size, stubs_always_before_branch); @@ -12220,7 +12196,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size, /* We may have added some stubs. Find out the new size of the stub sections. */ - for (stub_sec = htab->stub_bfd->sections; + for (stub_sec = htab->params->stub_bfd->sections; stub_sec != NULL; stub_sec = stub_sec->next) if ((stub_sec->flags & SEC_LINKER_CREATED) == 0) @@ -12252,7 +12228,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size, { size_t size = 0, align; - for (stub_sec = htab->stub_bfd->sections; + for (stub_sec = htab->params->stub_bfd->sections; stub_sec != NULL; stub_sec = stub_sec->next) if ((stub_sec->flags & SEC_LINKER_CREATED) == 0) @@ -12269,15 +12245,16 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size, htab->glink_eh_frame->size = size; } - if (htab->plt_stub_align != 0) - for (stub_sec = htab->stub_bfd->sections; + if (htab->params->plt_stub_align != 0) + for (stub_sec = htab->params->stub_bfd->sections; stub_sec != NULL; stub_sec = stub_sec->next) if ((stub_sec->flags & SEC_LINKER_CREATED) == 0) - stub_sec->size = ((stub_sec->size + (1 << htab->plt_stub_align) - 1) - & (-1 << htab->plt_stub_align)); + stub_sec->size = ((stub_sec->size + + (1 << htab->params->plt_stub_align) - 1) + & (-1 << htab->params->plt_stub_align)); - for (stub_sec = htab->stub_bfd->sections; + for (stub_sec = htab->params->stub_bfd->sections; stub_sec != NULL; stub_sec = stub_sec->next) if ((stub_sec->flags & SEC_LINKER_CREATED) == 0 @@ -12292,7 +12269,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size, break; /* Ask the linker to do its stuff. */ - (*htab->layout_sections_again) (); + (*htab->params->layout_sections_again) (); } maybe_strip_output (info, htab->brlt); @@ -12444,8 +12421,7 @@ build_global_entry_stubs (struct elf_link_hash_entry *h, void *inf) hash table. This function is called via gldelf64ppc_finish. */ bfd_boolean -ppc64_elf_build_stubs (bfd_boolean emit_stub_syms, - struct bfd_link_info *info, +ppc64_elf_build_stubs (struct bfd_link_info *info, char **stats) { struct ppc_link_hash_table *htab = ppc_hash_table (info); @@ -12456,16 +12432,14 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms, if (htab == NULL) return FALSE; - htab->emit_stub_syms = emit_stub_syms; - /* Allocate memory to hold the linker stubs. */ - for (stub_sec = htab->stub_bfd->sections; + for (stub_sec = htab->params->stub_bfd->sections; stub_sec != NULL; stub_sec = stub_sec->next) if ((stub_sec->flags & SEC_LINKER_CREATED) == 0 && stub_sec->size != 0) { - stub_sec->contents = bfd_zalloc (htab->stub_bfd, stub_sec->size); + stub_sec->contents = bfd_zalloc (htab->params->stub_bfd, stub_sec->size); if (stub_sec->contents == NULL) return FALSE; /* We want to check that built size is the same as calculated @@ -12480,7 +12454,7 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms, bfd_vma plt0; /* Build the .glink plt call stub. */ - if (htab->emit_stub_syms) + if (htab->params->emit_stub_syms) { struct elf_link_hash_entry *h; h = elf_link_hash_lookup (&htab->elf, "__glink_PLTresolve", @@ -12641,7 +12615,7 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms, bfd_put_32 (htab->elf.dynobj, last_fde_len, p); p += sizeof (glink_eh_frame_cie); - for (stub_sec = htab->stub_bfd->sections; + for (stub_sec = htab->params->stub_bfd->sections; stub_sec != NULL; stub_sec = stub_sec->next) if ((stub_sec->flags & SEC_LINKER_CREATED) == 0) @@ -12737,15 +12711,16 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms, if (htab->relbrlt != NULL) htab->relbrlt->reloc_count = 0; - if (htab->plt_stub_align != 0) - for (stub_sec = htab->stub_bfd->sections; + if (htab->params->plt_stub_align != 0) + for (stub_sec = htab->params->stub_bfd->sections; stub_sec != NULL; stub_sec = stub_sec->next) if ((stub_sec->flags & SEC_LINKER_CREATED) == 0) - stub_sec->size = ((stub_sec->size + (1 << htab->plt_stub_align) - 1) - & (-1 << htab->plt_stub_align)); + stub_sec->size = ((stub_sec->size + + (1 << htab->params->plt_stub_align) - 1) + & (-1 << htab->params->plt_stub_align)); - for (stub_sec = htab->stub_bfd->sections; + for (stub_sec = htab->params->stub_bfd->sections; stub_sec != NULL; stub_sec = stub_sec->next) if ((stub_sec->flags & SEC_LINKER_CREATED) == 0) @@ -12899,7 +12874,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, return FALSE; /* Don't relocate stub sections. */ - if (input_section->owner == htab->stub_bfd) + if (input_section->owner == htab->params->stub_bfd) return TRUE; BFD_ASSERT (is_ppc64_elf (input_bfd)); @@ -13620,7 +13595,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, if (h != NULL && (h == htab->tls_get_addr_fd || h == htab->tls_get_addr) - && !htab->no_tls_get_addr_opt) + && !htab->params->no_tls_get_addr_opt) { /* Special stub used, leave nop alone. */ } diff --git a/bfd/elf64-ppc.h b/bfd/elf64-ppc.h index 06c655f..3a2299a 100644 --- a/bfd/elf64-ppc.h +++ b/bfd/elf64-ppc.h @@ -19,12 +19,50 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ +/* Used to pass info between ld and bfd. */ +struct ppc64_elf_params +{ + /* Linker stub bfd. */ + bfd *stub_bfd; + + /* Linker call-backs. */ + asection * (*add_stub_section) (const char *, asection *); + void (*layout_sections_again) (void); + + /* Maximum size of a group of input sections that can be handled by + one stub section. A value of +/-1 indicates the bfd back-end + should use a suitable default size. */ + bfd_signed_vma group_size; + + /* Whether to use a special call stub for __tls_get_addr. */ + int no_tls_get_addr_opt; + + /* Whether to allow multiple toc sections. */ + int no_multi_toc; + + /* Set if PLT call stubs should load r11. */ + int plt_static_chain; + + /* Set if PLT call stubs need to be thread safe on power7+. */ + int plt_thread_safe; + + /* Set if individual PLT call stubs should be aligned. */ + int plt_stub_align; + + /* Whether to canonicalize .opd so that there are no overlapping + .opd entries. */ + int non_overlapping_opd; + + /* Whether to emit symbols for stubs. */ + int emit_stub_syms; +}; + bfd_boolean ppc64_elf_init_stub_bfd - (bfd *, struct bfd_link_info *); + (struct bfd_link_info *, struct ppc64_elf_params *); bfd_boolean ppc64_elf_edit_opd - (struct bfd_link_info *, bfd_boolean); + (struct bfd_link_info *); asection *ppc64_elf_tls_setup - (struct bfd_link_info *, int, int *); + (struct bfd_link_info *); bfd_boolean ppc64_elf_tls_optimize (struct bfd_link_info *); bfd_boolean ppc64_elf_edit_toc @@ -32,10 +70,9 @@ bfd_boolean ppc64_elf_edit_toc bfd_boolean ppc64_elf_has_small_toc_reloc (asection *); bfd_vma ppc64_elf_set_toc - (struct bfd_link_info *, bfd *); +(struct bfd_link_info *, bfd *); int ppc64_elf_setup_section_lists - (struct bfd_link_info *, asection *(*) (const char *, asection *), - void (*) (void)); + (struct bfd_link_info *); void ppc64_elf_start_multitoc_partition (struct bfd_link_info *); bfd_boolean ppc64_elf_next_toc_section @@ -49,8 +86,8 @@ bfd_boolean ppc64_elf_check_init_fini bfd_boolean ppc64_elf_next_input_section (struct bfd_link_info *, asection *); bfd_boolean ppc64_elf_size_stubs -(struct bfd_link_info *, bfd_signed_vma, bfd_boolean, int, int); +(struct bfd_link_info *); bfd_boolean ppc64_elf_build_stubs - (bfd_boolean, struct bfd_link_info *, char **); + (struct bfd_link_info *, char **); void ppc64_elf_restore_symbols (struct bfd_link_info *info); diff --git a/ld/ChangeLog b/ld/ChangeLog index 38d81b0..1bd1c99 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,5 +1,10 @@ 2014-02-17 Alan Modra + * emultemps/ppc64elf.em (params): New static struct replacing + various other static vars. Adjust code throughout file. + +2014-02-17 Alan Modra + * emultempl/ppc32elf.em (ppc_after_open_output): Really enable ppc476 workaround for ld -r. diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em index c126297..56cd0af 100644 --- a/ld/emultempl/ppc64elf.em +++ b/ld/emultempl/ppc64elf.em @@ -31,6 +31,16 @@ fragment <the_bfd->flags |= BFD_LINKER_CREATED; ldlang_add_file (stub_file); - if (!ppc64_elf_init_stub_bfd (stub_file->the_bfd, &link_info)) + params.stub_bfd = stub_file->the_bfd; + if (!ppc64_elf_init_stub_bfd (&link_info, ¶ms)) einfo ("%F%P: can not init BFD: %E\n"); } @@ -256,10 +245,10 @@ ppc_before_allocation (void) if (stub_file != NULL) { if (!no_opd_opt - && !ppc64_elf_edit_opd (&link_info, non_overlapping_opd)) + && !ppc64_elf_edit_opd (&link_info)) einfo ("%X%P: can not edit %s: %E\n", "opd"); - if (ppc64_elf_tls_setup (&link_info, no_tls_get_addr_opt, &no_multi_toc) + if (ppc64_elf_tls_setup (&link_info) && !no_tls_opt) { /* Size the sections. This is premature, but we want to know the @@ -480,16 +469,14 @@ gld${EMULATION_NAME}_after_allocation (void) stubs. */ if (stub_file != NULL && !link_info.relocatable) { - int ret = ppc64_elf_setup_section_lists (&link_info, - &ppc_add_stub_section, - &ppc_layout_sections_again); + int ret = ppc64_elf_setup_section_lists (&link_info); if (ret < 0) einfo ("%X%P: can not size stub section: %E\n"); else if (ret > 0) { ppc64_elf_start_multitoc_partition (&link_info); - if (!no_multi_toc) + if (!params.no_multi_toc) { toc_section = bfd_get_section_by_name (link_info.output_bfd, ".got"); @@ -498,7 +485,7 @@ gld${EMULATION_NAME}_after_allocation (void) } if (ppc64_elf_layout_multitoc (&link_info) - && !no_multi_toc + && !params.no_multi_toc && toc_section != NULL) lang_for_each_statement (build_toc_list); @@ -510,9 +497,7 @@ gld${EMULATION_NAME}_after_allocation (void) einfo ("%P: .init/.fini fragments use differing TOC pointers\n"); /* Call into the BFD backend to do the real work. */ - if (!ppc64_elf_size_stubs (&link_info, group_size, - plt_static_chain, plt_thread_safe, - plt_stub_align)) + if (!ppc64_elf_size_stubs (&link_info)) einfo ("%X%P: can not size stub section: %E\n"); } } @@ -542,10 +527,9 @@ gld${EMULATION_NAME}_finish (void) char *msg = NULL; char *line, *endline; - if (emit_stub_syms < 0) - emit_stub_syms = 1; - if (!ppc64_elf_build_stubs (emit_stub_syms, &link_info, - config.stats ? &msg : NULL)) + if (params.emit_stub_syms < 0) + params.emit_stub_syms = 1; + if (!ppc64_elf_build_stubs (&link_info, config.stats ? &msg : NULL)) einfo ("%X%P: can not build stubs: %E\n"); fflush (stdout); @@ -766,26 +750,26 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}' case OPTION_STUBGROUP_SIZE: { const char *end; - group_size = bfd_scan_vma (optarg, &end, 0); + params.group_size = bfd_scan_vma (optarg, &end, 0); if (*end) einfo (_("%P%F: invalid number `%s'\''\n"), optarg); } break; case OPTION_PLT_STATIC_CHAIN: - plt_static_chain = 1; + params.plt_static_chain = 1; break; case OPTION_NO_PLT_STATIC_CHAIN: - plt_static_chain = 0; + params.plt_static_chain = 0; break; case OPTION_PLT_THREAD_SAFE: - plt_thread_safe = 1; + params.plt_thread_safe = 1; break; case OPTION_NO_PLT_THREAD_SAFE: - plt_thread_safe = 0; + params.plt_thread_safe = 0; break; case OPTION_PLT_ALIGN: @@ -806,11 +790,11 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}' break; case OPTION_STUBSYMS: - emit_stub_syms = 1; + params.emit_stub_syms = 1; break; case OPTION_NO_STUBSYMS: - emit_stub_syms = 0; + params.emit_stub_syms = 0; break; case OPTION_DOTSYMS: @@ -826,7 +810,7 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}' break; case OPTION_NO_TLS_GET_ADDR_OPT: - no_tls_get_addr_opt = 1; + params.no_tls_get_addr_opt = 1; break; case OPTION_NO_OPD_OPT: @@ -838,7 +822,7 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}' break; case OPTION_NO_MULTI_TOC: - no_multi_toc = 1; + params.no_multi_toc = 1; break; case OPTION_NO_TOC_SORT: @@ -846,17 +830,17 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}' break; case OPTION_NON_OVERLAPPING_OPD: - non_overlapping_opd = 1; + params.non_overlapping_opd = 1; break; case OPTION_TRADITIONAL_FORMAT: no_tls_opt = 1; - no_tls_get_addr_opt = 1; + params.no_tls_get_addr_opt = 1; no_opd_opt = 1; no_toc_opt = 1; - no_multi_toc = 1; + params.no_multi_toc = 1; no_toc_sort = 1; - plt_static_chain = 1; + params.plt_static_chain = 1; return FALSE; '