This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Hidden dynamic symbols
- From: Paul Brook <paul at codesourcery dot com>
- To: binutils at sources dot redhat dot com
- Date: Wed, 9 Feb 2005 17:42:26 +0000
- Subject: Hidden dynamic symbols
- Organization: CodeSourcery
The elf spec says that dynamic symbols with STV_HIDDEN or STV_INTERNAL
visibility must either be removed or given STB_LOCAL binding.
We currently get this wrong when a hidden/internal symbol is provided by a
linker script.
The attached patch fixes this by forcing such symbols to be local, and
modifying the symbol renumbering to cope with this. I chose this alternative
because (a) it seemed simpler, and (b) I have a target that needs to output
dynamic relocations against these symbols.
Tested on i686-linux --enable-targets=all.
Ok?
Paul
2005-02-09 Paul Brook <paul@codesourcery.com>
* elflink.c (bfd_elf_record_link_assignment): Make hidden and internal
symbols local.
(elf_link_renumber_hash_table_dynsyms): Ignore local symbols.
(elf_link_renumber_local_hash_table_dynsyms): New function.
(_bfd_elf_link_renumber_dynsyms): Number local dynamic symbols.
ld/testsuite/
* ld-elfvsb/hidden2.s: New file
* ld-elfvsb/hidden2.d: New file
* ld-elfvsb/hidden2.ld: New file
Index: bfd/elflink.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/elflink.c,v
retrieving revision 1.131
diff -u -p -r1.131 elflink.c
--- bfd/elflink.c 8 Feb 2005 13:33:56 -0000 1.131
+++ bfd/elflink.c 9 Feb 2005 17:13:56 -0000
@@ -484,6 +484,14 @@ bfd_elf_record_link_assignment (bfd *out
h->def_regular = 1;
+ /* STV_HIDDEN and STV_INTERNAL symbols must be STB_LOCAL in shared objects
+ and executables. */
+ if (!info->relocatable
+ && h->dynindx != -1
+ && (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
+ || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL))
+ h->forced_local = 1;
+
if ((h->def_dynamic
|| h->ref_dynamic
|| info->shared)
@@ -624,6 +632,31 @@ elf_link_renumber_hash_table_dynsyms (st
if (h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ if (h->forced_local)
+ return TRUE;
+
+ if (h->dynindx != -1)
+ h->dynindx = ++(*count);
+
+ return TRUE;
+}
+
+
+/* Like elf_link_renumber_hash_table_dynsyms, but just number symbols with
+ STB_LOCAL binding. */
+
+static bfd_boolean
+elf_link_renumber_local_hash_table_dynsyms (struct elf_link_hash_entry *h,
+ void *data)
+{
+ size_t *count = data;
+
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ if (!h->forced_local)
+ return TRUE;
+
if (h->dynindx != -1)
h->dynindx = ++(*count);
@@ -667,9 +700,10 @@ _bfd_elf_link_omit_section_dynsym (bfd *
}
/* Assign dynsym indices. In a shared library we generate a section
- symbol for each output section, which come first. Next come all of
- the back-end allocated local dynamic syms, followed by the rest of
- the global symbols. */
+ symbol for each output section, which come first. Next come symbols
+ which have been forced to local binding. Then all of the back-end
+ allocated local dynamic syms, followed by the rest of the global
+ symbols. */
unsigned long
_bfd_elf_link_renumber_dynsyms (bfd *output_bfd, struct bfd_link_info *info)
@@ -687,6 +721,10 @@ _bfd_elf_link_renumber_dynsyms (bfd *out
elf_section_data (p)->dynindx = ++dynsymcount;
}
+ elf_link_hash_traverse (elf_hash_table (info),
+ elf_link_renumber_local_hash_table_dynsyms,
+ &dynsymcount);
+
if (elf_hash_table (info)->dynlocal)
{
struct elf_link_local_dynamic_entry *p;
Index: ld/testsuite/ld-elfvsb/hidden2.d
===================================================================
RCS file: ld/testsuite/ld-elfvsb/hidden2.d
diff -N ld/testsuite/ld-elfvsb/hidden2.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-elfvsb/hidden2.d 9 Feb 2005 17:13:27 -0000
@@ -0,0 +1,9 @@
+#source: hidden2.s
+#ld: -shared -T hidden2.ld
+#readelf: -Ds
+# It is also ok to remove this symbol, but we currently make it local.
+
+Symbol table for image:
+#...
+[ ]*[0-9]+ +[0-9]+: [0-9a-fA-F]* +0 NOTYPE LOCAL HIDDEN +ABS foo
+#pass
Index: ld/testsuite/ld-elfvsb/hidden2.ld
===================================================================
RCS file: ld/testsuite/ld-elfvsb/hidden2.ld
diff -N ld/testsuite/ld-elfvsb/hidden2.ld
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-elfvsb/hidden2.ld 9 Feb 2005 16:27:18 -0000
@@ -0,0 +1,6 @@
+SECTIONS
+{
+ . = 0x1000;
+ PROVIDE (foo = .);
+ .data : { *(.data) }
+}
Index: ld/testsuite/ld-elfvsb/hidden2.s
===================================================================
RCS file: ld/testsuite/ld-elfvsb/hidden2.s
diff -N ld/testsuite/ld-elfvsb/hidden2.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-elfvsb/hidden2.s 9 Feb 2005 16:12:40 -0000
@@ -0,0 +1,4 @@
+ .data
+ .hidden foo
+ .global foo
+ .word foo