diff options
author | Richard Sandiford <rdsandiford@googlemail.com> | 2003-11-26 20:58:45 +0000 |
---|---|---|
committer | Richard Sandiford <rdsandiford@googlemail.com> | 2003-11-26 20:58:45 +0000 |
commit | 0626d45128eab868030a7a5f58bd90cb6ee28b00 (patch) | |
tree | 998c8364df5bec6bfdf20127a9ffe2c1243c1949 /bfd/elfxx-mips.c | |
parent | b4f16abb97f6c746304fc98ba1c00174d9386f6e (diff) | |
download | gdb-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.c | 90 |
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); } } } |