This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: MIPS multigot fixes for Linux
> OK to install?
>
OK.
-eric
> Richard
>
>
> 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 entry and
> use mips_elf_create_dynamic_relocation to deal with any compatibility
> issues. Store the adjusted addend in the GOT slot.
>
> Index: bfd/elfxx-mips.c
> ===================================================================
> RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
> retrieving revision 1.82
> diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.82 elfxx-mips.c
> *** bfd/elfxx-mips.c 14 Nov 2003 16:05:13 -0000 1.82
> --- bfd/elfxx-mips.c 26 Nov 2003 20:32:04 -0000
> *************** static int mips_elf_bfd2got_entry_eq PAR
> *** 471,476 ****
> --- 471,477 ----
> 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 *));
> *************** mips_elf_set_global_got_offset (entryp,
> *** 2338,2347 ****
> 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
> --- 2339,2344 ----
> *************** mips_elf_set_global_got_offset (entryp,
> *** 2357,2362 ****
> --- 2354,2376 ----
> 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
> *************** mips_elf_multi_got (abfd, info, g, got,
> *** 2624,2629 ****
> --- 2638,2648 ----
> 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);
>
> *************** _bfd_mips_elf_finish_dynamic_symbol (out
> *** 6660,6669 ****
> if (g->next && h->dynindx != -1)
> {
> struct mips_got_entry e, *p;
> bfd_vma offset;
> - bfd_vma value;
> - Elf_Internal_Rela rel[3];
> - bfd_vma addend = 0;
>
> gg = g;
>
> --- 6679,6686 ----
> if (g->next && h->dynindx != -1)
> {
> struct mips_got_entry e, *p;
> + bfd_vma entry;
> bfd_vma offset;
>
> gg = g;
>
> *************** _bfd_mips_elf_finish_dynamic_symbol (out
> *** 6671,6688 ****
> 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
> --- 6688,6693 ----
> *************** _bfd_mips_elf_finish_dynamic_symbol (out
> *** 6690,6711 ****
> &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);
> }
> }
> }
> --- 6695,6731 ----
> &e)))
> {
> offset = p->gotidx;
> ! 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);
> }
> }
> }
--
Eric Christopher <echristo@redhat.com>