This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
PATCH: Fix MIPS DT_MIPS_UNREFEXTNO
- From: "H. J. Lu" <hjl at lucon dot org>
- To: binutils at sources dot redhat dot com
- Date: Wed, 16 Mar 2005 13:57:40 -0800
- Subject: PATCH: Fix MIPS DT_MIPS_UNREFEXTNO
DT_MIPS_UNREFEXTNO should hold an index into the dynamic symbol
table. The index is the entry of the first external symbol that is not
referenced within the object. We just put output section count there.
I don't think it is right. Also we may leave a gap between the GOT and
non-GOT symbols. This patch tries to fix them.
H.J.
----
bfd/
2005-03-16 H.J. Lu <hongjiu.lu@intel.com>
* elfxx-mips.c (mips_got_info): Add first_unref_global_dynindx.
(mips_elf_hash_sort_data): Add min_non_got_dynindx.
(mips_elf_sort_hash_table_1): New.
(mips_elf_sort_hash_table): Call mips_elf_sort_hash_table_1 to
make sure there is no gap between the GOT and non-GOT symbols.
Set first_unref_global_dynindx from min_non_got_dynindx.
(mips_elf_sort_hash_table_f): Set min_non_got_dynindx.
(_bfd_mips_elf_finish_dynamic_sections): Set DT_MIPS_UNREFEXTNO
with first_unref_global_dynindx.
(_bfd_mips_elf_final_link): Don't count sections. Pass 1 to
mips_elf_sort_hash_table.
ld/testsuite/
2005-03-16 H.J. Lu <hongjiu.lu@intel.com>
* ld-mips-elf/multi-got-1.d: Update MIPS_UNREFEXTNO.
* ld-mips-elf/tls-multi-got-1.r: Likewise.
--- binutils/bfd/elfxx-mips.c.unref 2005-03-16 11:44:25.000000000 -0800
+++ binutils/bfd/elfxx-mips.c 2005-03-16 13:12:11.441612984 -0800
@@ -85,6 +85,10 @@ struct mips_got_info
/* The global symbol in the GOT with the lowest index in the dynamic
symbol table. */
struct elf_link_hash_entry *global_gotsym;
+ /* The index into the dynamic symbol table which is the entry of the
+ first external symbol that is not referenced within the same
+ object. */
+ long first_unref_global_dynindx;
/* The number of global .got entries. */
unsigned int global_gotno;
/* The number of .got slots used for TLS. */
@@ -200,6 +204,9 @@ struct mips_elf_hash_sort_data
/* The greatest dynamic symbol table index not corresponding to a
symbol without a GOT entry. */
long max_non_got_dynindx;
+ /* The least dynamic symbol table index not corresponding to a
+ symbol without a GOT entry. */
+ long min_non_got_dynindx;
};
/* The MIPS ELF linker needs additional information for each symbol in
@@ -2523,20 +2530,15 @@ mips_elf_create_local_got_entry (bfd *ab
_bfd_mips_elf_size_dynamic_sections, this value is 1. Afterward, the
section symbols are added and the count is higher. */
-static bfd_boolean
-mips_elf_sort_hash_table (struct bfd_link_info *info, unsigned long max_local)
-{
- struct mips_elf_hash_sort_data hsd;
- struct mips_got_info *g;
- bfd *dynobj;
-
- dynobj = elf_hash_table (info)->dynobj;
-
- g = mips_elf_got_info (dynobj, NULL);
-
- hsd.low = NULL;
- hsd.max_unref_got_dynindx =
- hsd.min_got_dynindx = elf_hash_table (info)->dynsymcount
+static void
+mips_elf_sort_hash_table_1 (struct bfd_link_info *info,
+ unsigned long max_local,
+ struct mips_got_info *g,
+ struct mips_elf_hash_sort_data *hsd)
+{
+ hsd->low = NULL;
+ hsd->max_unref_got_dynindx =
+ hsd->min_got_dynindx = elf_hash_table (info)->dynsymcount
/* In the multi-got case, assigned_gotno of the master got_info
indicate the number of entries that aren't referenced in the
primary GOT, but that must have entries because there are
@@ -2545,15 +2547,38 @@ mips_elf_sort_hash_table (struct bfd_lin
don't prevent other entries that are referenced from getting
too large offsets. */
- (g->next ? g->assigned_gotno : 0);
- hsd.max_non_got_dynindx = max_local;
+ hsd->min_non_got_dynindx = 0;
+ hsd->max_non_got_dynindx = max_local;
mips_elf_link_hash_traverse (((struct mips_elf_link_hash_table *)
elf_hash_table (info)),
mips_elf_sort_hash_table_f,
- &hsd);
+ hsd);
+}
+
+static bfd_boolean
+mips_elf_sort_hash_table (struct bfd_link_info *info,
+ unsigned long max_local)
+{
+ struct mips_elf_hash_sort_data hsd;
+ struct mips_got_info *g;
+ bfd *dynobj;
+
+ dynobj = elf_hash_table (info)->dynobj;
+
+ g = mips_elf_got_info (dynobj, NULL);
+
+ mips_elf_sort_hash_table_1 (info, max_local, g, &hsd);
+
+ /* There should be no gap between the GOT and non-GOT symbols. */
+ if (hsd.max_non_got_dynindx < hsd.min_got_dynindx)
+ mips_elf_sort_hash_table_1 (info, (max_local
+ + hsd.min_got_dynindx
+ - hsd.max_non_got_dynindx),
+ g, &hsd);
/* There should have been enough room in the symbol table to
accommodate both the GOT and non-GOT symbols. */
- BFD_ASSERT (hsd.max_non_got_dynindx <= hsd.min_got_dynindx);
+ BFD_ASSERT (hsd.max_non_got_dynindx == hsd.min_got_dynindx);
BFD_ASSERT ((unsigned long)hsd.max_unref_got_dynindx
<= elf_hash_table (info)->dynsymcount);
@@ -2561,6 +2586,8 @@ mips_elf_sort_hash_table (struct bfd_lin
table index in the GOT. */
g->global_gotsym = hsd.low;
+ g->first_unref_global_dynindx = hsd.min_non_got_dynindx;
+
return TRUE;
}
@@ -2594,7 +2621,12 @@ mips_elf_sort_hash_table_f (struct mips_
h->root.dynindx = hsd->max_unref_got_dynindx++;
}
else if (h->root.got.offset != 1)
- h->root.dynindx = hsd->max_non_got_dynindx++;
+ {
+ /* Record it for DT_MIPS_UNREFEXTNO. */
+ if (hsd->min_non_got_dynindx == 0)
+ hsd->min_non_got_dynindx = hsd->max_non_got_dynindx;
+ h->root.dynindx = hsd->max_non_got_dynindx++;
+ }
else
{
BFD_ASSERT (h->tls_type == GOT_NORMAL);
@@ -7632,7 +7664,7 @@ _bfd_mips_elf_finish_dynamic_sections (b
/* The index into the dynamic symbol table which is the
entry of the first external symbol that is not
referenced within the same object. */
- dyn.d_un.d_val = bfd_count_sections (output_bfd) + 1;
+ dyn.d_un.d_val = gg->first_unref_global_dynindx;
break;
case DT_MIPS_GOTSYM:
@@ -8907,6 +8939,7 @@ _bfd_mips_elf_final_link (bfd *abfd, str
bfd *dynobj;
asection *got;
struct mips_got_info *g;
+#if 0
bfd_size_type dynsecsymcount;
/* When we resort, we must tell mips_elf_sort_hash_table what
@@ -8927,8 +8960,9 @@ _bfd_mips_elf_final_link (bfd *abfd, str
&& !(*bed->elf_backend_omit_section_dynsym) (abfd, info, p))
++ dynsecsymcount;
}
+#endif
- if (! mips_elf_sort_hash_table (info, dynsecsymcount + 1))
+ if (! mips_elf_sort_hash_table (info, 1))
return FALSE;
/* Make sure we didn't grow the global .got region. */
--- binutils/ld/testsuite/ld-mips-elf/multi-got-1.d.unref 2005-02-11 09:28:26.000000000 -0800
+++ binutils/ld/testsuite/ld-mips-elf/multi-got-1.d 2005-03-16 13:00:03.000000000 -0800
@@ -22,7 +22,7 @@ Dynamic section at offset 0xcc contains
0x70000006 \(MIPS_BASE_ADDRESS\) 0
0x7000000a \(MIPS_LOCAL_GOTNO\) 12
0x70000011 \(MIPS_SYMTABNO\) 16399
- 0x70000012 \(MIPS_UNREFEXTNO\) 14
+ 0x70000012 \(MIPS_UNREFEXTNO\) 6
0x70000013 \(MIPS_GOTSYM\) 0xf
0x00000000 \(NULL\) 0x0
--- binutils/ld/testsuite/ld-mips-elf/tls-multi-got-1.r.unref 2005-03-02 13:22:57.000000000 -0800
+++ binutils/ld/testsuite/ld-mips-elf/tls-multi-got-1.r 2005-03-16 13:02:58.000000000 -0800
@@ -16,7 +16,7 @@ Dynamic section at offset 0xec contains
0x70000006 \(MIPS_BASE_ADDRESS\) 0
0x7000000a \(MIPS_LOCAL_GOTNO\) 13
0x70000011 \(MIPS_SYMTABNO\) 20018
- 0x70000012 \(MIPS_UNREFEXTNO\) 15
+ 0x70000012 \(MIPS_UNREFEXTNO\) 7
0x70000013 \(MIPS_GOTSYM\) 0x12
0x0000001e \(FLAGS\) STATIC_TLS
0x00000000 \(NULL\) 0x0