[PATCH 1/5] Lay out MIPS GOTs later in the link process
Richard Sandiford
rdsandiford@googlemail.com
Sat Jun 28 16:47:00 GMT 2008
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?
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-06-28 17:14:17.000000000 +0100
+++ bfd/elf32-mips.c 2008-06-28 17:14:36.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-06-28 17:14:17.000000000 +0100
+++ bfd/elfn32-mips.c 2008-06-28 17:14:36.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-06-28 17:14:17.000000000 +0100
+++ bfd/elf64-mips.c 2008-06-28 17:14:36.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-06-28 17:09:14.000000000 +0100
+++ bfd/elfxx-mips.h 2008-06-28 17:14:36.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-06-28 17:14:35.000000000 +0100
+++ bfd/elfxx-mips.c 2008-06-28 17:14:36.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;
}
@@ -5056,33 +5171,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
@@ -7491,18 +7579,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;
}
}
@@ -7701,15 +7779,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);
@@ -7724,29 +7793,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
@@ -7763,22 +7843,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
@@ -7812,27 +7893,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
@@ -7840,7 +8014,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;
@@ -7862,16 +8036,17 @@ _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;
+ 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;
@@ -7919,88 +8094,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"))
@@ -8013,6 +8106,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)
@@ -8030,14 +8124,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)
@@ -8047,17 +8133,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
@@ -10136,91 +10211,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
@@ -10677,7 +10667,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;
@@ -10691,6 +10680,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-06-28 17:09:14.000000000 +0100
+++ ld/testsuite/ld-mips-elf/tlsdyn-o32-2.got 2008-06-28 17:14:36.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-06-28 17:09:14.000000000 +0100
+++ ld/testsuite/ld-mips-elf/tlsdyn-o32-3.got 2008-06-28 17:14:36.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-06-28 17:14:30.000000000 +0100
+++ ld/testsuite/ld-mips-elf/tlsdyn-o32-2.d 2008-06-28 17:14:36.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-06-28 17:14:30.000000000 +0100
+++ ld/testsuite/ld-mips-elf/tlsdyn-o32-3.d 2008-06-28 17:14:36.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
More information about the Binutils
mailing list