aboutsummaryrefslogtreecommitdiff
path: root/bfd/elfxx-mips.c
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2003-11-26 20:58:45 +0000
committerRichard Sandiford <rdsandiford@googlemail.com>2003-11-26 20:58:45 +0000
commit0626d45128eab868030a7a5f58bd90cb6ee28b00 (patch)
tree998c8364df5bec6bfdf20127a9ffe2c1243c1949 /bfd/elfxx-mips.c
parentb4f16abb97f6c746304fc98ba1c00174d9386f6e (diff)
downloadgdb-0626d45128eab868030a7a5f58bd90cb6ee28b00.zip
gdb-0626d45128eab868030a7a5f58bd90cb6ee28b00.tar.gz
gdb-0626d45128eab868030a7a5f58bd90cb6ee28b00.tar.bz2
* 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.
Diffstat (limited to 'bfd/elfxx-mips.c')
-rw-r--r--bfd/elfxx-mips.c90
1 files changed, 55 insertions, 35 deletions
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index b7224a5..0c94909 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -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_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 *));
@@ -2338,10 +2339,6 @@ mips_elf_set_global_got_offset (entryp, p)
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
@@ -2357,6 +2354,23 @@ mips_elf_set_global_got_offset (entryp, p)
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
@@ -2624,6 +2638,11 @@ mips_elf_multi_got (abfd, info, g, got, pages)
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);
@@ -6660,10 +6679,8 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
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;
@@ -6671,18 +6688,6 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
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
@@ -6690,22 +6695,37 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
&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);
}
}
}