From 33c0ec9de7564cdf93754037b2a568dbd848f3c9 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Mon, 8 Feb 2010 13:50:17 +0000 Subject: [PATCH] bfd/ * elf64-ppc.c (struct ppc_link_hash_table): Add do_multi_toc. (has_small_toc_reloc): Define. (ppc64_elf_check_relocs): Set the above flags. (ppc64_elf_edit_opd): Delete obfd param. (ppc64_elf_tls_optimize): Likewise. (ppc64_elf_edit_toc): Likewise. (ppc64_elf_tls_setup): Likewise. Add no_multi_toc param. * elf64-ppc.h: Update prototypes. ld/ * emultempl/ppc64elf.em (ppc_before_allocation): Update for changed function parameters. --- bfd/ChangeLog | 11 +++++++++++ bfd/elf64-ppc.c | 42 ++++++++++++++++++++++++++++++++---------- bfd/elf64-ppc.h | 8 ++++---- ld/ChangeLog | 5 +++++ ld/emultempl/ppc64elf.em | 10 ++++------ 5 files changed, 56 insertions(+), 20 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 1e09853..00f4854 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +2010-02-09 Alan Modra + + * elf64-ppc.c (struct ppc_link_hash_table): Add do_multi_toc. + (has_small_toc_reloc): Define. + (ppc64_elf_check_relocs): Set the above flags. + (ppc64_elf_edit_opd): Delete obfd param. + (ppc64_elf_tls_optimize): Likewise. + (ppc64_elf_edit_toc): Likewise. + (ppc64_elf_tls_setup): Likewise. Add no_multi_toc param. + * elf64-ppc.h: Update prototypes. + 2010-02-08 Alan Modra * section.c (struct bfd_section): Delete has_tls_reloc, diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 37701f2..494abed 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -3781,6 +3781,7 @@ struct ppc_link_hash_table 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; unsigned int second_toc_pass:1; @@ -3809,6 +3810,10 @@ struct ppc_link_hash_table /* Nonzero if this section has any toc or got relocs. */ #define has_toc_reloc sec_flg2 +/* Nonzero if this section has small toc/got relocs, ie. that expect + the reloc to be in the range -32768 to 32767. */ +#define has_small_toc_reloc sec_flg3 + /* Nonzero if this section has a call to another section that uses the toc or got. */ #define makes_toc_func_call sec_flg4 @@ -5010,6 +5015,17 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_PPC64_GOT16_LO_DS: /* This symbol requires a global offset table entry. */ sec->has_toc_reloc = 1; + if (r_type == R_PPC64_GOT_TLSLD16 + || r_type == R_PPC64_GOT_TLSGD16 + || r_type == R_PPC64_GOT_TPREL16_DS + || r_type == R_PPC64_GOT_DTPREL16_DS + || r_type == R_PPC64_GOT16 + || r_type == R_PPC64_GOT16_DS) + { + htab->do_multi_toc = 1; + sec->has_small_toc_reloc = 1; + } + if (ppc64_elf_tdata (abfd)->got == NULL && !create_got_section (abfd, info)) return FALSE; @@ -5106,10 +5122,12 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, break; case R_PPC64_TOC16: + case R_PPC64_TOC16_DS: + htab->do_multi_toc = 1; + sec->has_small_toc_reloc = 1; case R_PPC64_TOC16_LO: case R_PPC64_TOC16_HI: case R_PPC64_TOC16_HA: - case R_PPC64_TOC16_DS: case R_PPC64_TOC16_LO_DS: sec->has_toc_reloc = 1; break; @@ -6883,8 +6901,7 @@ dec_dynrel_count (bfd_vma r_info, applications. */ bfd_boolean -ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info, - bfd_boolean non_overlapping) +ppc64_elf_edit_opd (struct bfd_link_info *info, bfd_boolean non_overlapping) { bfd *ibfd; bfd_boolean some_edited = FALSE; @@ -7054,7 +7071,7 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info, new_contents = NULL; amt = sec->size * sizeof (long) / 8; opd = &ppc64_elf_section_data (sec)->u.opd; - opd->adjust = bfd_zalloc (obfd, amt); + opd->adjust = bfd_zalloc (sec->owner, amt); if (opd->adjust == NULL) return FALSE; ppc64_elf_section_data (sec)->sec_type = sec_opd; @@ -7285,9 +7302,9 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info, /* Set htab->tls_get_addr and call the generic ELF tls_setup function. */ asection * -ppc64_elf_tls_setup (bfd *obfd, - struct bfd_link_info *info, - int no_tls_get_addr_opt) +ppc64_elf_tls_setup (struct bfd_link_info *info, + int no_tls_get_addr_opt, + int *no_multi_toc) { struct ppc_link_hash_table *htab; @@ -7295,6 +7312,11 @@ ppc64_elf_tls_setup (bfd *obfd, if (htab == NULL) return NULL; + if (*no_multi_toc) + htab->do_multi_toc = 0; + else if (!htab->do_multi_toc) + *no_multi_toc = 1; + htab->tls_get_addr = ((struct ppc_link_hash_entry *) elf_link_hash_lookup (&htab->elf, ".__tls_get_addr", FALSE, FALSE, TRUE)); @@ -7375,7 +7397,7 @@ ppc64_elf_tls_setup (bfd *obfd, no_tls_get_addr_opt = TRUE; } htab->no_tls_get_addr_opt = no_tls_get_addr_opt; - return _bfd_elf_tls_setup (obfd, info); + return _bfd_elf_tls_setup (info->output_bfd, info); } /* Return TRUE iff REL is a branch reloc with a global symbol matching @@ -7412,7 +7434,7 @@ branch_reloc_hash_match (const bfd *ibfd, dynamic relocations. */ bfd_boolean -ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) +ppc64_elf_tls_optimize (struct bfd_link_info *info) { bfd *ibfd; asection *sec; @@ -7852,7 +7874,7 @@ adjust_toc_syms (struct elf_link_hash_entry *h, void *inf) unused .toc entries. */ bfd_boolean -ppc64_elf_edit_toc (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) +ppc64_elf_edit_toc (struct bfd_link_info *info) { bfd *ibfd; struct adjust_toc_info toc_inf; diff --git a/bfd/elf64-ppc.h b/bfd/elf64-ppc.h index 79bb1b3..9f69e06 100644 --- a/bfd/elf64-ppc.h +++ b/bfd/elf64-ppc.h @@ -22,13 +22,13 @@ void ppc64_elf_init_stub_bfd (bfd *, struct bfd_link_info *); bfd_boolean ppc64_elf_edit_opd - (bfd *, struct bfd_link_info *, bfd_boolean); + (struct bfd_link_info *, bfd_boolean); asection *ppc64_elf_tls_setup - (bfd *, struct bfd_link_info *, int); + (struct bfd_link_info *, int, int *); bfd_boolean ppc64_elf_tls_optimize - (bfd *, struct bfd_link_info *); + (struct bfd_link_info *); bfd_boolean ppc64_elf_edit_toc - (bfd *, struct bfd_link_info *); + (struct bfd_link_info *); bfd_vma ppc64_elf_toc (bfd *); int ppc64_elf_setup_section_lists diff --git a/ld/ChangeLog b/ld/ChangeLog index a6c4763..f78771a 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,8 @@ +2010-02-09 Alan Modra + + * emultempl/ppc64elf.em (ppc_before_allocation): Update for changed + function parameters. + 2010-02-05 Nick Clifton * configure.in (ALL_LIBGUAS): Add bg. diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em index 9532b29..2e6c805 100644 --- a/ld/emultempl/ppc64elf.em +++ b/ld/emultempl/ppc64elf.em @@ -103,12 +103,10 @@ ppc_before_allocation (void) if (stub_file != NULL) { if (!no_opd_opt - && !ppc64_elf_edit_opd (link_info.output_bfd, &link_info, - non_overlapping_opd)) + && !ppc64_elf_edit_opd (&link_info, non_overlapping_opd)) einfo ("%X%P: can not edit %s %E\n", "opd"); - if (ppc64_elf_tls_setup (link_info.output_bfd, &link_info, - no_tls_get_addr_opt) + if (ppc64_elf_tls_setup (&link_info, no_tls_get_addr_opt, &no_multi_toc) && !no_tls_opt) { /* Size the sections. This is premature, but we want to know the @@ -117,7 +115,7 @@ ppc_before_allocation (void) expld.dataseg.phase = exp_dataseg_none; one_lang_size_sections_pass (NULL, TRUE); - if (!ppc64_elf_tls_optimize (link_info.output_bfd, &link_info)) + if (!ppc64_elf_tls_optimize (&link_info)) einfo ("%X%P: TLS problem %E\n"); /* We must not cache anything from the preliminary sizing. */ @@ -126,7 +124,7 @@ ppc_before_allocation (void) if (!no_toc_opt && !link_info.relocatable - && !ppc64_elf_edit_toc (link_info.output_bfd, &link_info)) + && !ppc64_elf_edit_toc (&link_info)) einfo ("%X%P: can not edit %s %E\n", "toc"); } -- 2.7.4