int plt_slot_size;
/* The size of the first PLT entry. */
int plt_initial_entry_size;
-
- /* Small local sym cache. */
- struct sym_cache sym_cache;
};
/* Rename some of the generic section flags to better document how they
/* Get the PPC ELF linker hash table from a link_info structure. */
#define ppc_elf_hash_table(p) \
- (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
- == PPC32_ELF_DATA ? ((struct ppc_elf_link_hash_table *) ((p)->hash)) : NULL)
+ ((is_elf_hash_table ((p)->hash) \
+ && elf_hash_table_id (elf_hash_table (p)) == PPC32_ELF_DATA) \
+ ? (struct ppc_elf_link_hash_table *) (p)->hash : NULL)
/* Create an entry in a PPC ELF linker hash table. */
htab = ppc_elf_hash_table (info);
if (htab->sbss == NULL)
{
- flagword flags = SEC_IS_COMMON | SEC_LINKER_CREATED;
+ flagword flags = SEC_IS_COMMON | SEC_SMALL_DATA | SEC_LINKER_CREATED;
if (!htab->elf.dynobj)
htab->elf.dynobj = abfd;
ifunc = NULL;
if (h == NULL && htab->elf.target_os != is_vxworks)
{
- Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+ Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
abfd, r_symndx);
if (isym == NULL)
return FALSE;
return FALSE;
break;
+ case R_PPC_TPREL16_HI:
+ case R_PPC_TPREL16_HA:
+ sec->has_tls_reloc = 1;
+ /* Fall through. */
/* 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_dll (info))
info->flags |= DF_STATIC_TLS;
goto dodyn;
asection *s;
Elf_Internal_Sym *isym;
- isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+ isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
abfd, r_symndx);
if (isym == NULL)
return FALSE;
void *vpp;
Elf_Internal_Sym *isym;
- isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+ isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
abfd, r_symndx);
if (isym == NULL)
return FALSE;
if (htab == NULL)
return FALSE;
+ htab->do_tls_opt = 1;
+
/* Make two passes through the relocs. First time check that tls
relocs involved in setting up a tls_get_addr call are indeed
followed by such a call. If they are not, don't do any tls
tls_clear = 0;
break;
+ case R_PPC_TPREL16_HA:
+ if (pass == 0)
+ {
+ unsigned char buf[4];
+ unsigned int insn;
+ bfd_vma off = rel->r_offset & ~3;
+ if (!bfd_get_section_contents (ibfd, sec, buf,
+ off, 4))
+ {
+ if (elf_section_data (sec)->relocs != relstart)
+ free (relstart);
+ return FALSE;
+ }
+ insn = bfd_get_32 (ibfd, buf);
+ /* addis rt,2,imm */
+ if ((insn & ((0x3fu << 26) | 0x1f << 16))
+ != ((15u << 26) | (2 << 16)))
+ {
+ /* xgettext:c-format */
+ info->callbacks->minfo
+ (_("%H: warning: %s unexpected insn %#x.\n"),
+ ibfd, sec, off, "R_PPC_TPREL16_HA", insn);
+ htab->do_tls_opt = 0;
+ }
+ }
+ continue;
+
+ case R_PPC_TPREL16_HI:
+ htab->do_tls_opt = 0;
+ continue;
+
default:
continue;
}
free (relstart);
}
}
- htab->do_tls_opt = 1;
return TRUE;
}
\f
#define add_dynamic_entry(TAG, VAL) \
_bfd_elf_add_dynamic_entry (info, TAG, VAL)
- if (bfd_link_executable (info))
- {
- if (!add_dynamic_entry (DT_DEBUG, 0))
- return FALSE;
- }
-
- if (htab->elf.splt != NULL && htab->elf.splt->size != 0)
- {
- if (!add_dynamic_entry (DT_PLTGOT, 0)
- || !add_dynamic_entry (DT_PLTRELSZ, 0)
- || !add_dynamic_entry (DT_PLTREL, DT_RELA)
- || !add_dynamic_entry (DT_JMPREL, 0))
- return FALSE;
- }
+ if (!_bfd_elf_maybe_vxworks_add_dynamic_tags (output_bfd, info,
+ relocs))
+ return FALSE;
if (htab->plt_type == PLT_NEW
&& htab->glink != NULL
&& !add_dynamic_entry (DT_PPC_OPT, PPC_OPT_TLS))
return FALSE;
}
-
- if (relocs)
- {
- if (!add_dynamic_entry (DT_RELA, 0)
- || !add_dynamic_entry (DT_RELASZ, 0)
- || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
- return FALSE;
- }
-
- /* If any dynamic relocs apply to a read-only section, then we
- need a DT_TEXTREL entry. */
- if ((info->flags & DF_TEXTREL) == 0)
- elf_link_hash_traverse (elf_hash_table (info),
- _bfd_elf_maybe_set_textrel,
- info);
-
- if ((info->flags & DF_TEXTREL) != 0)
- {
- if (!add_dynamic_entry (DT_TEXTREL, 0))
- return FALSE;
- }
- if (htab->elf.target_os == is_vxworks
- && !elf_vxworks_add_dynamic_entries (output_bfd, info))
- return FALSE;
}
#undef add_dynamic_entry
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 & ((0x3fu << 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)
{
goto copy_reloc;
}
+ 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);
+ 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;
+ }
+
switch (r_type)
{
default: