Fix references to __ehdr_start when it cannot be defined
authorRoland McGrath <mcgrathr@google.com>
Tue, 19 Nov 2013 18:54:00 +0000 (10:54 -0800)
committerRoland McGrath <mcgrathr@google.com>
Tue, 19 Nov 2013 18:54:00 +0000 (10:54 -0800)
ld/
* emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation):
Don't use bfd_elf_record_link_assignment to mark __ehdr_start
hidden.  Instead, just do it directly here, and only if it was
referenced but not defined.

ld/testsuite/
* ld-elf/ehdr_start-userdef.t: New file.
* ld-elf/ehdr_start-userdef.d: New file.
* ld-elf/ehdr_start-strongref.s: New file.
* ld-elf/ehdr_start-missing.t: New file.
* ld-elf/ehdr_start-missing.d: New file.
* ld-elf/ehdr_start-weak.d: New file.
* ld-mips-elf/ehdr_start-2.nd: Expect __ehdr_start to be global.

ld/ChangeLog
ld/emultempl/elf32.em
ld/testsuite/ChangeLog
ld/testsuite/ld-elf/ehdr_start-missing.d [new file with mode: 0644]
ld/testsuite/ld-elf/ehdr_start-missing.t [new file with mode: 0644]
ld/testsuite/ld-elf/ehdr_start-strongref.s [new file with mode: 0644]
ld/testsuite/ld-elf/ehdr_start-userdef.d [new file with mode: 0644]
ld/testsuite/ld-elf/ehdr_start-userdef.t [new file with mode: 0644]
ld/testsuite/ld-elf/ehdr_start-weak.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/ehdr_start-2.nd

index 8984e66..2ea3b61 100644 (file)
@@ -1,3 +1,11 @@
+2013-11-19  Roland McGrath  <mcgrathr@google.com>
+           Alan Modra  <amodra@gmail.com>
+
+       * emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation):
+       Don't use bfd_elf_record_link_assignment to mark __ehdr_start
+       hidden.  Instead, just do it directly here, and only if it was
+       referenced but not defined.
+
 2013-11-18  Chung-Lin Tang  <cltang@codesourcery.com>
 
        * emulparams/nios2linux.sh: New emulation file.
index 682f5e5..9a2fe89 100644 (file)
@@ -1487,10 +1487,25 @@ gld${EMULATION_NAME}_before_allocation (void)
 
       /* Make __ehdr_start hidden if it has been referenced, to
         prevent the symbol from being dynamic.  */
