* elfxx-mips.c (mips_elf_set_global_got_offset): Don't set no_fn_stub.

(mips_elf_set_no_stub): New function.
	(mips_elf_multi_got): Call it.
	(_bfd_mips_elf_finish_dynamic_symbol): If a relocation is needed for
	a secondary GOT entry, create an R_MIPS_32 or R_MIPS_64 relocation and
	use mips_elf_create_dynamic_relocation to deal with any compatibility
	issues.  Store the adjusted addend in the GOT slot.
This commit is contained in:
Richard Sandiford
2003-11-26 20:58:45 +00:00
parent b4f16abb97
commit 0626d45128
2 changed files with 64 additions and 33 deletions

View File

@ -1,3 +1,14 @@
2003-11-26 Daniel Jacobowitz <drow@mvista.com>
Richard Sandiford <rsandifo@redhat.com>
* elfxx-mips.c (mips_elf_set_global_got_offset): Don't set no_fn_stub.
(mips_elf_set_no_stub): New function.
(mips_elf_multi_got): Call it.
(_bfd_mips_elf_finish_dynamic_symbol): If a relocation is needed for
a secondary GOT entry, create an R_MIPS_32 or R_MIPS_64 relocation and
use mips_elf_create_dynamic_relocation to deal with any compatibility
issues. Store the adjusted addend in the GOT slot.
2003-11-25 Mattias Engdeg<65>rd <mattias@virtutech.se> 2003-11-25 Mattias Engdeg<65>rd <mattias@virtutech.se>
* stabs.c (_bfd_link_section_stabs): Skip N_EXCL stabs when * stabs.c (_bfd_link_section_stabs): Skip N_EXCL stabs when

View File

@ -471,6 +471,7 @@ static int mips_elf_bfd2got_entry_eq PARAMS ((const PTR, const PTR));
static int mips_elf_make_got_per_bfd PARAMS ((void **, void *)); static int mips_elf_make_got_per_bfd PARAMS ((void **, void *));
static int mips_elf_merge_gots 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_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 int mips_elf_resolve_final_got_entry PARAMS ((void**, void *));
static void mips_elf_resolve_final_got_entries static void mips_elf_resolve_final_got_entries
PARAMS ((struct mips_got_info *)); PARAMS ((struct mips_got_info *));
@ -2338,10 +2339,6 @@ mips_elf_set_global_got_offset (entryp, p)
BFD_ASSERT (g->global_gotsym == NULL); BFD_ASSERT (g->global_gotsym == NULL);
entry->gotidx = arg->value * (long) g->assigned_gotno++; 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 if (arg->info->shared
|| (elf_hash_table (arg->info)->dynamic_sections_created || (elf_hash_table (arg->info)->dynamic_sections_created
&& ((entry->d.h->root.elf_link_hash_flags && ((entry->d.h->root.elf_link_hash_flags
@ -2357,6 +2354,23 @@ mips_elf_set_global_got_offset (entryp, p)
return 1; 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 /* Follow indirect and warning hash entries so that each got entry
points to the final symbol definition. P must point to a pointer points to the final symbol definition. P must point to a pointer
to the hash table we're traversing. Since this traversal may to the hash table we're traversing. Since this traversal may
@ -2624,6 +2638,11 @@ mips_elf_multi_got (abfd, info, g, got, pages)
g->next = gg->next; g->next = gg->next;
gg->next = g; gg->next = g;
g = gn; 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); while (g);
@ -6660,10 +6679,8 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
if (g->next && h->dynindx != -1) if (g->next && h->dynindx != -1)
{ {
struct mips_got_entry e, *p; struct mips_got_entry e, *p;
bfd_vma entry;
bfd_vma offset; bfd_vma offset;
bfd_vma value;
Elf_Internal_Rela rel[3];
bfd_vma addend = 0;
gg = g; gg = g;
@ -6671,18 +6688,6 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
e.symndx = -1; e.symndx = -1;
e.d.h = (struct mips_elf_link_hash_entry *)h; 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) for (g = g->next; g->next != gg; g = g->next)
{ {
if (g->got_entries if (g->got_entries
@ -6690,22 +6695,37 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
&e))) &e)))
{ {
offset = p->gotidx; offset = p->gotidx;
rel[0].r_offset = rel[1].r_offset = rel[2].r_offset = offset; if (info->shared
MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset);
if ((info->shared
|| (elf_hash_table (info)->dynamic_sections_created || (elf_hash_table (info)->dynamic_sections_created
&& p->d.h != NULL && p->d.h != NULL
&& ((p->d.h->root.elf_link_hash_flags && ((p->d.h->root.elf_link_hash_flags
& ELF_LINK_HASH_DEF_DYNAMIC) != 0) & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
&& ((p->d.h->root.elf_link_hash_flags && ((p->d.h->root.elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0))) & ELF_LINK_HASH_DEF_REGULAR) == 0)))
&& ! (mips_elf_create_dynamic_relocation {
/* 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, (output_bfd, info, rel,
e.d.h, NULL, value, &addend, sgot))) e.d.h, NULL, sym->st_value, &entry, sgot)))
return FALSE; return FALSE;
BFD_ASSERT (addend == 0); }
else
entry = sym->st_value;
MIPS_ELF_PUT_WORD (output_bfd, entry, sgot->contents + offset);
} }
} }
} }