This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH 1/5] Lay out MIPS GOTs later in the link process
- From: Richard Sandiford <rdsandiford at googlemail dot com>
- To: binutils at sourceware dot org
- Date: Wed, 06 Aug 2008 21:04:05 +0100
- Subject: Re: [PATCH 1/5] Lay out MIPS GOTs later in the link process
- References: <8763rt1pg0.fsf@firetop.home>
Richard Sandiford <rdsandiford@googlemail.com> writes:
> This patch is the first of a series aimed at improving the GOT allocation.
> It addresses what I see as the most fundamental flaw of the current code:
> that it allocates the GOT too early, before we even know how many dynamic
> symbols there will be.
>
> Specifically, the current code allocates the GOT in
> elf_backend_always_size_sections rather than
> elf_backend_size_dynamic_sections. This has two main drawbacks:
>
> - We have an 80+ line function, _bfd_mips_elf_hide_symbol,
> whose sole purpose is to try to update the GOT allocation
> in response to symbol hiding between always_size_sections
> and size_dynamic_sections. As the comment says, it isn't
> always possible to reclaim space:
>
> /* If this was a global symbol forced into the primary GOT, we
> no longer need an entry for it. We can't release the entry
> at this point, but we must at least stop counting it as one
> of the symbols that required a forced got entry. */
>
> This then leads to further fixups in size_dynamic_sections itself:
>
> /* _bfd_mips_elf_always_size_sections() has already done
> most of the work, but some symbols may have been mapped
> to versions that we must now resolve in the got_entries
> hash tables. */
>
> - We don't know in always_size_sections how many stubs we need --
> that's determined by _bfd_mips_elf_adjust_dynamic_symbol --
> so we have to use a very conservative estimate when computing
> loadable_size:
>
> /* In the worst case, we'll get one stub per dynamic symbol, plus
> one to account for the dummy entry at the end required by IRIX
> rld. */
> loadable_size += htab->function_stub_size * (i + 1);
>
> This means that we can have more page entries than we really need.
>
> Before the patch, the code has the following steps:
>
> always_size_sections
> --------------------
>
> [A] Compute the amount of memory that can be addressed by GOT page entries.
> [B] Sort the symbol table, dividing it into non-GOT-mapped and
> GOT-mapped areas.
> [C] Pick a stub size.
> [D] Count the number of page and TLS GOT entries.
> [E] Replace GOT entries for indirect and warning symbols
> with GOT entries for the target symbol.
>
> Either call mips_elf_multi_got or:
> [F1] Assign indices for TLS GOT entries.
>
> mips_elf_multi_got (called from always_size_sections)
> ------------------
>
> [G] Create a separate GOT for each input BFD.
> [H] Merge per-BFD GOTs together where possible, choosing one as
> the primary GOT.
> [I] Mark symbols that need primary GOT entries and reorder the
> symbol table so that those symbols come before all others
> in the "master" (i.e. ABI-defined) GOT.
> [J] Prevent symbols referenced by secondary GOTs from having
> lazy-binding stubs.
> [F2] Assign indices for TLS GOT entries.
>
> adjust_dynamic_symbol
> ---------------------
> [K] Allocate .MIPS.stub entries to each function that needs a stub.
>
> mips_elf_record_global_got_symbol
> ---------------------------------
> [L1] Count the number of forced-local symbols with global GOT entries.
>
> hide_symbol
> -----------
> [L2] Adjust local/global-GOT counts for symbols that have already
> been allocated a GOT entry.
>
> size_dymamic_sections
> ---------------------
> [M] If we have multiple GOTs, reapply [E].
> [N] If we have multiple GOTs, assign each primary and secondary GOT
> a position in the master GOT.
> [O] Allocate dynamic relocations needed by the GOT.
>
> The corresponding steps after the patch are:
>
> adjust_dynamic_symbol
> ---------------------
> [k1] Count the number of stubs needed.
>
> mips_elf_estimate_stub_size (called from size_dynamic_sections)
> ---------------------------
> [c] Pick a stub size and estimate the size of .MIPS.stubs.
>
> mips_lay_out_got (called from size_dynamic_sections)
> ----------------
> [e] Replace GOT entries for indirect and warning symbols
> with GOT entries for the target symbol.
> [l] Count the number forced-local symbols.
> [b] Sort the symbol table, dividing it into non-GOT-mapped and
> GOT-mapped areas.
> [a] Compute the amount of memory that can be addressed by GOT page entries.
> [d] Count the number of page and TLS GOT entries.
>
> Either call mips_elf_multi_got or:
> [f1] Assign indices for TLS GOT entries.
> [o1] Allocate dynamic relocations needed by the GOT.
>
> mips_elf_multi_got (called from mips_lay_out_got)
> ------------------
> [g] Create a separate GOT for each input BFD.
> [h] Merge per-BFD GOTs together where possible, choosing one as
> the primary GOT.
> [i] Mark symbols that need primary GOT entries and reorder the
> symbol table so that those symbols come before all others
> in the "master" (i.e. ABI-defined) GOT.
> [j] Prevent symbols referenced by secondary GOTs from having
> lazy-binding stubs.
> [f2] Assign indices for TLS GOT entries.
> [n] Assign each primary and secondary GOT a position in the master GOT.
> [o2] Allocate dynamic relocations needed by the GOT.
>
> mips_elf_lay_out_lazy_stubs (called from size_dynamic_sections)
> ---------------------------
> [k2] Allocate offsets to each .MIPS.stub entry.
>
> size_dynamic_sections
> ---------------------
> Call mips_elf_estimate_stub_size, mips_elf_lay_out_got and
> mips_elf_lay_out_lazy_stubs.
>
> In other words, everything is now handled by adjust_dynamic_symbol and
> size_dynamic_sections, although some of the work is done by subroutines.
> There is no need for special handling in always_size_sections,
> mips_elf_record_global_got_symbol or hide_symbol.
>
> Notes:
>
> - [J] happened before [K], so setting no_fn_stub to TRUE was
> enough to prevent a stub being used. [k1] now happens before [j],
> so [k1] conservatively assumes that we need a stub, then [j]
> removes it if necessary. The patch uses a new "needs_lazy_stub"
> field to track whether we're creating a stub.
>
> This arrangement means that, if we need multiple GOTs, we still
> overestimate the size of .MIPS.stubs when deciding how many page
> entries are needed. The new estimate is tighter than the old one
> though. Note that the final size of .MIPS.stubs is computed by
> [k2] and is accurate.
>
> mips_elf_output_extsym used no_fn_stub to detect whether a stub
> had been created. The patch uses needs_lazy_stub instead.
>
> - There was a comment querying whether [M] is really needed:
>
> /* NOTE 2005-02-03: How can this call, or the next, ever
> find any indirect entries to resolve? They were all
> resolved in mips_elf_multi_got. */
>
> It certainly isn't after the patch. The comment refers to step [E]
> (actually in always_size_sections) and [e], like [M], now happens
> in size_dynamic_sections.
>
> - [E] was needlessly quadratic. mips_elf_resolve_final_got_entries
> applied mips_elf_resolve_final_got_entry to each GOT entry,
> but stopped as soon as it found an entry that needed adjusting.
> (It isn't safe to continue a traversal after modifying the
> hashtable.) mips_elf_resolve_final_got_entries would then
> start again from the beginning, restarting again if it found
> another entry that needed adjusting.
>
> [e] instead does one walk to see whether any change needs to
> be made. If so, it uses a second traversal to creates a new GOT
> with the new information.
>
> - Symbols had a MIPS-specific "forced_local" field as well as the
> generic ELF "root.forced_local" field. Only GOT code used the
> MIPS-specific version.
>
> I'm not sure if the old code really needed a separate field,
> but the new code doesn't. I think it's confusing to have both.
>
> - The main size_dynamic_sections loop allocated GOT dynamic
> relocations ([O]), so the loop had to treat .rel.dyn specially,
> postponing the size calculation until after the loop. Now that
> mips_lay_out_got does [o] as part of the main GOT lay-out code,
> this special treatment is no longer necessary.
>
> Tested on mips64-linux-gnu and mips64el-linux-gnu. OK to install?
I've updated this for current mainline, taking account of:
http://sources.redhat.com/ml/binutils/2008-07/msg00350.html
Patches 2-4 are unaffected. I'll post an updated patch 5 in a sec.
Richard
bfd/
* elf32-mips.c (elf_backend_hide_symbol): Delete.
* elfn32-mips.c (elf_backend_hide_symbol): Likewise.
* elf64-mips.c (elf_backend_hide_symbol): Likewise.
* elfxx-mips.h (elf_backend_hide_symbol): Likewise.
* elfxx-mips.c (mips_elf_link_hash_entry): Remove "forced_local"
and add "needs_lazy_stub".
(mips_elf_link_hash_newfunc): Update accordingly.
(mips_elf_link_hash_table): Remove "computed_got_sizes" and
add "lazy_stub_count".
(_bfd_mips_elf_link_hash_table_create): Update accordingly.
(mips_elf_output_extsym): Use hd->needs_lazy_stub to detect
cases where a lazy stub is being used.
(mips_elf_sort_hash_table_f): Use h->root.forced_local instead
of h->forced_local.
(mips_elf_record_global_got_symbol): Use _bfd_elf_link_hash_hide_symbol
instead of _bfd_mips_elf_hide_symbol. Do not increment local_gotno
here.
(mips_elf_allocate_dynamic_relocations): Move before new first use.
(mips_elf_check_recreate_got, mips_elf_recreate_got): New functions.
(mips_elf_resolve_final_got_entries): Move earlier in file. Make at
most two passes over the hash table. Use mips_elf_check_recreate_got
to see if there are any indirect or warning entries and
mips_elf_recreate_got to create a new GOT without them.
Return a boolean success value.
(mips_elf_count_forced_local_got_entries): New function.
(mips_elf_make_got_per_bfd): Check h->root.forced_local instead of
h->forced_local.
(mips_elf_set_global_got_offset): Likewise.
(mips_elf_set_no_stub): Replace with...
(mips_elf_forbid_lazy_stubs): ...this new function.
(mips_elf_resolve_final_got_entry): Delete.
(mips_elf_multi_got): Fix formatting. Use mips_elf_forbid_lazy_stubs
instead of mips_elf_set_no_stub. Move the code that sets
global offsets and allocates dynamic relocations from the main
_bfd_mips_elf_size_dynamic_sections loop to here.
(_bfd_mips_elf_adjust_dynamic_symbol): Do not allocate room in
.MIPS.stubs here; just set hmips->needs_lazy_stub and increment
htab->lazy_stub_count.
(_bfd_mips_elf_always_size_sections): Move the stub-estimation
code to mips_elf_estimate_stub_size and the GOT-sizing code to
mips_elf_lay_out_got. Do not call these functions here.
(mips_elf_estimate_stub_size): New function, split
out from _bfd_mips_elf_always_size_sections. Call
mips_elf_resolve_final_got_entries earlier. Count the number
of forced-local entries. Do not add stub sizes to loadable_size;
after this patch, the stub sizes are already included in the main
estimate. Allocate dynamic relocations here rather than in the
main _bfd_mips_elf_size_dynamic_sections loop.
(mips_elf_estimate_stub_size): New function, split out from
_bfd_mips_elf_always_size_sections.
(mips_elf_allocate_lazy_stub): New function.
(mips_elf_lay_out_lazy_stubs): Likewise.
(_bfd_mips_elf_size_dynamic_sections): Call mips_elf_estimate_stub_size,
mips_elf_lay_out_got and mips_elf_lay_out_lazy_stubs. Do not handle
the allocation of sreldyn specially.
(_bfd_mips_elf_hide_symbol): Delete.
ld/testsuite/
* ld-mips-elf/tlsdyn-o32-2.got, ld-mips-elf/tlsdyn-o32-3.got,
ld-mips-elf/tlsdyn-o32-2.d, ld-mips-elf/tlsdyn-o32-3.d: Change the
GOT layout as follows:
BEFORE AFTER
+0x08 %call16(__tls_get_addr) %call16(__tls_get_addr)
+0x0c %tlsldm(tlsbin_ld) %gottprel(tlsvar_ie)
+0x10 " " %tlsgd(tlsvar_gd)
+0x14 %tlsgd(tlsvar_gd) " "
+0x18 " " %tlsgd(tlsbin_gd)
+0x1c %gottprel(tlsvar_ie) " "
+0x20 %tlsgd(tlsbin_gd) %tlsldm(tlsbin_ld)
+0x24 " " " "
+0x28 %gottprel(tlsbin_ie) %gottprel(tlsbin_ie)
Index: bfd/elf32-mips.c
===================================================================
--- bfd/elf32-mips.c 2008-08-06 20:43:36.000000000 +0100
+++ bfd/elf32-mips.c 2008-08-06 21:00:51.000000000 +0100
@@ -1606,7 +1606,6 @@ #define elf_backend_gc_mark_hook _bfd_mi
#define elf_backend_gc_sweep_hook _bfd_mips_elf_gc_sweep_hook
#define elf_backend_copy_indirect_symbol \
_bfd_mips_elf_copy_indirect_symbol
-#define elf_backend_hide_symbol _bfd_mips_elf_hide_symbol
#define elf_backend_grok_prstatus elf32_mips_grok_prstatus
#define elf_backend_grok_psinfo elf32_mips_grok_psinfo
#define elf_backend_ecoff_debug_swap &mips_elf32_ecoff_debug_swap
Index: bfd/elfn32-mips.c
===================================================================
--- bfd/elfn32-mips.c 2008-08-06 20:43:36.000000000 +0100
+++ bfd/elfn32-mips.c 2008-08-06 21:00:51.000000000 +0100
@@ -2433,7 +2433,6 @@ #define elf_backend_gc_mark_hook _bfd_mi
#define elf_backend_gc_sweep_hook _bfd_mips_elf_gc_sweep_hook
#define elf_backend_copy_indirect_symbol \
_bfd_mips_elf_copy_indirect_symbol
-#define elf_backend_hide_symbol _bfd_mips_elf_hide_symbol
#define elf_backend_grok_prstatus elf32_mips_grok_prstatus
#define elf_backend_grok_psinfo elf32_mips_grok_psinfo
#define elf_backend_ecoff_debug_swap &mips_elf32_ecoff_debug_swap
Index: bfd/elf64-mips.c
===================================================================
--- bfd/elf64-mips.c 2008-08-06 20:43:36.000000000 +0100
+++ bfd/elf64-mips.c 2008-08-06 21:00:51.000000000 +0100
@@ -3179,7 +3179,6 @@ #define elf_backend_gc_mark_hook _bfd_mi
#define elf_backend_gc_sweep_hook _bfd_mips_elf_gc_sweep_hook
#define elf_backend_copy_indirect_symbol \
_bfd_mips_elf_copy_indirect_symbol
-#define elf_backend_hide_symbol _bfd_mips_elf_hide_symbol
#define elf_backend_ignore_discarded_relocs \
_bfd_mips_elf_ignore_discarded_relocs
#define elf_backend_mips_irix_compat elf64_mips_irix_compat
Index: bfd/elfxx-mips.h
===================================================================
--- bfd/elfxx-mips.h 2008-08-06 20:18:41.000000000 +0100
+++ bfd/elfxx-mips.h 2008-08-06 21:00:51.000000000 +0100
@@ -81,8 +81,6 @@
extern void _bfd_mips_elf_copy_indirect_symbol
(struct bfd_link_info *, struct elf_link_hash_entry *,
struct elf_link_hash_entry *);
-extern void _bfd_mips_elf_hide_symbol
- (struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean);
extern bfd_boolean _bfd_mips_elf_ignore_discarded_relocs
(asection *);
extern bfd_boolean _bfd_mips_elf_find_nearest_line
Index: bfd/elfxx-mips.c
===================================================================
--- bfd/elfxx-mips.c 2008-08-06 20:57:18.000000000 +0100
+++ bfd/elfxx-mips.c 2008-08-06 21:00:51.000000000 +0100
@@ -317,15 +317,15 @@ #define GOT_TLS_DONE 0x80
in any relocs other than a 16 bit call. */
unsigned int need_fn_stub : 1;
- /* Are we forced local? This will only be set if we have converted
- the initial global GOT entry to a local GOT entry. */
- unsigned int forced_local : 1;
-
/* Are we referenced by some kind of relocation? */
unsigned int is_relocation_target : 1;
/* Are we referenced by branch relocations? */
unsigned int is_branch_target : 1;
+
+ /* Does this symbol need a traditional MIPS lazy-binding stub
+ (as opposed to a PLT entry)? */
+ unsigned int needs_lazy_stub : 1;
};
/* MIPS ELF linker hash table. */
@@ -349,8 +349,6 @@ struct mips_elf_link_hash_table
bfd_vma rld_value;
/* This is set if we see any mips16 stub sections. */
bfd_boolean mips16_stubs_seen;
- /* True if we've computed the size of the GOT. */
- bfd_boolean computed_got_sizes;
/* True if we're generating code for VxWorks. */
bfd_boolean is_vxworks;
/* True if we already reported the small-data section overflow. */
@@ -371,6 +369,8 @@ struct mips_elf_link_hash_table
bfd_vma plt_header_size;
/* The size of a PLT entry in bytes (VxWorks only). */
bfd_vma plt_entry_size;
+ /* The number of functions that need a lazy-binding stub. */
+ bfd_vma lazy_stub_count;
/* The size of a function stub entry in bytes. */
bfd_vma function_stub_size;
};
@@ -871,9 +871,9 @@ mips_elf_link_hash_newfunc (struct bfd_h
ret->readonly_reloc = FALSE;
ret->no_fn_stub = FALSE;
ret->need_fn_stub = FALSE;
- ret->forced_local = FALSE;
ret->is_relocation_target = FALSE;
ret->is_branch_target = FALSE;
+ ret->needs_lazy_stub = FALSE;
}
return (struct bfd_hash_entry *) ret;
@@ -2066,18 +2066,14 @@ mips_elf_output_extsym (struct mips_elf_
else
h->esym.asym.value = 0;
}
- else if (h->root.needs_plt)
+ else
{
struct mips_elf_link_hash_entry *hd = h;
- bfd_boolean no_fn_stub = h->no_fn_stub;
while (hd->root.root.type == bfd_link_hash_indirect)
- {
- hd = (struct mips_elf_link_hash_entry *)h->root.root.u.i.link;
- no_fn_stub = no_fn_stub || hd->no_fn_stub;
- }
+ hd = (struct mips_elf_link_hash_entry *)h->root.root.u.i.link;
- if (!no_fn_stub)
+ if (hd->needs_lazy_stub)
{
/* Set type and value for a symbol with a function stub. */
h->esym.asym.st = stProc;
@@ -2965,7 +2961,7 @@ mips_elf_sort_hash_table_f (struct mips_
hsd->low = (struct elf_link_hash_entry *) h;
h->root.dynindx = hsd->max_unref_got_dynindx++;
}
- else if (h->root.got.offset != 1 || h->forced_local)
+ else if (h->root.got.offset != 1 || h->root.forced_local)
h->root.dynindx = hsd->max_non_got_dynindx++;
else
{
@@ -3001,7 +2997,7 @@ mips_elf_record_global_got_symbol (struc
{
case STV_INTERNAL:
case STV_HIDDEN:
- _bfd_mips_elf_hide_symbol (info, h, TRUE);
+ _bfd_elf_link_hash_hide_symbol (info, h, TRUE);
break;
}
if (!bfd_elf_link_record_dynamic_symbol (info, h))
@@ -3042,14 +3038,10 @@ mips_elf_record_global_got_symbol (struc
return TRUE;
if (tls_flag == 0)
- {
- /* By setting this to a value other than -1, we are indicating that
- there needs to be a GOT entry for H. Avoid using zero, as the
- generic ELF copy_indirect_symbol tests for <= 0. */
- h->got.offset = 1;
- if (h->forced_local)
- g->local_gotno++;
- }
+ /* By setting this to a value other than -1, we are indicating that
+ there needs to be a GOT entry for H. Avoid using zero, as the
+ generic ELF copy_indirect_symbol tests for <= 0. */
+ h->got.offset = 1;
return TRUE;
}
@@ -3229,6 +3221,148 @@ mips_elf_record_got_page_entry (struct b
return TRUE;
}
+
+/* Add room for N relocations to the .rel(a).dyn section in ABFD. */
+
+static void
+mips_elf_allocate_dynamic_relocations (bfd *abfd, struct bfd_link_info *info,
+ unsigned int n)
+{
+ asection *s;
+ struct mips_elf_link_hash_table *htab;
+
+ htab = mips_elf_hash_table (info);
+ s = mips_elf_rel_dyn_section (info, FALSE);
+ BFD_ASSERT (s != NULL);
+
+ if (htab->is_vxworks)
+ s->size += n * MIPS_ELF_RELA_SIZE (abfd);
+ else
+ {
+ if (s->size == 0)
+ {
+ /* Make room for a null element. */
+ s->size += MIPS_ELF_REL_SIZE (abfd);
+ ++s->reloc_count;
+ }
+ s->size += n * MIPS_ELF_REL_SIZE (abfd);
+ }
+}
+
+/* A htab_traverse callback for GOT entries. Set boolean *DATA to true
+ if the GOT entry is for an indirect or warning symbol. */
+
+static int
+mips_elf_check_recreate_got (void **entryp, void *data)
+{
+ struct mips_got_entry *entry;
+ bfd_boolean *must_recreate;
+
+ entry = (struct mips_got_entry *) *entryp;
+ must_recreate = (bfd_boolean *) data;
+ if (entry->abfd != NULL && entry->symndx == -1)
+ {
+ struct mips_elf_link_hash_entry *h;
+
+ h = entry->d.h;
+ if (h->root.root.type == bfd_link_hash_indirect
+ || h->root.root.type == bfd_link_hash_warning)
+ {
+ *must_recreate = TRUE;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* A htab_traverse callback for GOT entries. Add all entries to
+ hash table *DATA, converting entries for indirect and warning
+ symbols into entries for the target symbol. Set *DATA to null
+ on error. */
+
+static int
+mips_elf_recreate_got (void **entryp, void *data)
+{
+ htab_t *new_got;
+ struct mips_got_entry *entry;
+ void **slot;
+
+ new_got = (htab_t *) data;
+ entry = (struct mips_got_entry *) *entryp;
+ if (entry->abfd != NULL && entry->symndx == -1)
+ {
+ struct mips_elf_link_hash_entry *h;
+
+ h = entry->d.h;
+ while (h->root.root.type == bfd_link_hash_indirect
+ || h->root.root.type == bfd_link_hash_warning)
+ h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
+ entry->d.h = h;
+ }
+ slot = htab_find_slot (*new_got, entry, INSERT);
+ if (slot == NULL)
+ {
+ *new_got = NULL;
+ return 0;
+ }
+ if (*slot == NULL)
+ *slot = entry;
+ else
+ free (entry);
+ return 1;
+}
+
+/* If any entries in G->got_entries are for indirect or warning symbols,
+ replace them with entries for the target symbol. */
+
+static bfd_boolean
+mips_elf_resolve_final_got_entries (struct mips_got_info *g)
+{
+ bfd_boolean must_recreate;
+ htab_t new_got;
+
+ must_recreate = FALSE;
+ htab_traverse (g->got_entries, mips_elf_check_recreate_got, &must_recreate);
+ if (must_recreate)
+ {
+ new_got = htab_create (htab_size (g->got_entries),
+ mips_elf_got_entry_hash,
+ mips_elf_got_entry_eq, NULL);
+ htab_traverse (g->got_entries, mips_elf_recreate_got, &new_got);
+ if (new_got == NULL)
+ return FALSE;
+
+ /* Each entry in g->got_entries has either been copied to new_got
+ or freed. Now delete the hash table itself. */
+ htab_delete (g->got_entries);
+ g->got_entries = new_got;
+ }
+ return TRUE;
+}
+
+/* An elf_link_hash_traverse callback for which DATA points to a mips_got_info.
+ Add each forced-local GOT symbol to DATA's local_gotno field. */
+
+static int
+mips_elf_count_forced_local_got_symbols (struct elf_link_hash_entry *h,
+ void *data)
+{
+ struct mips_got_info *g;
+
+ g = (struct mips_got_info *) data;
+ if (h->got.offset != MINUS_ONE
+ && (h->forced_local || h->dynindx == -1))
+ {
+ /* We no longer need this entry if it was only used for
+ relocations; those relocations will be against the
+ null or section symbol instead of H. */
+ if (h->got.offset == 2)
+ h->got.offset = MINUS_ONE;
+ else
+ g->local_gotno++;
+ }
+ return 1;
+}
/* Compute the hash value of the bfd in a bfd2got hash entry. */
@@ -3360,7 +3494,7 @@ mips_elf_make_got_per_bfd (void **entryp
if (entry->tls_type & GOT_TLS_IE)
g->tls_gotno += 1;
}
- else if (entry->symndx >= 0 || entry->d.h->forced_local)
+ else if (entry->symndx >= 0 || entry->d.h->root.forced_local)
++g->local_gotno;
else
++g->global_gotno;
@@ -3593,7 +3727,7 @@ mips_elf_set_global_got_offset (void **e
if (entry->abfd != NULL && entry->symndx == -1
&& entry->d.h->root.dynindx != -1
- && !entry->d.h->forced_local
+ && !entry->d.h->root.forced_local
&& entry->d.h->tls_type == GOT_NORMAL)
{
if (g)
@@ -3614,85 +3748,31 @@ mips_elf_set_global_got_offset (void **e
return 1;
}
-/* Mark any global symbols referenced in the GOT we are iterating over
- as inelligible for lazy resolution stubs. */
+/* A htab_traverse callback for GOT entries for which DATA is the
+ bfd_link_info. Forbid any global symbols from having traditional
+ lazy-binding stubs. */
+
static int
-mips_elf_set_no_stub (void **entryp, void *p ATTRIBUTE_UNUSED)
+mips_elf_forbid_lazy_stubs (void **entryp, void *data)
{
- struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
+ struct bfd_link_info *info;
+ struct mips_elf_link_hash_table *htab;
+ struct mips_got_entry *entry;
+ entry = (struct mips_got_entry *) *entryp;
+ info = (struct bfd_link_info *) data;
+ htab = mips_elf_hash_table (info);
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
- modify the hash table, we set this pointer to NULL to indicate
- we've made a potentially-destructive change to the hash table, so
- the traversal must be restarted. */
-static int
-mips_elf_resolve_final_got_entry (void **entryp, void *p)
-{
- struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
- htab_t got_entries = *(htab_t *)p;
-
- if (entry->abfd != NULL && entry->symndx == -1)
+ && entry->d.h->needs_lazy_stub)
{
- struct mips_elf_link_hash_entry *h = entry->d.h;
-
- while (h->root.root.type == bfd_link_hash_indirect
- || h->root.root.type == bfd_link_hash_warning)
- h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
-
- if (entry->d.h == h)
- return 1;
-
- entry->d.h = h;
-
- /* If we can't find this entry with the new bfd hash, re-insert
- it, and get the traversal restarted. */
- if (! htab_find (got_entries, entry))
- {
- htab_clear_slot (got_entries, entryp);
- entryp = htab_find_slot (got_entries, entry, INSERT);
- if (! *entryp)
- *entryp = entry;
- /* Abort the traversal, since the whole table may have
- moved, and leave it up to the parent to restart the
- process. */
- *(htab_t *)p = NULL;
- return 0;
- }
- /* We might want to decrement the global_gotno count, but it's
- either too early or too late for that at this point. */
+ entry->d.h->needs_lazy_stub = FALSE;
+ htab->lazy_stub_count--;
}
return 1;
}
-/* Turn indirect got entries in a got_entries table into their final
- locations. */
-static void
-mips_elf_resolve_final_got_entries (struct mips_got_info *g)
-{
- htab_t got_entries;
-
- do
- {
- got_entries = g->got_entries;
-
- htab_traverse (got_entries,
- mips_elf_resolve_final_got_entry,
- &got_entries);
- }
- while (got_entries == NULL);
-}
-
/* Return the offset of an input bfd IBFD's GOT from the beginning of
the primary GOT. */
static bfd_vma
@@ -3724,8 +3804,10 @@ mips_elf_multi_got (bfd *abfd, struct bf
struct mips_elf_got_per_bfd_arg got_per_bfd_arg;
struct mips_elf_set_global_got_offset_arg set_got_offset_arg;
struct mips_got_info *g, *gg;
- unsigned int assign;
+ unsigned int assign, needed_relocs;
+ bfd *dynobj;
+ dynobj = elf_hash_table (info)->dynobj;
htab = mips_elf_hash_table (info);
g = htab->got_info;
g->bfd2got = htab_try_create (1, mips_elf_bfd2got_entry_hash,
@@ -3916,16 +3998,49 @@ mips_elf_multi_got (bfd *abfd, struct bf
/* Move onto the next GOT. It will be a secondary GOT if nonull. */
g = gn;
- /* Mark global symbols in every non-primary GOT as ineligible for
- stubs. */
+ /* Forbid global symbols in every non-primary GOT from having
+ lazy-binding stubs. */
if (g)
- htab_traverse (g->got_entries, mips_elf_set_no_stub, NULL);
+ htab_traverse (g->got_entries, mips_elf_forbid_lazy_stubs, info);
}
while (g);
got->size = (gg->next->local_gotno
- + gg->next->global_gotno
- + gg->next->tls_gotno) * MIPS_ELF_GOT_SIZE (abfd);
+ + gg->next->global_gotno
+ + gg->next->tls_gotno) * MIPS_ELF_GOT_SIZE (abfd);
+
+ needed_relocs = 0;
+ set_got_offset_arg.value = MIPS_ELF_GOT_SIZE (abfd);
+ set_got_offset_arg.info = info;
+ for (g = gg->next; g && g->next != gg; g = g->next)
+ {
+ unsigned int save_assign;
+
+ /* Assign offsets to global GOT entries. */
+ save_assign = g->assigned_gotno;
+ g->assigned_gotno = g->local_gotno;
+ set_got_offset_arg.g = g;
+ set_got_offset_arg.needed_relocs = 0;
+ htab_traverse (g->got_entries,
+ mips_elf_set_global_got_offset,
+ &set_got_offset_arg);
+ needed_relocs += set_got_offset_arg.needed_relocs;
+ BFD_ASSERT (g->assigned_gotno - g->local_gotno <= g->global_gotno);
+
+ g->assigned_gotno = save_assign;
+ if (info->shared)
+ {
+ needed_relocs += g->local_gotno - g->assigned_gotno;
+ BFD_ASSERT (g->assigned_gotno == g->next->local_gotno
+ + g->next->global_gotno
+ + g->next->tls_gotno
+ + MIPS_RESERVED_GOTNO (info));
+ }
+ }
+
+ if (needed_relocs)
+ mips_elf_allocate_dynamic_relocations (dynobj, info,
+ needed_relocs);
return TRUE;
}
@@ -5059,33 +5174,6 @@ mips_elf_perform_relocation (struct bfd_
return TRUE;
}
-/* Add room for N relocations to the .rel(a).dyn section in ABFD. */
-
-static void
-mips_elf_allocate_dynamic_relocations (bfd *abfd, struct bfd_link_info *info,
- unsigned int n)
-{
- asection *s;
- struct mips_elf_link_hash_table *htab;
-
- htab = mips_elf_hash_table (info);
- s = mips_elf_rel_dyn_section (info, FALSE);
- BFD_ASSERT (s != NULL);
-
- if (htab->is_vxworks)
- s->size += n * MIPS_ELF_RELA_SIZE (abfd);
- else
- {
- if (s->size == 0)
- {
- /* Make room for a null element. */
- s->size += MIPS_ELF_REL_SIZE (abfd);
- ++s->reloc_count;
- }
- s->size += n * MIPS_ELF_REL_SIZE (abfd);
- }
-}
-
/* Create a rel.dyn relocation for the dynamic linker to resolve. REL
is the original relocation, which is now being transformed into a
dynamic relocation. The ADDENDP is adjusted if necessary; the
@@ -7547,18 +7635,8 @@ _bfd_mips_elf_adjust_dynamic_symbol (str
executable and the shared library. */
if (!h->def_regular)
{
- /* We need .stub section. */
- h->root.u.def.section = htab->sstubs;
- h->root.u.def.value = htab->sstubs->size;
-
- /* XXX Write this stub address somewhere. */
- h->plt.offset = htab->sstubs->size;
-
- /* Make room for this stub code. */
- htab->sstubs->size += htab->function_stub_size;
-
- /* The last half word of the stub will be filled with the index
- of this symbol in .dynsym section. */
+ hmips->needs_lazy_stub = TRUE;
+ htab->lazy_stub_count++;
return TRUE;
}
}
@@ -7757,15 +7835,6 @@ _bfd_mips_elf_always_size_sections (bfd
struct bfd_link_info *info)
{
asection *ri;
-
- asection *s;
- struct mips_got_info *g;
- int i;
- bfd_size_type loadable_size = 0;
- bfd_size_type page_gotno;
- bfd_size_type dynsymcount;
- bfd *sub;
- struct mips_elf_count_tls_arg count_tls_arg;
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
@@ -7780,29 +7849,40 @@ _bfd_mips_elf_always_size_sections (bfd
mips_elf_link_hash_traverse (mips_elf_hash_table (info),
mips_elf_check_mips16_stubs, info);
+ return TRUE;
+}
+
+/* If the link uses a GOT, lay it out and work out its size. */
+
+static bfd_boolean
+mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
+{
+ bfd *dynobj;
+ asection *s;
+ struct mips_got_info *g;
+ int i;
+ bfd_size_type loadable_size = 0;
+ bfd_size_type page_gotno;
+ bfd *sub;
+ struct mips_elf_count_tls_arg count_tls_arg;
+ struct mips_elf_link_hash_table *htab;
+
+ htab = mips_elf_hash_table (info);
s = htab->sgot;
if (s == NULL)
return TRUE;
+ dynobj = elf_hash_table (info)->dynobj;
g = htab->got_info;
- /* Calculate the total loadable size of the output. That
- will give us the maximum number of GOT_PAGE entries
- required. */
- for (sub = info->input_bfds; sub; sub = sub->link_next)
- {
- asection *subsection;
+ /* Replace entries for indirect and warning symbols with entries for
+ the target symbol. */
+ if (!mips_elf_resolve_final_got_entries (g))
+ return FALSE;
- for (subsection = sub->sections;
- subsection;
- subsection = subsection->next)
- {
- if ((subsection->flags & SEC_ALLOC) == 0)
- continue;
- loadable_size += ((subsection->size + 0xf)
- &~ (bfd_size_type) 0xf);
- }
- }
+ /* Count the number of forced-local entries. */
+ elf_link_hash_traverse (elf_hash_table (info),
+ mips_elf_count_forced_local_got_symbols, g);
/* There has to be a global GOT entry for every symbol with
a dynamic symbol table index of DT_MIPS_GOTSYM or
@@ -7819,22 +7899,23 @@ _bfd_mips_elf_always_size_sections (bfd
relocations, then GLOBAL_GOTSYM will be NULL. */
i = 0;
- /* Get a worst-case estimate of the number of dynamic symbols needed.
- At this point, dynsymcount does not account for section symbols
- and count_section_dynsyms may overestimate the number that will
- be needed. */
- dynsymcount = (elf_hash_table (info)->dynsymcount
- + count_section_dynsyms (output_bfd, info));
-
- /* Determine the size of one stub entry. */
- htab->function_stub_size = (dynsymcount > 0x10000
- ? MIPS_FUNCTION_STUB_BIG_SIZE
- : MIPS_FUNCTION_STUB_NORMAL_SIZE);
+ /* Calculate the total loadable size of the output. That
+ will give us the maximum number of GOT_PAGE entries
+ required. */
+ for (sub = info->input_bfds; sub; sub = sub->link_next)
+ {
+ asection *subsection;
- /* In the worst case, we'll get one stub per dynamic symbol, plus
- one to account for the dummy entry at the end required by IRIX
- rld. */
- loadable_size += htab->function_stub_size * (i + 1);
+ for (subsection = sub->sections;
+ subsection;
+ subsection = subsection->next)
+ {
+ if ((subsection->flags & SEC_ALLOC) == 0)
+ continue;
+ loadable_size += ((subsection->size + 0xf)
+ &~ (bfd_size_type) 0xf);
+ }
+ }
if (htab->is_vxworks)
/* There's no need to allocate page entries for VxWorks; R_MIPS*_GOT16
@@ -7868,27 +7949,120 @@ _bfd_mips_elf_always_size_sections (bfd
g->tls_gotno += count_tls_arg.needed;
s->size += g->tls_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
- mips_elf_resolve_final_got_entries (g);
-
/* VxWorks does not support multiple GOTs. It initializes $gp to
__GOTT_BASE__[__GOTT_INDEX__], the value of which is set by the
dynamic loader. */
- if (!htab->is_vxworks && s->size > MIPS_ELF_GOT_MAX_SIZE (info))
+ if (htab->is_vxworks)
+ {
+ /* VxWorks executables do not need a GOT. */
+ if (info->shared)
+ {
+ /* Each VxWorks GOT entry needs an explicit relocation. */
+ unsigned int count;
+
+ count = g->global_gotno + g->local_gotno - MIPS_RESERVED_GOTNO (info);
+ if (count)
+ mips_elf_allocate_dynamic_relocations (dynobj, info, count);
+ }
+ }
+ else if (s->size > MIPS_ELF_GOT_MAX_SIZE (info))
{
if (!mips_elf_multi_got (output_bfd, info, s, page_gotno))
return FALSE;
}
else
{
- /* Set up TLS entries for the first GOT. */
+ struct mips_elf_count_tls_arg arg;
+
+ /* Set up TLS entries. */
g->tls_assigned_gotno = g->global_gotno + g->local_gotno;
htab_traverse (g->got_entries, mips_elf_initialize_tls_index, g);
+
+ /* Allocate room for the TLS relocations. */
+ arg.info = info;
+ arg.needed = 0;
+ htab_traverse (g->got_entries, mips_elf_count_local_tls_relocs, &arg);
+ elf_link_hash_traverse (elf_hash_table (info),
+ mips_elf_count_global_tls_relocs,
+ &arg);
+ if (arg.needed)
+ mips_elf_allocate_dynamic_relocations (dynobj, info, arg.needed);
}
- htab->computed_got_sizes = TRUE;
return TRUE;
}
+/* Estimate the size of the .MIPS.stubs section. */
+
+static void
+mips_elf_estimate_stub_size (bfd *output_bfd, struct bfd_link_info *info)
+{
+ struct mips_elf_link_hash_table *htab;
+ bfd_size_type dynsymcount;
+
+ htab = mips_elf_hash_table (info);
+ if (htab->lazy_stub_count == 0)
+ return;
+
+ /* IRIX rld assumes that a function stub isn't at the end of the .text
+ section, so add a dummy entry to the end. */
+ htab->lazy_stub_count++;
+
+ /* Get a worst-case estimate of the number of dynamic symbols needed.
+ At this point, dynsymcount does not account for section symbols
+ and count_section_dynsyms may overestimate the number that will
+ be needed. */
+ dynsymcount = (elf_hash_table (info)->dynsymcount
+ + count_section_dynsyms (output_bfd, info));
+
+ /* Determine the size of one stub entry. */
+ htab->function_stub_size = (dynsymcount > 0x10000
+ ? MIPS_FUNCTION_STUB_BIG_SIZE
+ : MIPS_FUNCTION_STUB_NORMAL_SIZE);
+
+ htab->sstubs->size = htab->lazy_stub_count * htab->function_stub_size;
+}
+
+/* A mips_elf_link_hash_traverse callback for which DATA points to the
+ MIPS hash table. If H needs a traditional MIPS lazy-binding stub,
+ allocate an entry in the stubs section. */
+
+static bfd_boolean
+mips_elf_allocate_lazy_stub (struct mips_elf_link_hash_entry *h, void **data)
+{
+ struct mips_elf_link_hash_table *htab;
+
+ htab = (struct mips_elf_link_hash_table *) data;
+ if (h->needs_lazy_stub)
+ {
+ h->root.root.u.def.section = htab->sstubs;
+ h->root.root.u.def.value = htab->sstubs->size;
+ h->root.plt.offset = htab->sstubs->size;
+ htab->sstubs->size += htab->function_stub_size;
+ }
+ return TRUE;
+}
+
+/* Allocate offsets in the stubs section to each symbol that needs one.
+ Set the final size of the .MIPS.stub section. */
+
+static void
+mips_elf_lay_out_lazy_stubs (struct bfd_link_info *info)
+{
+ struct mips_elf_link_hash_table *htab;
+
+ htab = mips_elf_hash_table (info);
+ if (htab->lazy_stub_count == 0)
+ return;
+
+ htab->sstubs->size = 0;
+ mips_elf_link_hash_traverse (mips_elf_hash_table (info),
+ mips_elf_allocate_lazy_stub, htab);
+ htab->sstubs->size += htab->function_stub_size;
+ BFD_ASSERT (htab->sstubs->size
+ == htab->lazy_stub_count * htab->function_stub_size);
+}
+
/* Set the sizes of the dynamic sections. */
bfd_boolean
@@ -7896,7 +8070,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd
struct bfd_link_info *info)
{
bfd *dynobj;
- asection *s, *sreldyn;
+ asection *s;
bfd_boolean reltext;
struct mips_elf_link_hash_table *htab;
@@ -7918,19 +8092,20 @@ _bfd_mips_elf_size_dynamic_sections (bfd
}
}
- /* IRIX rld assumes that the function stub isn't at the end
- of the .text section, so add a dummy entry to the end. */
- if (htab->sstubs && htab->sstubs->size > 0)
- htab->sstubs->size += htab->function_stub_size;
-
/* Allocate space for global sym dynamic relocs. */
elf_link_hash_traverse (&htab->root, allocate_dynrelocs, (PTR) info);
+ mips_elf_estimate_stub_size (output_bfd, info);
+
+ if (!mips_elf_lay_out_got (output_bfd, info))
+ return FALSE;
+
+ mips_elf_lay_out_lazy_stubs (info);
+
/* The check_relocs and adjust_dynamic_symbol entry points have
determined the sizes of the various dynamic sections. Allocate
memory for them. */
reltext = FALSE;
- sreldyn = NULL;
for (s = dynobj->sections; s != NULL; s = s->next)
{
const char *name;
@@ -7978,88 +8153,6 @@ _bfd_mips_elf_size_dynamic_sections (bfd
info->combreloc = 0;
}
}
- else if (htab->is_vxworks && strcmp (name, ".got") == 0)
- {
- /* Executables do not need a GOT. */
- if (info->shared)
- {
- /* Allocate relocations for all but the reserved entries. */
- unsigned int count;
-
- count = (htab->got_info->global_gotno
- + htab->got_info->local_gotno
- - MIPS_RESERVED_GOTNO (info));
- mips_elf_allocate_dynamic_relocations (dynobj, info, count);
- }
- }
- else if (!htab->is_vxworks && CONST_STRNEQ (name, ".got"))
- {
- /* _bfd_mips_elf_always_size_sections() has already done
- most of the work, but some symbols may have been mapped
- to versions that we must now resolve in the got_entries
- hash tables. */
- struct mips_got_info *gg = htab->got_info;
- struct mips_got_info *g = gg;
- struct mips_elf_set_global_got_offset_arg set_got_offset_arg;
- unsigned int needed_relocs = 0;
-
- if (gg->next)
- {
- set_got_offset_arg.value = MIPS_ELF_GOT_SIZE (output_bfd);
- set_got_offset_arg.info = info;
-
- /* NOTE 2005-02-03: How can this call, or the next, ever
- find any indirect entries to resolve? They were all
- resolved in mips_elf_multi_got. */
- mips_elf_resolve_final_got_entries (gg);
- for (g = gg->next; g && g->next != gg; g = g->next)
- {
- unsigned int save_assign;
-
- mips_elf_resolve_final_got_entries (g);
-
- /* Assign offsets to global GOT entries. */
- save_assign = g->assigned_gotno;
- g->assigned_gotno = g->local_gotno;
- set_got_offset_arg.g = g;
- set_got_offset_arg.needed_relocs = 0;
- htab_traverse (g->got_entries,
- mips_elf_set_global_got_offset,
- &set_got_offset_arg);
- needed_relocs += set_got_offset_arg.needed_relocs;
- BFD_ASSERT (g->assigned_gotno - g->local_gotno
- <= g->global_gotno);
-
- g->assigned_gotno = save_assign;
- if (info->shared)
- {
- needed_relocs += g->local_gotno - g->assigned_gotno;
- BFD_ASSERT (g->assigned_gotno == g->next->local_gotno
- + g->next->global_gotno
- + g->next->tls_gotno
- + MIPS_RESERVED_GOTNO (info));
- }
- }
- }
- else
- {
- struct mips_elf_count_tls_arg arg;
- arg.info = info;
- arg.needed = 0;
-
- htab_traverse (gg->got_entries, mips_elf_count_local_tls_relocs,
- &arg);
- elf_link_hash_traverse (elf_hash_table (info),
- mips_elf_count_global_tls_relocs,
- &arg);
-
- needed_relocs += arg.needed;
- }
-
- if (needed_relocs)
- mips_elf_allocate_dynamic_relocations (dynobj, info,
- needed_relocs);
- }
else if (! info->shared
&& ! mips_elf_hash_table (info)->use_rld_obj_head
&& CONST_STRNEQ (name, ".rld_map"))
@@ -8072,6 +8165,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd
&& CONST_STRNEQ (name, ".compact_rel"))
s->size += mips_elf_hash_table (info)->compact_rel_size;
else if (! CONST_STRNEQ (name, ".init")
+ && s != htab->sgot
&& s != htab->sgotplt
&& s != htab->splt
&& s != htab->sstubs)
@@ -8089,14 +8183,6 @@ _bfd_mips_elf_size_dynamic_sections (bfd
if ((s->flags & SEC_HAS_CONTENTS) == 0)
continue;
- /* Allocate memory for this section last, since we may increase its
- size above. */
- if (strcmp (name, MIPS_ELF_REL_DYN_NAME (info)) == 0)
- {
- sreldyn = s;
- continue;
- }
-
/* Allocate memory for the section contents. */
s->contents = bfd_zalloc (dynobj, s->size);
if (s->contents == NULL)
@@ -8106,17 +8192,6 @@ _bfd_mips_elf_size_dynamic_sections (bfd
}
}
- /* Allocate memory for the .rel(a).dyn section. */
- if (sreldyn != NULL)
- {
- sreldyn->contents = bfd_zalloc (dynobj, sreldyn->size);
- if (sreldyn->contents == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return FALSE;
- }
- }
-
if (elf_hash_table (info)->dynamic_sections_created)
{
/* Add some entries to the .dynamic section. We fill in the
@@ -10193,91 +10268,6 @@ _bfd_mips_elf_copy_indirect_symbol (stru
if (dirmips->tls_type == 0)
dirmips->tls_type = indmips->tls_type;
}
-
-void
-_bfd_mips_elf_hide_symbol (struct bfd_link_info *info,
- struct elf_link_hash_entry *entry,
- bfd_boolean force_local)
-{
- bfd *dynobj;
- struct mips_got_info *g;
- struct mips_elf_link_hash_entry *h;
- struct mips_elf_link_hash_table *htab;
-
- h = (struct mips_elf_link_hash_entry *) entry;
- if (h->forced_local)
- return;
- h->forced_local = force_local;
-
- dynobj = elf_hash_table (info)->dynobj;
- htab = mips_elf_hash_table (info);
- if (dynobj != NULL
- && force_local
- && h->root.type != STT_TLS
- && htab->got_info != NULL)
- {
- g = htab->got_info;
- if (g->next)
- {
- struct mips_got_entry e;
- struct mips_got_info *gg = g;
-
- /* Since we're turning what used to be a global symbol into a
- local one, bump up the number of local entries of each GOT
- that had an entry for it. This will automatically decrease
- the number of global entries, since global_gotno is actually
- the upper limit of global entries. */
- e.abfd = dynobj;
- e.symndx = -1;
- e.d.h = h;
- e.tls_type = 0;
-
- for (g = g->next; g != gg; g = g->next)
- if (htab_find (g->got_entries, &e))
- {
- BFD_ASSERT (g->global_gotno > 0);
- g->local_gotno++;
- g->global_gotno--;
- }
-
- /* If this was a global symbol forced into the primary GOT, we
- no longer need an entry for it. We can't release the entry
- at this point, but we must at least stop counting it as one
- of the symbols that required a forced got entry. */
- if (h->root.got.offset == 2)
- {
- BFD_ASSERT (gg->assigned_gotno > 0);
- gg->assigned_gotno--;
- }
- }
- else if (h->root.got.offset == 1)
- {
- /* check_relocs didn't know that this symbol would be
- forced-local, so add an extra local got entry. */
- g->local_gotno++;
- if (htab->computed_got_sizes)
- {
- /* We'll have treated this symbol as global rather
- than local. */
- BFD_ASSERT (g->global_gotno > 0);
- g->global_gotno--;
- }
- }
- else if (htab->is_vxworks && h->root.needs_plt)
- {
- /* check_relocs didn't know that this symbol would be
- forced-local, so add an extra local got entry. */
- g->local_gotno++;
- if (htab->computed_got_sizes)
- /* The symbol is only used in call relocations, so we'll
- have assumed it only needs a .got.plt entry. Increase
- the size of .got accordingly. */
- htab->sgot->size += MIPS_ELF_GOT_SIZE (dynobj);
- }
- }
-
- _bfd_elf_link_hash_hide_symbol (info, &h->root, force_local);
-}
#define PDR_SIZE 32
@@ -10734,7 +10724,6 @@ _bfd_mips_elf_link_hash_table_create (bf
ret->use_rld_obj_head = FALSE;
ret->rld_value = 0;
ret->mips16_stubs_seen = FALSE;
- ret->computed_got_sizes = FALSE;
ret->is_vxworks = FALSE;
ret->small_data_overflow_reported = FALSE;
ret->srelbss = NULL;
@@ -10748,6 +10737,7 @@ _bfd_mips_elf_link_hash_table_create (bf
ret->got_info = NULL;
ret->plt_header_size = 0;
ret->plt_entry_size = 0;
+ ret->lazy_stub_count = 0;
ret->function_stub_size = 0;
return &ret->root.root;
Index: ld/testsuite/ld-mips-elf/tlsdyn-o32-2.got
===================================================================
--- ld/testsuite/ld-mips-elf/tlsdyn-o32-2.got 2008-08-06 20:18:41.000000000 +0100
+++ ld/testsuite/ld-mips-elf/tlsdyn-o32-2.got 2008-08-06 21:00:51.000000000 +0100
@@ -4,16 +4,16 @@
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
00000000 R_MIPS_NONE \*ABS\*
-10000040 R_MIPS_TLS_DTPMOD32 tlsbin_gd
-10000044 R_MIPS_TLS_DTPREL32 tlsbin_gd
-10000034 R_MIPS_TLS_DTPMOD32 tlsvar_gd
-10000038 R_MIPS_TLS_DTPREL32 tlsvar_gd
-1000003c R_MIPS_TLS_TPREL32 tlsvar_ie
+10000038 R_MIPS_TLS_DTPMOD32 tlsbin_gd
+1000003c R_MIPS_TLS_DTPREL32 tlsbin_gd
+10000030 R_MIPS_TLS_DTPMOD32 tlsvar_gd
+10000034 R_MIPS_TLS_DTPREL32 tlsvar_gd
+1000002c R_MIPS_TLS_TPREL32 tlsvar_ie
10000048 R_MIPS_TLS_TPREL32 tlsbin_ie
Contents of section .got:
- 10000020 00000000 80000000 0040053c 00000001 .*
+ 10000020 00000000 80000000 0040053c 00000000 .*
10000030 00000000 00000000 00000000 00000000 .*
- 10000040 00000000 00000000 00000000 00000000 .*
+ 10000040 00000001 00000000 00000000 00000000 .*
10000050 00000000 00000000 .*
Index: ld/testsuite/ld-mips-elf/tlsdyn-o32-3.got
===================================================================
--- ld/testsuite/ld-mips-elf/tlsdyn-o32-3.got 2008-08-06 20:18:41.000000000 +0100
+++ ld/testsuite/ld-mips-elf/tlsdyn-o32-3.got 2008-08-06 21:00:51.000000000 +0100
@@ -4,16 +4,16 @@
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
00000000 R_MIPS_NONE \*ABS\*
-10000040 R_MIPS_TLS_DTPMOD32 tlsbin_gd
-10000044 R_MIPS_TLS_DTPREL32 tlsbin_gd
-10000034 R_MIPS_TLS_DTPMOD32 tlsvar_gd
-10000038 R_MIPS_TLS_DTPREL32 tlsvar_gd
-1000003c R_MIPS_TLS_TPREL32 tlsvar_ie
+10000038 R_MIPS_TLS_DTPMOD32 tlsbin_gd
+1000003c R_MIPS_TLS_DTPREL32 tlsbin_gd
+10000030 R_MIPS_TLS_DTPMOD32 tlsvar_gd
+10000034 R_MIPS_TLS_DTPREL32 tlsvar_gd
+1000002c R_MIPS_TLS_TPREL32 tlsvar_ie
10000048 R_MIPS_TLS_TPREL32 tlsbin_ie
Contents of section .got:
- 10000020 00000000 80000000 004005ec 00000001 .*
+ 10000020 00000000 80000000 004005ec 00000000 .*
10000030 00000000 00000000 00000000 00000000 .*
- 10000040 00000000 00000000 00000000 00000000 .*
+ 10000040 00000001 00000000 00000000 00000000 .*
10000050 00000000 00000000 .*
Index: ld/testsuite/ld-mips-elf/tlsdyn-o32-2.d
===================================================================
--- ld/testsuite/ld-mips-elf/tlsdyn-o32-2.d 2008-08-06 20:48:34.000000000 +0100
+++ ld/testsuite/ld-mips-elf/tlsdyn-o32-2.d 2008-08-06 21:00:51.000000000 +0100
@@ -12,19 +12,19 @@ Disassembly of section .text:
.*: 03a0f021 move s8,sp
.*: afbc0000 sw gp,0\(sp\)
.*: 8f998018 lw t9,-32744\(gp\)
- .*: 27848030 addiu a0,gp,-32720
+ .*: 27848028 addiu a0,gp,-32728
.*: 0320f809 jalr t9
.*: 00000000 nop
.*: 8fdc0000 lw gp,0\(s8\)
.*: 00000000 nop
.*: 8f998018 lw t9,-32744\(gp\)
- .*: 27848024 addiu a0,gp,-32732
+ .*: 27848020 addiu a0,gp,-32736
.*: 0320f809 jalr t9
.*: 00000000 nop
.*: 8fdc0000 lw gp,0\(s8\)
.*: 00000000 nop
.*: 8f998018 lw t9,-32744\(gp\)
- .*: 2784801c addiu a0,gp,-32740
+ .*: 27848030 addiu a0,gp,-32720
.*: 0320f809 jalr t9
.*: 00000000 nop
.*: 8fdc0000 lw gp,0\(s8\)
@@ -36,7 +36,7 @@ Disassembly of section .text:
.*: 8f838038 lw v1,-32712\(gp\)
.*: 00000000 nop
.*: 00621821 addu v1,v1,v0
- .*: 8f83802c lw v1,-32724\(gp\)
+ .*: 8f83801c lw v1,-32740\(gp\)
.*: 00000000 nop
.*: 00621821 addu v1,v1,v0
.*: 7c02283b rdhwr v0,\$5
@@ -62,19 +62,19 @@ Disassembly of section .text:
.*: 03a0f021 move s8,sp
.*: afbc0000 sw gp,0\(sp\)
.*: 8f998018 lw t9,-32744\(gp\)
- .*: 27848030 addiu a0,gp,-32720
+ .*: 27848028 addiu a0,gp,-32728
.*: 0320f809 jalr t9
.*: 00000000 nop
.*: 8fdc0000 lw gp,0\(s8\)
.*: 00000000 nop
.*: 8f998018 lw t9,-32744\(gp\)
- .*: 27848024 addiu a0,gp,-32732
+ .*: 27848020 addiu a0,gp,-32736
.*: 0320f809 jalr t9
.*: 00000000 nop
.*: 8fdc0000 lw gp,0\(s8\)
.*: 00000000 nop
.*: 8f998018 lw t9,-32744\(gp\)
- .*: 2784801c addiu a0,gp,-32740
+ .*: 27848030 addiu a0,gp,-32720
.*: 0320f809 jalr t9
.*: 00000000 nop
.*: 8fdc0000 lw gp,0\(s8\)
@@ -86,7 +86,7 @@ Disassembly of section .text:
.*: 8f838038 lw v1,-32712\(gp\)
.*: 00000000 nop
.*: 00621821 addu v1,v1,v0
- .*: 8f83802c lw v1,-32724\(gp\)
+ .*: 8f83801c lw v1,-32740\(gp\)
.*: 00000000 nop
.*: 00621821 addu v1,v1,v0
.*: 7c02283b rdhwr v0,\$5
Index: ld/testsuite/ld-mips-elf/tlsdyn-o32-3.d
===================================================================
--- ld/testsuite/ld-mips-elf/tlsdyn-o32-3.d 2008-08-06 20:48:34.000000000 +0100
+++ ld/testsuite/ld-mips-elf/tlsdyn-o32-3.d 2008-08-06 21:00:51.000000000 +0100
@@ -12,19 +12,19 @@ Disassembly of section .text:
.*: 03a0f021 move s8,sp
.*: afbc0000 sw gp,0\(sp\)
.*: 8f998018 lw t9,-32744\(gp\)
- .*: 27848030 addiu a0,gp,-32720
+ .*: 27848028 addiu a0,gp,-32728
.*: 0320f809 jalr t9
.*: 00000000 nop
.*: 8fdc0000 lw gp,0\(s8\)
.*: 00000000 nop
.*: 8f998018 lw t9,-32744\(gp\)
- .*: 27848024 addiu a0,gp,-32732
+ .*: 27848020 addiu a0,gp,-32736
.*: 0320f809 jalr t9
.*: 00000000 nop
.*: 8fdc0000 lw gp,0\(s8\)
.*: 00000000 nop
.*: 8f998018 lw t9,-32744\(gp\)
- .*: 2784801c addiu a0,gp,-32740
+ .*: 27848030 addiu a0,gp,-32720
.*: 0320f809 jalr t9
.*: 00000000 nop
.*: 8fdc0000 lw gp,0\(s8\)
@@ -36,7 +36,7 @@ Disassembly of section .text:
.*: 8f838038 lw v1,-32712\(gp\)
.*: 00000000 nop
.*: 00621821 addu v1,v1,v0
- .*: 8f83802c lw v1,-32724\(gp\)
+ .*: 8f83801c lw v1,-32740\(gp\)
.*: 00000000 nop
.*: 00621821 addu v1,v1,v0
.*: 7c02283b rdhwr v0,\$5
@@ -58,19 +58,19 @@ Disassembly of section .text:
.*: 03a0f021 move s8,sp
.*: afbc0000 sw gp,0\(sp\)
.*: 8f998018 lw t9,-32744\(gp\)
- .*: 27848030 addiu a0,gp,-32720
+ .*: 27848028 addiu a0,gp,-32728
.*: 0320f809 jalr t9
.*: 00000000 nop
.*: 8fdc0000 lw gp,0\(s8\)
.*: 00000000 nop
.*: 8f998018 lw t9,-32744\(gp\)
- .*: 27848024 addiu a0,gp,-32732
+ .*: 27848020 addiu a0,gp,-32736
.*: 0320f809 jalr t9
.*: 00000000 nop
.*: 8fdc0000 lw gp,0\(s8\)
.*: 00000000 nop
.*: 8f998018 lw t9,-32744\(gp\)
- .*: 2784801c addiu a0,gp,-32740
+ .*: 27848030 addiu a0,gp,-32720
.*: 0320f809 jalr t9
.*: 00000000 nop
.*: 8fdc0000 lw gp,0\(s8\)
@@ -82,7 +82,7 @@ Disassembly of section .text:
.*: 8f838038 lw v1,-32712\(gp\)
.*: 00000000 nop
.*: 00621821 addu v1,v1,v0
- .*: 8f83802c lw v1,-32724\(gp\)
+ .*: 8f83801c lw v1,-32740\(gp\)
.*: 00000000 nop
.*: 00621821 addu v1,v1,v0
.*: 7c02283b rdhwr v0,\$5