This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] LD: PROVIDE_HIDDEN export class problem


Hi,

 [HPPA maintainers: please comment on note #2 below.  Thanks.]

 While testing the __ehdr_start fix (PR ld/15365) I have realised we have 
a problem with the PROVIDE_HIDDEN linker script command or 
bfd_elf_record_link_assignment that implements this command's export class 
handling.  The issue is the symbol named is always assigned the hidden 
export class even if it was actually created by other means and the 
PROVIDE part of the command wasn't used.

 Here's a proposal to address it.  I think the changes to 
bfd_elf_record_link_assignment should be mostly obvious -- make_hidden is 
only set to true when the HIDDEN command has been used, or otherwise the 
respective PROVIDE_HIDDEN command actually produced the symbol.  The 
latter is the case when the relevant hash table entry's type is either of 
bfd_link_hash_undefweak or bfd_link_hash_undefined, or when the symbol has 
only been defined in a dynamic object but is referred to in the binary
being linked.

 The change to gld${EMULATION_NAME}_find_exp_assignment is trickier, but I 
believe it is correct.  From my observation the case only triggers when 
PROVIDE_HIDDEN has been used outside any section -- in this case the 
symbol is put in the absolute section and a final definition created 
before bfd_elf_record_link_assignment has been called.  Additionally the 
node class of the command is changed in exp_fold_tree_1 from etree_provide 
to etree_provided.  As you can see from code there the hash table entry's 
type is set to bfd_link_hash_defined.

 Therefore for the purpose of handling within 
bfd_elf_record_link_assignment the command can be treated as HIDDEN rather 
than PROVIDE_HIDDEN -- elf_link_hash_lookup won't ever create a new 
symbol, because one already exists, and for the same reason neither 
condition that checks for the symbol not to have been defined in the 
binary being linked will ever trigger.  This avoids the need to change 
bfd_elf_record_link_assignment's API to handle the cases of etree_provide 
and etree_provided separately.  Please let me know if you think there is 
any issue with these implications.

 Suitable test cases are included.  Cases 1, 3, 4 and 6 as well as the 
auxiliary shared object test cover the changes to 
bfd_elf_record_link_assignment.  They fail with our trunk, without the 
change proposed to bfd_elf_record_link_assignment.  Case 5 covers the 
change to gld${EMULATION_NAME}_find_exp_assignment.  It fails if the 
change to bfd_elf_record_link_assignment has been applied, but the change 
to gld${EMULATION_NAME}_find_exp_assignment has not.  Case 2 does not 
trigger a failure either way, but is included for completeness (although 
some MIPS test cases could stand for, we had no specific general case to 
cover PROVIDE_HIDDEN when introduced -- this serves as one).

 Two further notes:

1. The i370-linux target produces assertion failures with the shared 
   library link.  The target is probably broken, there's nothing 
   particularly unusual about that link.  I reckon it's not the first 
   problem I saw with this target.

2. For the hppa64-hp-hpux11.23 and hppa64-linux targets the backend 
   produces .dynsym and .dynstr sections even in static links.  The former 
   section is empty and the latter contains a single zero byte, however 
   the result is they show up in `readelf -s' dumps.  Other dynamic 
   sections are also produced as is a dynamic segment.

   This is probably a bug in these backends; especially for Linux I fail 
   to see a reason why the kernel would require any dynamic file 
   structures in a static executable.  I will appreciate feedback from 
   HPPA maintainers; meanwhile I have tweaked test patterns to discard
   rubbish before static symbol table dumps to avoid failures on these 
   targets (I'd prefer to remove the tweak though, if that is indeed a 
   bug).

 The change has been tested across the 139 targets I use (with 
tic6x-uclinux being a useful recent addition that let me notice the 
`etree_provided' special case) showing no regressions.  OK to apply?

2013-04-29  Maciej W. Rozycki  <macro@codesourcery.com>

	bfd/
	* elflink.c (bfd_elf_record_link_assignment): For symbols that
	have been named in a PROVIDE_HIDDEN command only set the hidden 
	export class if the symbol has been actually set by the command.

	ld/
	* emultempl/elf32.em (gld${EMULATION_NAME}_find_exp_assignment):
	Don't set `provide' to true for nodes of the `etree_provided' 
	class.

	ld/testsuite/
	* ld-elf/provide-hidden-s.nd: New test.
	* ld-elf/provide-hidden-1.nd: New test.
	* ld-elf/provide-hidden-2.nd: New test.
	* ld-elf/provide-hidden-3.nd: New test.
	* ld-elf/provide-hidden-4.nd: New test.
	* ld-elf/provide-hidden-5.nd: New test.
	* ld-elf/provide-hidden-6.nd: New test.
	* ld-elf/provide-hidden-1.ld: New test linker script.
	* ld-elf/provide-hidden-2.ld: New test linker script.
	* ld-elf/provide-hidden-1.s: New test source.
	* ld-elf/provide-hidden-2.s: New test source.
	* ld-elf/provide-hidden.exp: New test script.

  Maciej

binutils-provide-nohidden.diff
Index: binutils-fsf-trunk-quilt/bfd/elflink.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/bfd/elflink.c	2013-04-27 09:48:37.373850846 +0100
+++ binutils-fsf-trunk-quilt/bfd/elflink.c	2013-04-29 22:10:03.773802901 +0100
@@ -501,6 +501,7 @@ bfd_elf_record_link_assignment (bfd *out
 				bfd_boolean provide,
 				bfd_boolean hidden)
 {
+  bfd_boolean make_hidden = !provide && hidden;
   struct elf_link_hash_entry *h, *hv;
   struct elf_link_hash_table *htab;
   const struct elf_backend_data *bed;
@@ -527,6 +528,7 @@ bfd_elf_record_link_assignment (bfd *out
       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);
+      make_hidden = hidden;
       break;
     case bfd_link_hash_new:
       bfd_elf_link_mark_dynamic_symbol (info, h, NULL);
@@ -559,7 +561,10 @@ bfd_elf_record_link_assignment (bfd *out
   if (provide
       && h->def_dynamic
       && !h->def_regular)
-    h->root.type = bfd_link_hash_undefined;
+    {
+      h->root.type = bfd_link_hash_undefined;
+      make_hidden = hidden;
+    }
 
   /* If this symbol is not being provided by the linker script, and it is
      currently defined by a dynamic object, but not by a regular object,
@@ -572,7 +577,7 @@ bfd_elf_record_link_assignment (bfd *out
 
   h->def_regular = 1;
 
-  if (hidden)
+  if (make_hidden)
     {
       bed = get_elf_backend_data (output_bfd);
       h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
Index: binutils-fsf-trunk-quilt/ld/emultempl/elf32.em
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/emultempl/elf32.em	2013-04-27 09:48:37.373850846 +0100
+++ binutils-fsf-trunk-quilt/ld/emultempl/elf32.em	2013-04-29 22:10:03.773802901 +0100
@@ -1357,9 +1357,9 @@ gld${EMULATION_NAME}_find_exp_assignment
   switch (exp->type.node_class)
     {
     case etree_provide:
-    case etree_provided:
       provide = TRUE;
       /* Fall thru */
+    case etree_provided:
     case etree_assign:
       /* We call record_link_assignment even if the symbol is defined.
 	 This is because if it is defined by a dynamic object, we
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-1.ld
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-1.ld	2013-04-29 22:10:42.773801389 +0100
@@ -0,0 +1,15 @@
+SECTIONS
+{
+  . = 0x12300000;
+  .data :
+    {
+      PROVIDE_HIDDEN (foo = . + 0x11100000);
+      *(.data)
+    }
+  .got : { *(.got) }
+  .interp : { *(.interp) }
+  .dynsym : { *(.dynsym) }
+  .dynstr : { *(.dynstr) }
+  .dynamic : { *(.dynamic) }
+  .hash : { *(.hash) }
+}
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-1.nd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-1.nd	2013-04-29 22:10:42.773801389 +0100
@@ -0,0 +1,5 @@
+#...
+Symbol table '\.symtab' contains [0-9]+ entries:
+#...
+ *[0-9]+: 0*12300000 +0 (?:NOTYPE|OBJECT) +GLOBAL +DEFAULT +[0-9]+ foo
+#pass
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-1.s
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-1.s	2013-04-29 22:10:42.773801389 +0100
@@ -0,0 +1,4 @@
+	.data
+	.globl	foo
+foo:
+	.dc.a	foo
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-2.ld
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-2.ld	2013-04-29 22:10:42.773801389 +0100
@@ -0,0 +1,12 @@
+SECTIONS
+{
+  . = 0x12300000;
+  PROVIDE_HIDDEN (foo = . + 0x11100000);
+  .data : { *(.data) }
+  .got : { *(.got) }
+  .interp : { *(.interp) }
+  .dynsym : { *(.dynsym) }
+  .dynstr : { *(.dynstr) }
+  .dynamic : { *(.dynamic) }
+  .hash : { *(.hash) }
+}
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-2.nd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-2.nd	2013-04-29 22:10:42.773801389 +0100
@@ -0,0 +1,5 @@
+#...
+Symbol table '\.symtab' contains [0-9]+ entries:
+#...
+ *[0-9]+: 0*23400000 +0 (?:NOTYPE|OBJECT) +LOCAL +DEFAULT +[0-9]+ foo
+#pass
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-2.s
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-2.s	2013-04-29 22:10:42.773801389 +0100
@@ -0,0 +1,4 @@
+	.data
+	.globl	bar
+bar:
+	.dc.a	foo
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-3.nd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-3.nd	2013-04-29 22:10:42.773801389 +0100
@@ -0,0 +1,8 @@
+Symbol table '\.dynsym' contains [0-9]+ entries:
+#...
+ *[0-9]+: 0*23400000 +0 (?:NOTYPE|OBJECT) +LOCAL +DEFAULT +[0-9]+ foo
+#...
+Symbol table '\.symtab' contains [0-9]+ entries:
+#...
+ *[0-9]+: 0*23400000 +0 (?:NOTYPE|OBJECT) +LOCAL +DEFAULT +[0-9]+ foo
+#pass
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-4.nd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-4.nd	2013-04-29 22:10:42.773801389 +0100
@@ -0,0 +1,5 @@
+#...
+Symbol table '\.symtab' contains [0-9]+ entries:
+#...
+ *[0-9]+: 0*12300000 +0 (?:NOTYPE|OBJECT) +GLOBAL +DEFAULT +[0-9]+ foo
+#pass
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-5.nd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-5.nd	2013-04-29 22:10:42.773801389 +0100
@@ -0,0 +1,5 @@
+#...
+Symbol table '\.symtab' contains [0-9]+ entries:
+#...
+ *[0-9]+: 0*23400000 +0 (?:NOTYPE|OBJECT) +LOCAL +DEFAULT +ABS foo
+#pass
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-6.nd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-6.nd	2013-04-29 22:10:42.773801389 +0100
@@ -0,0 +1,8 @@
+Symbol table '\.dynsym' contains [0-9]+ entries:
+#...
+ *[0-9]+: 0*23400000 +0 (?:NOTYPE|OBJECT) +LOCAL +DEFAULT +ABS foo
+#...
+Symbol table '\.symtab' contains [0-9]+ entries:
+#...
+ *[0-9]+: 0*23400000 +0 (?:NOTYPE|OBJECT) +LOCAL +DEFAULT +ABS foo
+#pass
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-s.nd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden-s.nd	2013-04-29 22:10:42.773801389 +0100
@@ -0,0 +1,8 @@
+Symbol table '\.dynsym' contains [0-9]+ entries:
+#...
+ *[0-9]+: 0*12300000 +0 (?:NOTYPE|OBJECT) +GLOBAL +DEFAULT +[0-9]+ foo
+#...
+Symbol table '\.symtab' contains [0-9]+ entries:
+#...
+ *[0-9]+: 0*12300000 +0 (?:NOTYPE|OBJECT) +GLOBAL +DEFAULT +[0-9]+ foo
+#pass
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden.exp
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/provide-hidden.exp	2013-04-29 22:10:42.773801389 +0100
@@ -0,0 +1,95 @@
+# Expect script for the PROVIDE_HIDDEN linker script command.
+#
+# Copyright 2013 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+#
+# Written by Maciej W. Rozycki <macro@codesourcery.com>
+#
+
+# Export classes only make sense for ELF shared-library targets.
+if { ![is_elf_format] || ![check_shared_lib_support] } {
+    return
+}
+
+set old_asflags $ASFLAGS
+
+# This target requires extra GAS options when building code for shared
+# libraries.
+if [istarget "tic6x-*-*"] {
+    append ASFLAGS " -mpic -mpid=near"
+}
+
+set testname "PROVIDE_HIDDEN test"
+
+run_ld_link_tests [list \
+    [list \
+	"$testname (auxiliary shared object)" \
+	"-shared -T provide-hidden-1.ld" "" \
+	"" \
+	{ provide-hidden-1.s } \
+	{ { readelf -s provide-hidden-s.nd } } \
+	"provide-hidden-s.so"]]
+
+run_ld_link_tests [list \
+    [list \
+	"$testname 1" \
+	"-T provide-hidden-1.ld" "" \
+	"" \
+	[list provide-hidden-1.s] \
+	[list "readelf -s provide-hidden-1.nd"] \
+	"provide-hidden-1"] \
+    [list \
+	"$testname 2" \
+	"-T provide-hidden-1.ld" "" \
+	"" \
+	[list provide-hidden-2.s] \
+	[list "readelf -s provide-hidden-2.nd"] \
+	"provide-hidden-2"] \
+    [list \
+	"$testname 3" \
+	"-T provide-hidden-1.ld" "tmpdir/provide-hidden-s.so" \
+	"" \
+	[list provide-hidden-2.s] \
+	[list "readelf -s provide-hidden-3.nd"] \
+	"provide-hidden-3"] \
+    [list \
+	"$testname 4" \
+	"-T provide-hidden-2.ld" "" \
+	"" \
+	[list provide-hidden-1.s] \
+	[list "readelf -s provide-hidden-4.nd"] \
+	"provide-hidden-4"] \
+    [list \
+	"$testname 5" \
+	"-T provide-hidden-2.ld" "" \
+	"" \
+	[list provide-hidden-2.s] \
+	[list "readelf -s provide-hidden-5.nd"] \
+	"provide-hidden-5"] \
+    [list \
+	"$testname 6" \
+	"-T provide-hidden-2.ld" "tmpdir/provide-hidden-s.so" \
+	"" \
+	[list provide-hidden-2.s] \
+	[list "readelf -s provide-hidden-6.nd"] \
+	"provide-hidden-6"]]
+
+set ASFLAGS $old_asflags


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]