static int mips_elf_make_got_per_bfd PARAMS ((void **, void *));
static int mips_elf_merge_gots PARAMS ((void **, void *));
static int mips_elf_set_global_got_offset PARAMS ((void**, void *));
+static int mips_elf_set_no_stub PARAMS ((void **, void *));
static int mips_elf_resolve_final_got_entry PARAMS ((void**, void *));
static void mips_elf_resolve_final_got_entries
PARAMS ((struct mips_got_info *));
BFD_ASSERT (g->global_gotsym == NULL);
entry->gotidx = arg->value * (long) g->assigned_gotno++;
- /* We can't do lazy update of GOT entries for
- non-primary GOTs since the PLT entries don't use the
- right offsets, so punt at it for now. */
- entry->d.h->no_fn_stub = TRUE;
if (arg->info->shared
|| (elf_hash_table (arg->info)->dynamic_sections_created
&& ((entry->d.h->root.elf_link_hash_flags
return 1;
}
+/* Mark any global symbols referenced in the GOT we are iterating over
+ as inelligible for lazy resolution stubs. */
+static int
+mips_elf_set_no_stub (entryp, p)
+ void **entryp;
+ void *p ATTRIBUTE_UNUSED;
+{
+ struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
+
+ if (entry->abfd != NULL
+ && entry->symndx == -1
+ && entry->d.h->root.dynindx != -1)
+ entry->d.h->no_fn_stub = TRUE;
+
+ return 1;
+}
+
/* Follow indirect and warning hash entries so that each got entry
points to the final symbol definition. P must point to a pointer
to the hash table we're traversing. Since this traversal may
g->next = gg->next;
gg->next = g;
g = gn;
+
+ /* Mark global symbols in every non-primary GOT as ineligible for
+ stubs. */
+ if (g)
+ htab_traverse (g->got_entries, mips_elf_set_no_stub, NULL);
}
while (g);
if (g->next && h->dynindx != -1)
{
struct mips_got_entry e, *p;
+ bfd_vma entry;
bfd_vma offset;
- bfd_vma value;
- Elf_Internal_Rela rel[3];
- bfd_vma addend = 0;
gg = g;
e.symndx = -1;
e.d.h = (struct mips_elf_link_hash_entry *)h;
- if (info->shared
- || h->root.type == bfd_link_hash_undefined
- || h->root.type == bfd_link_hash_undefweak)
- value = 0;
- else if (sym->st_value)
- value = sym->st_value;
- else
- value = h->root.u.def.value;
-
- memset (rel, 0, sizeof (rel));
- rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_REL32);
-
for (g = g->next; g->next != gg; g = g->next)
{
if (g->got_entries
&e)))
{
offset = p->gotidx;
- rel[0].r_offset = rel[1].r_offset = rel[2].r_offset = offset;
-
- MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset);
-
- if ((info->shared
- || (elf_hash_table (info)->dynamic_sections_created
- && p->d.h != NULL
- && ((p->d.h->root.elf_link_hash_flags
- & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
- && ((p->d.h->root.elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0)))
- && ! (mips_elf_create_dynamic_relocation
- (output_bfd, info, rel,
- e.d.h, NULL, value, &addend, sgot)))
- return FALSE;
- BFD_ASSERT (addend == 0);
+ if (info->shared
+ || (elf_hash_table (info)->dynamic_sections_created
+ && p->d.h != NULL
+ && ((p->d.h->root.elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
+ && ((p->d.h->root.elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0)))
+ {
+ /* Create an R_MIPS_REL32 relocation for this entry. Due to
+ the various compatibility problems, it's easier to mock
+ up an R_MIPS_32 or R_MIPS_64 relocation and leave
+ mips_elf_create_dynamic_relocation to calculate the
+ appropriate addend. */
+ Elf_Internal_Rela rel[3];
+
+ memset (rel, 0, sizeof (rel));
+ if (ABI_64_P (output_bfd))
+ rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_64);
+ else
+ rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_32);
+ rel[0].r_offset = rel[1].r_offset = rel[2].r_offset = offset;
+
+ entry = 0;
+ if (! (mips_elf_create_dynamic_relocation
+ (output_bfd, info, rel,
+ e.d.h, NULL, sym->st_value, &entry, sgot)))
+ return FALSE;
+ }
+ else
+ entry = sym->st_value;
+ MIPS_ELF_PUT_WORD (output_bfd, entry, sgot->contents + offset);
}
}
}