This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: Ping Re: Patch for MIPS multi-got bug with forced-local symbols
Here is a revised version of this patch
<http://sourceware.org/ml/binutils/2007-09/msg00266.html>. I found a new
related case of failure (with both unpatched binutils and binutils with my
previous patch applied), as shown by the second new test added, and fixed
by the
+ && !entry->d.h->forced_local
added to mips_elf_set_global_got_offset.
Tested with cross to mips-linux-gnu. OK to commit?
bfd:
2007-09-28 Joseph Myers <joseph@codesourcery.com>
* elfxx-mips.c (struct mips_got_info): Add forced_local_count.
(struct mips_elf_hash_sort_data): Add forced_local and
prev_forced_local.
(mips_elf_sort_hash_table): Subtract g->forced_local_count in
computing hsd.min_got_dynindx. Initialize hsd.forced_local and
hsd.prev_forced_local. Set g->forced_local_count after sorting.
(mips_elf_sort_hash_table_f): Count forced-local symbols. Handle
them as unreferenced where allowed for in calculation of
min_got_dynindx.
(mips_elf_make_got_per_bfd, mips_elf_multi_got,
mips_elf_create_got_section): Initialize forced_local_count.
(_bfd_mips_elf_always_size_sections): Subtract forced_local_count
in calculating global_gotno.
(_bfd_mips_elf_final_link): Subtract forced_local_count in
assertion.
(mips_elf_set_global_got_offset): Check for forced-local symbols
before assigning global GOT offsets.
ld/testsuite:
2007-09-28 Joseph Myers <joseph@codesourcery.com>
* ld-mips-elf/multi-got-hidden-1.d,
ld-mips-elf/multi-got-hidden-1.s,
ld-mips-elf/multi-got-hidden-2.d,
ld-mips-elf/multi-got-hidden-2.s: New.
* ld-mips-elf/mips-elf.exp: Run multi-got-hidden tests.
(To keep down the size of this patch, multi-got-hidden-2.s is omitted;
it's the result of "cat multi-got-1-2.s multi-got-hidden-1.s".)
Index: bfd/elfxx-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
retrieving revision 1.215
diff -u -r1.215 elfxx-mips.c
--- bfd/elfxx-mips.c 26 Sep 2007 13:45:32 -0000 1.215
+++ bfd/elfxx-mips.c 28 Sep 2007 22:40:43 -0000
@@ -143,6 +143,9 @@
because a single-GOT link may have multiple hash table entries
for the LDM. It does not get initialized in multi-GOT mode. */
bfd_vma tls_ldm_offset;
+ /* The number of forced-local entries being counted as global found
+ during sorting. */
+ unsigned int forced_local_count;
};
/* Map an input bfd to a got in a multi-got link. */
@@ -234,6 +237,10 @@
/* The greatest dynamic symbol table index not corresponding to a
symbol without a GOT entry. */
long max_non_got_dynindx;
+ /* The number of forced-local entries being counted as global. */
+ long forced_local;
+ /* The number of such entries found previously. */
+ long prev_forced_local;
};
/* The MIPS ELF linker needs additional information for each symbol in
@@ -2757,8 +2764,10 @@
referenced, we move them to the end of the GOT, so that they
don't prevent other entries that are referenced from getting
too large offsets. */
- - (g->next ? g->assigned_gotno : 0);
+ - (g->next ? g->assigned_gotno : 0) - g->forced_local_count;
hsd.max_non_got_dynindx = max_local;
+ hsd.forced_local = 0;
+ hsd.prev_forced_local = g->forced_local_count;
mips_elf_link_hash_traverse (((struct mips_elf_link_hash_table *)
elf_hash_table (info)),
mips_elf_sort_hash_table_f,
@@ -2774,6 +2783,8 @@
table index in the GOT. */
g->global_gotsym = hsd.low;
+ g->forced_local_count = hsd.forced_local;
+
return TRUE;
}
@@ -2794,6 +2805,9 @@
if (h->root.dynindx == -1)
return TRUE;
+ if (h->forced_local)
+ hsd->forced_local++;
+
/* Global symbols that need GOT entries that are not explicitly
referenced are marked with got offset 2. Those that are
referenced get a 1, and those that don't need GOT entries get
@@ -2812,8 +2826,13 @@
{
BFD_ASSERT (h->tls_type == GOT_NORMAL);
- h->root.dynindx = --hsd->min_got_dynindx;
- hsd->low = (struct elf_link_hash_entry *) h;
+ if (h->forced_local && hsd->forced_local <= hsd->prev_forced_local)
+ h->root.dynindx = hsd->max_unref_got_dynindx++;
+ else
+ {
+ h->root.dynindx = --hsd->min_got_dynindx;
+ hsd->low = (struct elf_link_hash_entry *) h;
+ }
}
return TRUE;
@@ -3044,6 +3063,7 @@
g->tls_gotno = 0;
g->tls_assigned_gotno = 0;
g->tls_ldm_offset = MINUS_ONE;
+ g->forced_local_count = 0;
g->got_entries = htab_try_create (1, mips_elf_multi_got_entry_hash,
mips_elf_multi_got_entry_eq, NULL);
if (g->got_entries == NULL)
@@ -3269,6 +3289,7 @@
if (entry->abfd != NULL && entry->symndx == -1
&& entry->d.h->root.dynindx != -1
+ && !entry->d.h->forced_local
&& entry->d.h->tls_type == GOT_NORMAL)
{
if (g)
@@ -3451,6 +3472,7 @@
g->next->assigned_gotno = 0;
g->next->tls_assigned_gotno = 0;
g->next->tls_ldm_offset = MINUS_ONE;
+ g->next->forced_local_count = 0;
g->next->got_entries = htab_try_create (1, mips_elf_multi_got_entry_hash,
mips_elf_multi_got_entry_eq,
NULL);
@@ -3816,6 +3838,7 @@
g->bfd2got = NULL;
g->next = NULL;
g->tls_ldm_offset = MINUS_ONE;
+ g->forced_local_count = 0;
g->got_entries = htab_try_create (1, mips_elf_got_entry_hash,
mips_elf_got_entry_eq, NULL);
if (g->got_entries == NULL)
@@ -7254,7 +7277,8 @@
return FALSE;
if (g->global_gotsym != NULL)
- i = elf_hash_table (info)->dynsymcount - g->global_gotsym->dynindx;
+ i = elf_hash_table (info)->dynsymcount - g->global_gotsym->dynindx
+ - g->forced_local_count;
else
/* If there are no global symbols, or none requiring
relocations, then GLOBAL_GOTSYM will be NULL. */
@@ -10309,7 +10333,8 @@
if (g->global_gotsym != NULL)
BFD_ASSERT ((elf_hash_table (info)->dynsymcount
- - g->global_gotsym->dynindx)
+ - g->global_gotsym->dynindx
+ - g->forced_local_count)
<= g->global_gotno);
}
Index: ld/testsuite/ld-mips-elf/mips-elf.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-mips-elf/mips-elf.exp,v
retrieving revision 1.47
diff -u -r1.47 mips-elf.exp
--- ld/testsuite/ld-mips-elf/mips-elf.exp 13 Aug 2007 21:16:39 -0000 1.47
+++ ld/testsuite/ld-mips-elf/mips-elf.exp 28 Sep 2007 22:40:44 -0000
@@ -68,6 +68,8 @@
if { $linux_gnu } {
run_dump_test "multi-got-1"
run_dump_test "multi-got-no-shared"
+ run_dump_test "multi-got-hidden-1"
+ run_dump_test "multi-got-hidden-2"
}
if $has_newabi {
Index: ld/testsuite/ld-mips-elf/multi-got-hidden-1.d
===================================================================
RCS file: ld/testsuite/ld-mips-elf/multi-got-hidden-1.d
diff -N ld/testsuite/ld-mips-elf/multi-got-hidden-1.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-mips-elf/multi-got-hidden-1.d 28 Sep 2007 22:40:44 -0000
@@ -0,0 +1,8 @@
+#name: MIPS multi-got-hidden-1
+#as: -EB -32 -KPIC
+#source: multi-got-1-1.s
+#source: multi-got-1-2.s
+#source: multi-got-hidden-1.s
+#ld: -melf32btsmip -e 0
+#objdump: -dr
+#pass
Index: ld/testsuite/ld-mips-elf/multi-got-hidden-1.s
===================================================================
RCS file: ld/testsuite/ld-mips-elf/multi-got-hidden-1.s
diff -N ld/testsuite/ld-mips-elf/multi-got-hidden-1.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-mips-elf/multi-got-hidden-1.s 28 Sep 2007 22:40:44 -0000
@@ -0,0 +1,5 @@
+.hidden __init_array_end
+.hidden __init_array_start
+sym_3_1:
+la $2, __init_array_start
+la $2, __init_array_end
Index: ld/testsuite/ld-mips-elf/multi-got-hidden-2.d
===================================================================
RCS file: ld/testsuite/ld-mips-elf/multi-got-hidden-2.d
diff -N ld/testsuite/ld-mips-elf/multi-got-hidden-2.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-mips-elf/multi-got-hidden-2.d 28 Sep 2007 22:40:44 -0000
@@ -0,0 +1,7 @@
+#name: MIPS multi-got-hidden-2
+#as: -EB -32 -KPIC
+#source: multi-got-1-1.s
+#source: multi-got-hidden-2.s
+#ld: -melf32btsmip -e 0
+#objdump: -dr
+#pass
--
Joseph S. Myers
joseph@codesourcery.com