#include "elf64-ppc.h"
#include "dwarf2.h"
+/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1. */
+#define OCTETS_PER_BYTE(ABFD, SEC) 1
+
static bfd_reloc_status_type ppc64_elf_ha_reloc
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
static bfd_reloc_status_type ppc64_elf_branch_reloc
+ input_section->output_section->vma);
value = (bfd_signed_vma) value >> 16;
- octets = reloc_entry->address * bfd_octets_per_byte (abfd);
+ octets = reloc_entry->address * OCTETS_PER_BYTE (abfd, input_section);
insn = bfd_get_32 (abfd, (bfd_byte *) data + octets);
insn &= ~0x1fffc1;
insn |= (value & 0xffc1) | ((value & 0x3e) << 15);
return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
input_section, output_bfd, error_message);
- octets = reloc_entry->address * bfd_octets_per_byte (abfd);
+ octets = reloc_entry->address * OCTETS_PER_BYTE (abfd, input_section);
insn = bfd_get_32 (abfd, (bfd_byte *) data + octets);
insn &= ~(0x01 << 21);
r_type = reloc_entry->howto->type;
if (TOCstart == 0)
TOCstart = ppc64_elf_set_toc (NULL, input_section->output_section->owner);
- octets = reloc_entry->address * bfd_octets_per_byte (abfd);
+ octets = reloc_entry->address * OCTETS_PER_BYTE (abfd, input_section);
bfd_put_64 (abfd, TOCstart + TOC_BASE_OFF, (bfd_byte *) data + octets);
return bfd_reloc_ok;
}
if ((a->flags & BSF_DYNAMIC) == 0 && (b->flags & BSF_DYNAMIC) != 0)
return 1;
- return a > b;
+ /* Finally, sort on where the symbol is in memory. The symbols will
+ be in at most two malloc'd blocks, one for static syms, one for
+ dynamic syms, and we distinguish the two blocks above by testing
+ BSF_DYNAMIC. Since we are sorting the symbol pointers which were
+ originally in the same order as the symbols (and we're not
+ sorting the symbols themselves), this ensures a stable sort. */
+ if (a < b)
+ return -1;
+ if (a > b)
+ return 1;
+ return 0;
}
/* Search SYMS for a symbol of the given VALUE. */
/* Nonzero if this section has TLS related relocations. */
#define has_tls_reloc sec_flg0
-/* Nonzero if this section has an old-style call to __tls_get_addr. */
-#define has_tls_get_addr_call sec_flg1
+/* Nonzero if this section has a call to __tls_get_addr lacking marker
+ relocations. */
+#define nomark_tls_get_addr sec_flg1
/* Nonzero if this section has any toc or got relocs. */
#define has_toc_reloc sec_flg2
;
else
/* Mark this section as having an old-style call. */
- sec->has_tls_get_addr_call = 1;
+ sec->nomark_tls_get_addr = 1;
}
plt_list = &h->plt.plist;
}
s = elf_link_hash_lookup (&htab->elf, buf, TRUE, TRUE, FALSE);
if (s == NULL)
return FALSE;
- if (s->root.type == bfd_link_hash_new
- || (s->root.type = bfd_link_hash_defined
- && s->root.u.def.section == stub_sec))
+ if (s->root.type == bfd_link_hash_new)
{
s->root.type = bfd_link_hash_defined;
s->root.u.def.section = stub_sec;
setup insn. If we don't find matching arg setup
relocs, don't do any tls optimization. */
if (pass == 0
- && sec->has_tls_get_addr_call
+ && sec->nomark_tls_get_addr
&& h != NULL
&& (h == &htab->tls_get_addr->elf
|| h == &htab->tls_get_addr_fd->elf)
}
continue;
- case R_PPC64_TLSGD:
case R_PPC64_TLSLD:
+ if (!is_local)
+ continue;
+ /* Fall through. */
+ case R_PPC64_TLSGD:
if (rel + 1 < relend
&& is_plt_seq_reloc (ELF64_R_TYPE (rel[1].r_info)))
{
if (pass == 0)
{
if (!expecting_tls_get_addr
- || !sec->has_tls_get_addr_call)
+ || !sec->nomark_tls_get_addr)
continue;
if (rel + 1 < relend
Disable optimization in this case. */
if ((tls_clear & (TLS_GD | TLS_LD)) != 0
&& (tls_set & TLS_EXPLICIT) == 0
- && !sec->has_tls_get_addr_call
+ && !sec->nomark_tls_get_addr
&& ((*tls_mask & (TLS_TLS | TLS_MARK))
!= (TLS_TLS | TLS_MARK)))
continue;
- if (expecting_tls_get_addr)
+ if (expecting_tls_get_addr == 1 + !sec->nomark_tls_get_addr)
{
struct plt_entry *ent = NULL;
htab->elf.irelplt->size += rel_size;
htab->got_reli_size += rel_size;
}
- else if (bfd_link_dll (info))
+ else if (bfd_link_pic (info)
+ && !(ent->tls_type != 0
+ && bfd_link_executable (info)))
{
asection *srel = ppc64_elf_tdata (ibfd)->relgot;
srel->size += rel_size;
stays with its arg setup insns, ie. that the next
reloc is the __tls_get_addr call associated with
the current reloc. Edit both insns. */
- if (input_section->has_tls_get_addr_call
+ if (input_section->nomark_tls_get_addr
&& rel + 1 < relend
&& branch_reloc_hash_match (input_bfd, rel + 1,
htab->tls_get_addr,