case 268: /* Linux/PPC. */
/* pr_cursig */
- elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
+ elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12);
/* pr_pid */
- elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24);
+ elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 24);
/* pr_reg */
offset = 72;
return FALSE;
case 128: /* Linux/PPC elf_prpsinfo. */
- elf_tdata (abfd)->core_pid
+ elf_tdata (abfd)->core->pid
= bfd_get_32 (abfd, note->descdata + 16);
- elf_tdata (abfd)->core_program
+ elf_tdata (abfd)->core->program
= _bfd_elfcore_strndup (abfd, note->descdata + 32, 16);
- elf_tdata (abfd)->core_command
+ elf_tdata (abfd)->core->command
= _bfd_elfcore_strndup (abfd, note->descdata + 48, 80);
}
implementations, so strip it off if it exists. */
{
- char *command = elf_tdata (abfd)->core_command;
+ char *command = elf_tdata (abfd)->core->command;
int n = strlen (command);
if (0 < n && command[n - 1] == ' ')
If we find that case, we split the segment.
We maintain the original output section order. */
- for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+ for (m = elf_seg_map (abfd); m != NULL; m = m->next)
{
if (m->count == 0)
continue;
shared lib. */
#define ELIMINATE_COPY_RELOCS 1
+/* Used to track dynamic relocations for local symbols. */
+struct ppc_dyn_relocs
+{
+ struct ppc_dyn_relocs *next;
+
+ /* The input section of the reloc. */
+ asection *sec;
+
+ /* Total number of relocs copied for the input section. */
+ unsigned int count : 31;
+
+ /* Whether this entry is for STT_GNU_IFUNC symbols. */
+ unsigned int ifunc : 1;
+};
+
/* PPC ELF linker hash entry. */
struct ppc_elf_link_hash_entry
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ /* PR15323, ref flags aren't set for references in the same
+ object. */
+ h->root.non_ir_ref = 1;
}
/* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got.
if (isym == NULL)
return FALSE;
- if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC
- && (!info->shared
- || is_branch_reloc (r_type)))
+ if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
{
struct plt_entry **ifunc;
- bfd_vma addend;
+ /* Set PLT_IFUNC flag for this sym, no GOT entry yet. */
ifunc = update_local_sym_info (abfd, symtab_hdr, r_symndx,
PLT_IFUNC);
if (ifunc == NULL)
/* STT_GNU_IFUNC symbols must have a PLT entry;
In a non-pie executable even when there are
no plt calls. */
- addend = 0;
- if (r_type == R_PPC_PLTREL24)
+ if (!info->shared
+ || is_branch_reloc (r_type))
{
- ppc_elf_tdata (abfd)->makes_plt_call = 1;
- if (info->shared)
- addend = rel->r_addend;
+ bfd_vma addend = 0;
+ if (r_type == R_PPC_PLTREL24)
+ {
+ ppc_elf_tdata (abfd)->makes_plt_call = 1;
+ if (info->shared)
+ addend = rel->r_addend;
+ }
+ if (!update_plt_info (abfd, ifunc, got2, addend))
+ return FALSE;
}
- if (!update_plt_info (abfd, ifunc, got2, addend))
- return FALSE;
}
}
if ((info->shared
&& (must_be_dyn_reloc (info, r_type)
|| (h != NULL
- && (! info->symbolic
+ && (!SYMBOLIC_BIND (info, h)
|| h->root.type == bfd_link_hash_defweak
|| !h->def_regular))))
|| (ELIMINATE_COPY_RELOCS
&& (h->root.type == bfd_link_hash_defweak
|| !h->def_regular)))
{
- struct elf_dyn_relocs *p;
- struct elf_dyn_relocs **rel_head;
-
#ifdef DEBUG
fprintf (stderr,
"ppc_elf_check_relocs needs to "
relocations we need for this symbol. */
if (h != NULL)
{
+ struct elf_dyn_relocs *p;
+ struct elf_dyn_relocs **rel_head;
+
rel_head = &ppc_elf_hash_entry (h)->dyn_relocs;
+ p = *rel_head;
+ if (p == NULL || p->sec != sec)
+ {
+ p = bfd_alloc (htab->elf.dynobj, sizeof *p);
+ if (p == NULL)
+ return FALSE;
+ p->next = *rel_head;
+ *rel_head = p;
+ p->sec = sec;
+ p->count = 0;
+ p->pc_count = 0;
+ }
+ p->count += 1;
+ if (!must_be_dyn_reloc (info, r_type))
+ p->pc_count += 1;
}
else
{
/* Track dynamic relocs needed for local syms too.
We really need local syms available to do this
easily. Oh well. */
+ struct ppc_dyn_relocs *p;
+ struct ppc_dyn_relocs **rel_head;
+ bfd_boolean is_ifunc;
asection *s;
void *vpp;
Elf_Internal_Sym *isym;
s = sec;
vpp = &elf_section_data (s)->local_dynrel;
- rel_head = (struct elf_dyn_relocs **) vpp;
- }
-
- p = *rel_head;
- if (p == NULL || p->sec != sec)
- {
- p = bfd_alloc (htab->elf.dynobj, sizeof *p);
- if (p == NULL)
- return FALSE;
- p->next = *rel_head;
- *rel_head = p;
- p->sec = sec;
- p->count = 0;
- p->pc_count = 0;
+ rel_head = (struct ppc_dyn_relocs **) vpp;
+ is_ifunc = ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC;
+ p = *rel_head;
+ if (p != NULL && p->sec == sec && p->ifunc != is_ifunc)
+ p = p->next;
+ if (p == NULL || p->sec != sec || p->ifunc != is_ifunc)
+ {
+ p = bfd_alloc (htab->elf.dynobj, sizeof *p);
+ if (p == NULL)
+ return FALSE;
+ p->next = *rel_head;
+ *rel_head = p;
+ p->sec = sec;
+ p->ifunc = is_ifunc;
+ p->count = 0;
+ }
+ p->count += 1;
}
-
- p->count += 1;
- if (!must_be_dyn_reloc (info, r_type))
- p->pc_count += 1;
}
break;
|| eh->elf.root.type != bfd_link_hash_undefweak))
{
asection *rsec = htab->relgot;
+
+ if (eh->elf.type == STT_GNU_IFUNC)
+ rsec = htab->reliplt;
/* All the entries we allocated need relocs.
Except LD only needs one. */
if ((eh->tls_mask & TLS_LD) != 0
for (p = eh->dyn_relocs; p != NULL; p = p->next)
{
asection *sreloc = elf_section_data (p->sec)->sreloc;
- if (!htab->elf.dynamic_sections_created)
+ if (eh->elf.type == STT_GNU_IFUNC)
sreloc = htab->reliplt;
sreloc->size += p->count * sizeof (Elf32_External_Rela);
}
for (s = ibfd->sections; s != NULL; s = s->next)
{
- struct elf_dyn_relocs *p;
+ struct ppc_dyn_relocs *p;
- for (p = ((struct elf_dyn_relocs *)
+ for (p = ((struct ppc_dyn_relocs *)
elf_section_data (s)->local_dynrel);
p != NULL;
p = p->next)
else if (p->count != 0)
{
asection *sreloc = elf_section_data (p->sec)->sreloc;
- if (!htab->elf.dynamic_sections_created)
+ if (p->ifunc)
sreloc = htab->reliplt;
sreloc->size += p->count * sizeof (Elf32_External_Rela);
if ((p->sec->output_section->flags
{
*local_got = allocate_got (htab, need);
if (info->shared)
- htab->relgot->size += (need
- * (sizeof (Elf32_External_Rela) / 4));
+ {
+ asection *srel = htab->relgot;
+ if ((*lgot_masks & PLT_IFUNC) != 0)
+ srel = htab->reliplt;
+ srel->size += need * (sizeof (Elf32_External_Rela) / 4);
+ }
}
}
else
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
Elf_Internal_Rela outrel;
- asection *got2, *sreloc = NULL;
+ asection *got2;
bfd_vma *local_got_offsets;
bfd_boolean ret = TRUE;
bfd_vma d_offset = (bfd_big_endian (output_bfd) ? 2 : 0);
{
if (got2 != NULL
&& r_type == R_PPC_PLTREL24
- && rel->r_addend >= 32768)
+ && rel->r_addend != 0)
{
/* R_PPC_PLTREL24 is rather special. If non-zero, the
addend specifies the GOT pointer offset within .got2. */
asection *rsec = htab->relgot;
bfd_byte * loc;
+ if (ifunc != NULL)
+ rsec = htab->reliplt;
outrel.r_offset = (htab->got->output_section->vma
+ htab->got->output_offset
+ off);
&& !h->def_regular))
{
int skip;
- bfd_byte * loc;
+ bfd_byte *loc;
+ asection *sreloc;
#ifdef DEBUG
fprintf (stderr, "ppc_elf_relocate_section needs to "
"create relocation for %s\n",
/* When generating a shared object, these relocations
are copied into the output file to be resolved at run
time. */
+ sreloc = elf_section_data (input_section)->sreloc;
+ if (ifunc)
+ sreloc = htab->reliplt;
if (sreloc == NULL)
- {
- sreloc = elf_section_data (input_section)->sreloc;
- if (!htab->elf.dynamic_sections_created)
- sreloc = htab->reliplt;
- if (sreloc == NULL)
- return FALSE;
- }
+ return FALSE;
skip = 0;
outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
break;
case R_PPC_PLTREL24:
- if (h == NULL || ifunc != NULL)
- break;
- /* Relocation is to the entry for this symbol in the
- procedure linkage table. */
- {
- struct plt_entry *ent = find_plt_ent (&h->plt.plist, got2,
- info->shared ? addend : 0);
- addend = 0;
- if (ent == NULL
- || htab->plt == NULL)
- {
- /* We didn't make a PLT entry for this symbol. This
- happens when statically linking PIC code, or when
- using -Bsymbolic. */
- break;
- }
+ if (h != NULL && ifunc == NULL)
+ {
+ struct plt_entry *ent = find_plt_ent (&h->plt.plist, got2,
+ info->shared ? addend : 0);
+ if (ent == NULL
+ || htab->plt == NULL)
+ {
+ /* We didn't make a PLT entry for this symbol. This
+ happens when statically linking PIC code, or when
+ using -Bsymbolic. */
+ }
+ else
+ {
+ /* Relocation is to the entry for this symbol in the
+ procedure linkage table. */
+ unresolved_reloc = FALSE;
+ if (htab->plt_type == PLT_NEW)
+ relocation = (htab->glink->output_section->vma
+ + htab->glink->output_offset
+ + ent->glink_offset);
+ else
+ relocation = (htab->plt->output_section->vma
+ + htab->plt->output_offset
+ + ent->plt.offset);
+ }
+ }
- unresolved_reloc = FALSE;
- if (htab->plt_type == PLT_NEW)
- relocation = (htab->glink->output_section->vma
- + htab->glink->output_offset
- + ent->glink_offset);
- else
- relocation = (htab->plt->output_section->vma
- + htab->plt->output_offset
- + ent->plt.offset);
- }
+ /* R_PPC_PLTREL24 is rather special. If non-zero, the
+ addend specifies the GOT pointer offset within .got2.
+ Don't apply it to the relocation field. */
+ addend = 0;
break;
/* Relocate against _SDA_BASE_. */
}
\f
static enum elf_reloc_type_class
-ppc_elf_reloc_type_class (const Elf_Internal_Rela *rela)
+ppc_elf_reloc_type_class (const struct bfd_link_info *info,
+ const asection *rel_sec,
+ const Elf_Internal_Rela *rela)
{
+ struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info);
+
+ if (rel_sec == htab->reliplt)
+ return reloc_class_ifunc;
+
switch (ELF32_R_TYPE (rela->r_info))
{
case R_PPC_RELATIVE:
return reloc_class_relative;
- case R_PPC_REL24:
- case R_PPC_ADDR24:
case R_PPC_JMP_SLOT:
return reloc_class_plt;
case R_PPC_COPY: