From 4199e3b8669d0a36448687850374fdc2ad7240b6 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 15 Jan 2014 21:50:55 +1030 Subject: [PATCH] non-PIC references to __ehdr_start in pie and shared Rather than hacking every backend to not discard dynamic relocations against an undefined hidden __ehdr_start, make it appear to be defined early. We want __ehdr_start hidden before size_dynamic_sections so that it isn't put in .dynsym, but we do need the dynamic relocations for a PIE or shared library with a non-PIC reference. Defining it early is wrong if we don't actually define the symbol later to its proper value. (In some cases we want to leave the symbol undefined, for example, when the ELF header isn't loaded, and we don't have this infomation available in before_allocation.) ld/ * emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation): Define __ehdr_start before size_dynamic_sections and restore afterwards. ld/testsuite/ * ld-elf/ehdr_start-shared.d: New. * ld-elf/ehdr_start-userdef.d: xfail frv. * ld-elf/ehdr_start-weak.d: Likewise. * ld-elf/ehdr_start.d: Likewise. --- ld/ChangeLog | 5 +++++ ld/emultempl/elf32.em | 20 ++++++++++++++++++++ ld/testsuite/ChangeLog | 7 +++++++ ld/testsuite/ld-elf/ehdr_start-shared.d | 9 +++++++++ ld/testsuite/ld-elf/ehdr_start-userdef.d | 1 + ld/testsuite/ld-elf/ehdr_start-weak.d | 1 + ld/testsuite/ld-elf/ehdr_start.d | 1 + 7 files changed, 44 insertions(+) create mode 100644 ld/testsuite/ld-elf/ehdr_start-shared.d diff --git a/ld/ChangeLog b/ld/ChangeLog index 2b7a5738ee..eaa6b93575 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,8 @@ +2014-01-15 Alan Modra + + * emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation): Define + __ehdr_start before size_dynamic_sections and restore afterwards. + 2014-01-10 Alan Modra PR ld/14207 diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 9a2fe89947..13f86f084e 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -1480,6 +1480,8 @@ gld${EMULATION_NAME}_before_allocation (void) const char *rpath; asection *sinterp; bfd *abfd; + struct elf_link_hash_entry *ehdr_start = NULL; + struct bfd_link_hash_entry ehdr_start_save; if (is_elf_hash_table (link_info.hash)) { @@ -1504,6 +1506,16 @@ gld${EMULATION_NAME}_before_allocation (void) _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; + /* Don't leave the symbol undefined. Undefined hidden + symbols typically won't have dynamic relocations, but + we most likely will need dynamic relocations for + __ehdr_start if we are building a PIE or shared + library. */ + ehdr_start = h; + ehdr_start_save = h->root; + h->root.type = bfd_link_hash_defined; + h->root.u.def.section = bfd_abs_section_ptr; + h->root.u.def.value = 0; } } @@ -1620,6 +1632,14 @@ ${ELF_INTERPRETER_SET_DEFAULT} if (!bfd_elf_size_dynsym_hash_dynstr (link_info.output_bfd, &link_info)) einfo ("%P%F: failed to set dynamic section sizes: %E\n"); + + if (ehdr_start != NULL) + { + /* If we twiddled __ehdr_start to defined earlier, put it back + as it was. */ + ehdr_start->root.type = ehdr_start_save.type; + ehdr_start->root.u = ehdr_start_save.u; + } } EOF diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index cd97fd577f..8fbd3754bb 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2014-01-15 Alan Modra + + * ld-elf/ehdr_start-shared.d: New. + * ld-elf/ehdr_start-userdef.d: xfail frv. + * ld-elf/ehdr_start-weak.d: Likewise. + * ld-elf/ehdr_start.d: Likewise. + 2014-01-14 Vidya Praveen * lib/ld-lib.exp (default_ld_link): Remove support for ldflags. diff --git a/ld/testsuite/ld-elf/ehdr_start-shared.d b/ld/testsuite/ld-elf/ehdr_start-shared.d new file mode 100644 index 0000000000..c17516a130 --- /dev/null +++ b/ld/testsuite/ld-elf/ehdr_start-shared.d @@ -0,0 +1,9 @@ +#source: ehdr_start.s +#ld: -e _start -shared +#nm: -n +#target: *-*-linux* *-*-gnu* *-*-nacl* +#xfail: cris*-*-* frv-*-* + +#... +[0-9a-f]*000 [Adrt] __ehdr_start +#pass diff --git a/ld/testsuite/ld-elf/ehdr_start-userdef.d b/ld/testsuite/ld-elf/ehdr_start-userdef.d index 2a88e98ea5..b58ae3fa6c 100644 --- a/ld/testsuite/ld-elf/ehdr_start-userdef.d +++ b/ld/testsuite/ld-elf/ehdr_start-userdef.d @@ -2,6 +2,7 @@ #ld: -e _start -T ehdr_start-userdef.t #readelf: -Ws #target: *-*-linux* *-*-gnu* *-*-nacl* +#xfail: frv-*-* #... Symbol table '\.symtab' contains [0-9]+ entries: diff --git a/ld/testsuite/ld-elf/ehdr_start-weak.d b/ld/testsuite/ld-elf/ehdr_start-weak.d index 8bd90357a4..24ae34cda7 100644 --- a/ld/testsuite/ld-elf/ehdr_start-weak.d +++ b/ld/testsuite/ld-elf/ehdr_start-weak.d @@ -2,6 +2,7 @@ #ld: -e _start -T ehdr_start-missing.t #nm: -n #target: *-*-linux* *-*-gnu* *-*-nacl* +#xfail: frv-*-* #... \s+[wU] __ehdr_start diff --git a/ld/testsuite/ld-elf/ehdr_start.d b/ld/testsuite/ld-elf/ehdr_start.d index 52e5b54883..d538b66d9d 100644 --- a/ld/testsuite/ld-elf/ehdr_start.d +++ b/ld/testsuite/ld-elf/ehdr_start.d @@ -2,6 +2,7 @@ #ld: -e _start #nm: -n #target: *-*-linux* *-*-gnu* *-*-nacl* +#xfail: frv-*-* #... [0-9a-f]*000 [Adrt] __ehdr_start -- 2.34.1