#define VXWORKS_PLT_NON_JMP_SLOT_RELOCS 3
/* The number of relocations in the PLTResolve slot. */
#define VXWORKS_PLTRESOLVE_RELOCS 2
-/* The number of relocations in the PLTResolve slot when when creating
+/* The number of relocations in the PLTResolve slot when creating
a shared library. */
#define VXWORKS_PLTRESOLVE_RELOCS_SHLIB 0
bfd_vma glink_offset;
};
-/* Of those relocs that might be copied as dynamic relocs, this function
- selects those that must be copied when linking a shared library,
- even when the symbol is local. */
+/* Of those relocs that might be copied as dynamic relocs, this
+ function selects those that must be copied when linking a shared
+ library or PIE, even when the symbol is local. */
static int
must_be_dyn_reloc (struct bfd_link_info *info,
switch (r_type)
{
default:
+ /* Only relative relocs can be resolved when the object load
+ address isn't fixed. DTPREL32 is excluded because the
+ dynamic linker needs to differentiate global dynamic from
+ local dynamic __tls_index pairs when PPC_OPT_TLS is set. */
return 1;
case R_PPC_REL24:
case R_PPC_TPREL16_LO:
case R_PPC_TPREL16_HI:
case R_PPC_TPREL16_HA:
- return !bfd_link_executable (info);
+ /* These relocations are relative but in a shared library the
+ linker doesn't know the thread pointer base. */
+ return bfd_link_dll (info);
}
}
unsigned int local_ifunc_resolver:1;
unsigned int maybe_local_ifunc_resolver:1;
+ /* Set if tls optimization is enabled. */
+ unsigned int do_tls_opt:1;
+
/* The size of PLT entries. */
int plt_entry_size;
/* The distance between adjacent PLT slots. */
case R_PPC_GOT_TPREL16_LO:
case R_PPC_GOT_TPREL16_HI:
case R_PPC_GOT_TPREL16_HA:
- if (bfd_link_pic (info))
+ if (bfd_link_dll (info))
info->flags |= DF_STATIC_TLS;
tls_type = TLS_TLS | TLS_TPREL;
goto dogottls;
return FALSE;
break;
- /* We shouldn't really be seeing these. */
+ /* We shouldn't really be seeing TPREL32. */
case R_PPC_TPREL32:
case R_PPC_TPREL16:
case R_PPC_TPREL16_LO:
case R_PPC_TPREL16_HI:
case R_PPC_TPREL16_HA:
- if (bfd_link_pic (info))
+ if (bfd_link_dll (info))
info->flags |= DF_STATIC_TLS;
goto dodyn;
symtab_hdr->contents = (unsigned char *) locsyms;
}
}
+ htab->do_tls_opt = 1;
return TRUE;
}
\f
return where;
}
-/* If H is undefined weak, make it dynamic if that makes sense. */
+/* If H is undefined, make it dynamic if that makes sense. */
static bfd_boolean
-ensure_undefweak_dynamic (struct bfd_link_info *info,
- struct elf_link_hash_entry *h)
+ensure_undef_dynamic (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h)
{
struct elf_link_hash_table *htab = elf_hash_table (info);
if (htab->dynamic_sections_created
- && info->dynamic_undefined_weak != 0
- && h->root.type == bfd_link_hash_undefweak
+ && ((info->dynamic_undefined_weak != 0
+ && h->root.type == bfd_link_hash_undefweak)
+ || h->root.type == bfd_link_hash_undefined)
&& h->dynindx == -1
&& !h->forced_local
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
{
unsigned int need;
- /* Make sure this symbol is output as a dynamic symbol.
- Undefined weak syms won't yet be marked as dynamic. */
- if (!ensure_undefweak_dynamic (info, &eh->elf))
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (!ensure_undef_dynamic (info, &eh->elf))
return FALSE;
need = 0;
if (eh->dyn_relocs != NULL)
{
- /* Make sure undefined weak symbols are output as a dynamic
- symbol in PIEs. */
- if (!ensure_undefweak_dynamic (info, h))
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (!ensure_undef_dynamic (info, h))
return FALSE;
}
}
&& eh->has_addr16_lo
&& htab->params->pic_fixup > 0))
{
- /* Make sure this symbol is output as a dynamic symbol.
- Undefined weak syms won't yet be marked as dynamic. */
- if (!ensure_undefweak_dynamic (info, h))
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (!ensure_undef_dynamic (info, h))
return FALSE;
if (h->dynindx == -1)
}
addend = rel->r_addend;
- tls_type = 0;
howto = NULL;
if (r_type < R_PPC_max)
howto = ppc_elf_howto_table[r_type];
+
+ switch (r_type)
+ {
+ default:
+ break;
+
+ case R_PPC_TPREL16_HA:
+ if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
+ {
+ bfd_byte *p = contents + (rel->r_offset & ~3);
+ unsigned int insn = bfd_get_32 (input_bfd, p);
+ if ((insn & ((0x3f << 26) | 0x1f << 16))
+ != ((15u << 26) | (2 << 16)) /* addis rt,2,imm */)
+ /* xgettext:c-format */
+ info->callbacks->minfo
+ (_("%H: warning: %s unexpected insn %#x.\n"),
+ input_bfd, input_section, rel->r_offset, howto->name, insn);
+ else
+ bfd_put_32 (input_bfd, NOP, p);
+ }
+ break;
+
+ case R_PPC_TPREL16_LO:
+ if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
+ {
+ bfd_byte *p = contents + (rel->r_offset & ~3);
+ unsigned int insn = bfd_get_32 (input_bfd, p);
+ insn &= ~(0x1f << 16);
+ insn |= 2 << 16;
+ bfd_put_32 (input_bfd, insn, p);
+ }
+ break;
+ }
+
+ tls_type = 0;
switch (r_type)
{
default:
if (htab->elf.tls_sec != NULL)
addend -= htab->elf.tls_sec->vma + TP_OFFSET;
/* The TPREL16 relocs shouldn't really be used in shared
- libs as they will result in DT_TEXTREL being set, but
- support them anyway. */
+ libs or with non-local symbols as that will result in
+ DT_TEXTREL being set, but support them anyway. */
goto dodyn;
case R_PPC_TPREL32: