This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] Fix references to __ehdr_start when it cannot be defined
- From: Roland McGrath <mcgrathr at google dot com>
- To: "binutils at sourceware dot org" <binutils at sourceware dot org>
- Cc: macro at codesourcery dot com
- Date: Thu, 7 Nov 2013 15:12:39 -0800
- Subject: [PATCH] Fix references to __ehdr_start when it cannot be defined
- Authentication-results: sourceware.org; auth=none
The change Maciej made to make the __ehdr_start symbol hidden broke the
cases when __ehdr_start cannot be defined (because the beginning of the
file does not appear in the memory image).
The failure mode was a BFD abort in elf_link_output_extsym. When all the
references to __ehdr_start were weak, there were also undefined symbol
messages (which of course there should never be for weak references) before
the abort.
This fixes it by moving the logic that changes the __ehdr_start symbol's
visibility to be part of the logic that creates the symbol in the first
place (which does not run at all when the layout makes it impossible to
give it a proper definition). I also added test coverage for both weak and
strong references to __ehdr_start when it cannot be defined.
I don't know why the call was put where it was (the before_allocation hook)
rather than where I moved it (the place where the __ehdr_start symbol is
created) and the latter seems the far more obvious thing to do, so perhaps
there is some reason the former is better that I don't understand.
I have tested this only for {x86_64,i386}-{linux-gnu,nacl} targets.
I am not set up to test any mips targets.
OK for trunk and 2.24?
Thanks,
Roland
bfd/
* elf.c (assign_file_positions_for_non_load_sections):
Call bfd_elf_record_link_assignment here to mark __ehdr_start as
STV_HIDDEN when creating it.
ld/
* emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation):
Don't call bfd_elf_record_link_assignment on __ehdr_start here.
ld/testsuite/
* 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.
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -4962,6 +4962,14 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
hash->root.type = bfd_link_hash_defined;
hash->def_regular = 1;
hash->non_elf = 0;
+
+ /* 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))
+ (*link_info->callbacks->einfo)
+ (_("%P%F: failed to record assignment to %s: %E\n"),
+ "__ehdr_start");
}
}
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -1485,13 +1485,6 @@ gld${EMULATION_NAME}_before_allocation (void)
{
_bfd_elf_tls_setup (link_info.output_bfd, &link_info);
- /* 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 we are going to make any variable assignments, we need to
let the ELF backend know about them in case the variables are
referred to by dynamic objects. */
--- /dev/null
+++ b/ld/testsuite/ld-elf/ehdr_start-missing.d
@@ -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*
--- /dev/null
+++ b/ld/testsuite/ld-elf/ehdr_start-missing.t
@@ -0,0 +1,8 @@
+SECTIONS
+{
+ . = 0x10000000;
+ .text : { *(.text) }
+
+ . = 0x20000000;
+ .rodata : { *(.rodata) }
+}
--- /dev/null
+++ b/ld/testsuite/ld-elf/ehdr_start-strongref.s
@@ -0,0 +1,9 @@
+ .text
+ .globl _start
+_start:
+ .space 16
+
+ .section .rodata,"a"
+ .globl foo
+foo:
+ .dc.a __ehdr_start
--- /dev/null
+++ b/ld/testsuite/ld-elf/ehdr_start-weak.d
@@ -0,0 +1,8 @@
+#source: ehdr_start.s
+#ld: -e _start -T ehdr_start-missing.t
+#nm: -n
+#target: *-*-linux* *-*-gnu* *-*-nacl*
+
+#...
+\s+w __ehdr_start
+#pass