-      if (!bfd_elf_record_link_assignment (link_info.output_bfd, &link_info,
-                                          "__ehdr_start", TRUE, TRUE))
-       einfo ("%P%F: failed to record assignment to %s: %E\n",
-              "__ehdr_start");
+      if (!link_info.relocatable)
+       {
+         struct elf_link_hash_entry *h
+           = elf_link_hash_lookup (elf_hash_table (&link_info), "__ehdr_start",
+                                   FALSE, FALSE, TRUE);
+
+         /* Only adjust the export class if the symbol was referenced
+            and not defined, otherwise leave it alone.  */
+         if (h != NULL
+             && (h->root.type == bfd_link_hash_new
+                 || h->root.type == bfd_link_hash_undefined
+                 || h->root.type == bfd_link_hash_undefweak
+                 || h->root.type == bfd_link_hash_common))
+           {
+             _bfd_elf_link_hash_hide_symbol (&link_info, h, TRUE);
+             if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
+               h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
+           }
+       }
 
       /* If we are going to make any variable assignments, we need to
         let the ELF backend know about them in case the variables are
index 2462cd3..a00cddf 100644 (file)
@@ -1,3 +1,13 @@
+2013-11-19  Roland McGrath  <mcgrathr@google.com>
+
+       * ld-elf/ehdr_start-userdef.t: New file.
+       * ld-elf/ehdr_start-userdef.d: New file.
+       * ld-elf/ehdr_start-strongref.s: New file.
+       * ld-elf/ehdr_start-missing.t: New file.
+       * ld-elf/ehdr_start-missing.d: New file.
+       * ld-elf/ehdr_start-weak.d: New file.
+       * ld-mips-elf/ehdr_start-2.nd: Expect __ehdr_start to be global.
+
 2013-11-17  H.J. Lu  <hongjiu.lu@intel.com>
 
        * ld-x86-64/mpx.exp: New file.
diff --git a/ld/testsuite/ld-elf/ehdr_start-missing.d b/ld/testsuite/ld-elf/ehdr_start-missing.d
new file mode 100644 (file)
index 0000000..5c2090f
--- /dev/null
@@ -0,0 +1,4 @@
+#source: ehdr_start-strongref.s
+#ld: -e _start -T ehdr_start-missing.t
+#error: .*: undefined reference to `__ehdr_start'
+#target: *-*-linux* *-*-gnu* *-*-nacl*
diff --git a/ld/testsuite/ld-elf/ehdr_start-missing.t b/ld/testsuite/ld-elf/ehdr_start-missing.t
new file mode 100644 (file)
index 0000000..a4daf06
--- /dev/null
@@ -0,0 +1,8 @@
+SECTIONS
+{
+  . = 0x10000000;
+  .text : { *(.text) }
+
+  . = 0x20000000;
+  .rodata : { *(.rodata) }
+}
diff --git a/ld/testsuite/ld-elf/ehdr_start-strongref.s b/ld/testsuite/ld-elf/ehdr_start-strongref.s
new file mode 100644 (file)
index 0000000..3937507
--- /dev/null
@@ -0,0 +1,9 @@
+       .text
+       .globl _start
+_start:
+       .space 16
+
+       .section .rodata,"a"
+       .globl foo
+foo:
+       .dc.a __ehdr_start
diff --git a/ld/testsuite/ld-elf/ehdr_start-userdef.d b/ld/testsuite/ld-elf/ehdr_start-userdef.d
new file mode 100644 (file)
index 0000000..16d2749
--- /dev/null
@@ -0,0 +1,9 @@
+#source: ehdr_start-strongref.s
+#ld: -e _start -T ehdr_start-userdef.t
+#readelf: -Ws
+#target: *-*-linux* *-*-gnu* *-*-nacl*
+
+Symbol table '\.symtab' contains [0-9]+ entries:
+#...
+ *[0-9]+: 0*12345678 +0 +NOTYPE +GLOBAL +DEFAULT +ABS +__ehdr_start
+#pass
diff --git a/ld/testsuite/ld-elf/ehdr_start-userdef.t b/ld/testsuite/ld-elf/ehdr_start-userdef.t
new file mode 100644 (file)
index 0000000..6ef1de7
--- /dev/null
@@ -0,0 +1,10 @@
+SECTIONS
+{
+  . = 0x10000000;
+  .text : { *(.text) }
+
+  __ehdr_start = 0x12345678;
+
+  . = 0x20000000;
+  .rodata : { *(.rodata) }
+}
diff --git a/ld/testsuite/ld-elf/ehdr_start-weak.d b/ld/testsuite/ld-elf/ehdr_start-weak.d
new file mode 100644 (file)
index 0000000..8bd9035
--- /dev/null
@@ -0,0 +1,8 @@
+#source: ehdr_start.s
+#ld: -e _start -T ehdr_start-missing.t
+#nm: -n
+#target: *-*-linux* *-*-gnu* *-*-nacl*
+
+#...
+\s+[wU] __ehdr_start
+#pass
index 986c2a2..0a6c06e 100644 (file)
@@ -1,4 +1,4 @@
 Symbol table '\.symtab' contains [0-9]+ entries:
 #...
- *[0-9]+: 0*23400000 +0 (?:NOTYPE|OBJECT) +LOCAL +DEFAULT +[0-9]+ __ehdr_start
+ *[0-9]+: 0*23400000 +0 (?:NOTYPE|OBJECT) +GLOBAL +DEFAULT +[0-9]+ __ehdr_start
 #pass