This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: Fix uninitialized data in .dynsym
On Tue, Jul 10, 2007 at 09:28:13AM +0930, Alan Modra wrote:
> On Mon, Jul 09, 2007 at 04:25:29PM -0700, H.J. Lu wrote:
> > I don't think it is right. When you do
> >
> > ld -shared -o b.so --defsym foo=0 a.so --version-script a.ver -E
> >
> > shouldn't foo be dynamic?
>
> Yes, it should. So should the following, but I wasn't going to reject
> Joseph's patch just because he didn't fix all the bugs involved.
>
> ld -shared -o b.so --defsym foo=0 -E empty.o
I don't feel comfortable for patches without a testcase. We may break
it aganst later.
Here is a patch to linker defined symbols with version.
I also noticed a bug. In _bfd_elf_merge_symbol, there are
h->root.type = bfd_link_hash_indirect;
h->root.u.i.link = (struct bfd_link_hash_entry *) flip;
(*bed->elf_backend_copy_indirect_symbol) (info, flip, h);
flip->root.u.undef.abfd = h->root.u.undef.abfd;
The problem is
h->root.u.i.link = (struct bfd_link_hash_entry *) flip;
will update h->root.u.undef.abfd since it is a union. I think we
should copy h->root.u.undef.abfd before updating h->root.u.i.link.
H.J.
---
2007-07-09 H.J. Lu <hongjiu.lu@intel.com>
* elflink.c (bfd_elf_record_link_assignment): Handle indirect
symbol.
(_bfd_elf_merge_symbol): Properly update normal symbol when
overriding the versioned symbol from a dynamic library.
--- bfd/elflink.c.bad 2007-07-09 15:39:46.000000000 -0700
+++ bfd/elflink.c 2007-07-09 17:31:59.000000000 -0700
@@ -489,8 +489,9 @@ bfd_elf_record_link_assignment (bfd *out
bfd_boolean provide,
bfd_boolean hidden)
{
- struct elf_link_hash_entry *h;
+ struct elf_link_hash_entry *h, *hv;
struct elf_link_hash_table *htab;
+ const struct elf_backend_data *bed;
if (!is_elf_hash_table (info->hash))
return TRUE;
@@ -500,21 +501,43 @@ bfd_elf_record_link_assignment (bfd *out
if (h == NULL)
return provide;
- /* Since we're defining the symbol, don't let it seem to have not
- been defined. record_dynamic_symbol and size_dynamic_sections
- may depend on this. */
- if (h->root.type == bfd_link_hash_undefweak
- || h->root.type == bfd_link_hash_undefined)
+ switch (h->root.type)
{
+ case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
+ case bfd_link_hash_common:
+ break;
+ case bfd_link_hash_undefweak:
+ case bfd_link_hash_undefined:
+ /* Since we're defining the symbol, don't let it seem to have not
+ been defined. record_dynamic_symbol and size_dynamic_sections
+ may depend on this. */
h->root.type = bfd_link_hash_new;
if (h->root.u.undef.next != NULL || htab->root.undefs_tail == &h->root)
bfd_link_repair_undef_list (&htab->root);
- }
-
- if (h->root.type == bfd_link_hash_new)
- {
+ break;
+ case bfd_link_hash_new:
bfd_elf_link_mark_dynamic_symbol (info, h, NULL);
h->non_elf = 0;
+ break;
+ case bfd_link_hash_indirect:
+ /* We had a versioned symbol in a dynamic library. We make the
+ the versioned symbol point to this one. */
+ bed = get_elf_backend_data (output_bfd);
+ hv = h;
+ while (hv->root.type == bfd_link_hash_indirect
+ || hv->root.type == bfd_link_hash_warning)
+ hv = (struct elf_link_hash_entry *) hv->root.u.i.link;
+ /* We don't need to update h->root.u since linker will set them
+ later. */
+ h->root.type = bfd_link_hash_undefined;
+ hv->root.type = bfd_link_hash_indirect;
+ hv->root.u.i.link = (struct bfd_link_hash_entry *) h;
+ (*bed->elf_backend_copy_indirect_symbol) (info, h, hv);
+ break;
+ case bfd_link_hash_warning:
+ abort ();
+ break;
}
/* If this symbol is being provided by the linker script, and it is
@@ -1456,10 +1479,10 @@ _bfd_elf_merge_symbol (bfd *abfd,
case, we make the versioned symbol point to the normal one. */
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
flip->root.type = h->root.type;
+ flip->root.u.undef.abfd = h->root.u.undef.abfd;
h->root.type = bfd_link_hash_indirect;
h->root.u.i.link = (struct bfd_link_hash_entry *) flip;
(*bed->elf_backend_copy_indirect_symbol) (info, flip, h);
- flip->root.u.undef.abfd = h->root.u.undef.abfd;
if (h->def_dynamic)
{
h->def_dynamic = 0;