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;
/* 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
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;
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;
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;
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;
/* 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;
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));
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
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;
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;
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
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
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. */
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");
}