[x86] Resolve non-PIC undefweak symbols in executable
authorH.J. Lu <hjl.tools@gmail.com>
Fri, 26 Feb 2016 12:16:15 +0000 (04:16 -0800)
committerH.J. Lu <hjl.tools@gmail.com>
Fri, 26 Feb 2016 12:55:57 +0000 (04:55 -0800)
For i386 and x86-64, non-PIC references to undefined weak symbols are
resolved without dynamic relocation when creating executable.  Resolved
undefined weak symbols are removed from the dynamic symbol table in
executable.  One exception is on i386, we need resolved undefined weak
symbols in the dynamic symbol table in PIE if input relocatable files
contain branchs without PLT so that we can branch to 0 with dynamic
relocation in text section.

This makes behaviors of dynamic executable and position independent
executable predictable with mixed PIC and non-PIC references to undefined
weak symbols.  If all references to undefined weak symbols are PIC,
dynamic relocations against undefined weak symbols will be generated
in executable unless -z nodynamic-undefined-weak is passed to linker.

bfd/

PR ld/19636
PR ld/19704
PR ld/19719
* elf32-i386.c (UNDEFINED_WEAK_RESOLVED_TO_ZERO): New.
(elf_i386_link_hash_entry): Add has_got_reloc and
has_non_got_reloc.
(elf_i386_link_hash_table): Add interp.
(elf_i386_link_hash_newfunc): Initialize has_got_reloc and
has_non_got_reloc.
(elf_i386_copy_indirect_symbol): Copy has_got_reloc and
has_non_got_reloc.
(elf_i386_check_relocs): Set has_got_reloc and has_non_got_reloc.
(elf_i386_fixup_symbol): New function.
(elf_i386_pie_finish_undefweak_symbol): Likewise.
(elf_i386_allocate_dynrelocs): Don't allocate space for dynamic
relocations and discard relocations against resolved undefined
weak symbols in executable.  Don't make resolved undefined weak
symbols in executable dynamic.  Keep dynamic non-GOT/non-PLT
relocation against undefined weak symbols in PIE.
(elf_i386_size_dynamic_sections): Set interp to .interp section.
(elf_i386_relocate_section): Don't generate dynamic relocations
against resolved undefined weak symbols in PIE, except for
R_386_PC32.
(elf_i386_finish_dynamic_symbol): Keep PLT/GOT entries without
dynamic PLT/GOT relocations for resolved undefined weak symbols.
Don't generate dynamic relocation against resolved undefined weak
symbol in executable.
(elf_i386_finish_dynamic_sections): Call
elf_i386_pie_finish_undefweak_symbol on all symbols in PIE.
(elf_backend_fixup_symbol): New.
* elf64-x86-64.c (UNDEFINED_WEAK_RESOLVED_TO_ZERO): New.
(elf_x86_64_link_hash_entry): Add has_got_reloc and
has_non_got_reloc.
(elf_x86_64_link_hash_table): Add interp.
(elf_x86_64_link_hash_newfunc): Initialize has_got_reloc and
has_non_got_reloc.
(elf_x86_64_copy_indirect_symbol): Copy has_got_reloc and
has_non_got_reloc.
(elf_x86_64_check_relocs): Set has_got_reloc and
has_non_got_reloc.
(elf_x86_64_fixup_symbol): New function.
(elf_x86_64_pie_finish_undefweak_symbol): Likewise.
(elf_x86_64_allocate_dynrelocs): Don't allocate space for dynamic
relocations and discard relocations against resolved undefined
weak symbols in executable.  Don't make resolved undefined weak
symbols in executable dynamic.
(elf_x86_64_size_dynamic_sections): Set interp to .interp section.
(elf_x86_64_relocate_section): Check relocation overflow for
dynamic relocations against unresolved weak undefined symbols.
Don't generate dynamic relocations against resolved weak
undefined symbols in PIE.
(elf_x86_64_finish_dynamic_symbol): Keep PLT/GOT entries without
dynamic PLT/GOT relocations for resolved undefined weak symbols.
Don't generate dynamic relocation against resolved undefined weak
symbol in executable.
(elf_x86_64_finish_dynamic_sections): Call
elf_x86_64_pie_finish_undefweak_symbol on all symbols in PIE.
(elf_backend_fixup_symbol): New.

include/

PR ld/19636
PR ld/19704
PR ld/19719
* bfdlink.h (bfd_link_info): Add dynamic_undefined_weak.

ld/

PR ld/19636
PR ld/19704
PR ld/19719
* Makefile.am (ELF_X86_DEPS): Add dynamic_undefined_weak.sh.
* Makefile.in: Regenerated.
* NEWS: Mention -z nodynamic-undefined-weak.
* ld.texinfo: Document -z nodynamic-undefined-weak.
* ldmain.c (main): Initialize dynamic_undefined_weak to -1.
* emulparams/dynamic_undefined_weak.sh: New file.
* emulparams/elf32_x86_64.sh: Source dynamic_undefined_weak.sh.
* emulparams/elf_i386.sh: Likewise.
* emulparams/elf_i386_be.sh: Likewise.
* emulparams/elf_i386_chaos.sh: Likewise.
* emulparams/elf_i386_ldso.sh: Likewise.
* emulparams/elf_i386_vxworks.sh: Likewise.
* emulparams/elf_iamcu.sh: Likewise.
* emulparams/elf_k1om.sh: Likewise.
* emulparams/elf_l1om.sh: Likewise.
* emulparams/elf_x86_64.sh: Likewise.
* emulparams/extern_protected_data.sh (PARSE_AND_LIST_OPTIONS):
Append.
(PARSE_AND_LIST_ARGS_CASE_Z): Likewise.
* testsuite/ld-elf/pr19719a.c: New file.
* testsuite/ld-elf/pr19719b.c: Likewise.
* testsuite/ld-elf/pr19719c.c: Likewise.
* testsuite/ld-elf/pr19719d.c: Likewise.
* testsuite/ld-i386/pr19636-1.s: Likewise.
* testsuite/ld-i386/pr19636-1a.d: Likewise.
* testsuite/ld-i386/pr19636-1b.d: Likewise.
* testsuite/ld-i386/pr19636-1c.d: Likewise.
* testsuite/ld-i386/pr19636-1d-nacl.d: Likewise.
* testsuite/ld-i386/pr19636-1d.d: Likewise.
* testsuite/ld-i386/pr19636-1e.d: Likewise.
* testsuite/ld-i386/pr19636-1f.d: Likewise.
* testsuite/ld-i386/pr19636-1g.d: Likewise.
* testsuite/ld-i386/pr19636-1h.d: Likewise.
* testsuite/ld-i386/pr19636-1i.d: Likewise.
* testsuite/ld-i386/pr19636-2.s: Likewise.
* testsuite/ld-i386/pr19636-2a.d: Likewise.
* testsuite/ld-i386/pr19636-2b.d: Likewise.
* testsuite/ld-i386/pr19636-2c-nacl.d: Likewise.
* testsuite/ld-i386/pr19636-2c.d: Likewise.
* testsuite/ld-i386/pr19636-2d-nacl.d: Likewise.
* testsuite/ld-i386/pr19636-2d.d: Likewise.
* testsuite/ld-i386/pr19636-2e-nacl.d: Likewise.
* testsuite/ld-i386/pr19636-2e.d: Likewise.
* testsuite/ld-i386/pr19636-3.s: Likewise.
* testsuite/ld-i386/pr19636-3a.d: Likewise.
* testsuite/ld-i386/pr19636-3b.d: Likewise.
* testsuite/ld-i386/pr19636-3c.d: Likewise.
* testsuite/ld-i386/pr19636-3d.d: Likewise.
* testsuite/ld-i386/pr19636-3e.d: Likewise.
* testsuite/ld-i386/pr19636-3f.d: Likewise.
* testsuite/ld-i386/pr19636-3g.d: Likewise.
* testsuite/ld-i386/pr19636-4.s: Likewise.
* testsuite/ld-i386/pr19636-4a.d: Likewise.
* testsuite/ld-i386/pr19636-4b.d: Likewise.
* testsuite/ld-i386/pr19636-4c.d: Likewise.
* testsuite/ld-i386/pr19636-4d.d: Likewise.
* testsuite/ld-i386/pr19704.out: Likewise.
* testsuite/ld-i386/pr19704a.c: Likewise.
* testsuite/ld-i386/pr19704b.c: Likewise.
* testsuite/ld-x86-64/pr19636-1.s: Likewise.
* testsuite/ld-x86-64/pr19636-1a.d: Likewise.
* testsuite/ld-x86-64/pr19636-1b.d: Likewise.
* testsuite/ld-x86-64/pr19636-1c.d: Likewise.
* testsuite/ld-x86-64/pr19636-1d.d: Likewise.
* testsuite/ld-x86-64/pr19636-1e.d: Likewise.
* testsuite/ld-x86-64/pr19636-1f.d: Likewise.
* testsuite/ld-x86-64/pr19636-1g.d: Likewise.
* testsuite/ld-x86-64/pr19636-2.s: Likewise.
* testsuite/ld-x86-64/pr19636-2a.d: Likewise.
* testsuite/ld-x86-64/pr19636-2b.d: Likewise.
* testsuite/ld-x86-64/pr19636-2c.d: Likewise.
* testsuite/ld-x86-64/pr19636-2d-nacl.d: Likewise.
* testsuite/ld-x86-64/pr19636-2d.d: Likewise.
* testsuite/ld-x86-64/pr19636-2e.d: Likewise.
* testsuite/ld-x86-64/pr19636-2f.d: Likewise.
* testsuite/ld-x86-64/pr19636-2g.d: Likewise.
* testsuite/ld-x86-64/pr19636-2h.d: Likewise.
* testsuite/ld-x86-64/pr19636-2i.d: Likewise.
* testsuite/ld-x86-64/pr19636-3.s: Likewise.
* testsuite/ld-x86-64/pr19636-3a.d: Likewise.
* testsuite/ld-x86-64/pr19636-3b.d: Likewise.
* testsuite/ld-x86-64/pr19636-3c.d: Likewise.
* testsuite/ld-x86-64/pr19636-3d.d: Likewise.
* testsuite/ld-x86-64/pr19704.out: Likewise.
* testsuite/ld-x86-64/pr19704a.c: Likewise.
* testsuite/ld-x86-64/pr19704b.c: Likewise.
* testsuite/ld-elf/shared.exp (mix_pic_and_non_pic): New.
Run mix_pic_and_non_pic.
* testsuite/ld-i386/i386.exp (undefined_weak): New.
Run undefined_weak and PR ld/19636 tests.
* testsuite/ld-x86-64/x86-64.exp: Likewise.
* testsuite/ld-x86-64/pr13082-3b.d: Updated.
* testsuite/ld-x86-64/pr13082-4b.d: Likewise.

95 files changed:
bfd/ChangeLog
bfd/elf32-i386.c
bfd/elf64-x86-64.c
include/ChangeLog
include/bfdlink.h
ld/ChangeLog
ld/Makefile.am
ld/Makefile.in
ld/NEWS
ld/emulparams/dynamic_undefined_weak.sh [new file with mode: 0644]
ld/emulparams/elf32_x86_64.sh
ld/emulparams/elf_i386.sh
ld/emulparams/elf_i386_be.sh
ld/emulparams/elf_i386_chaos.sh
ld/emulparams/elf_i386_ldso.sh
ld/emulparams/elf_i386_vxworks.sh
ld/emulparams/elf_iamcu.sh
ld/emulparams/elf_k1om.sh
ld/emulparams/elf_l1om.sh
ld/emulparams/elf_x86_64.sh
ld/emulparams/extern_protected_data.sh
ld/ld.texinfo
ld/ldmain.c
ld/testsuite/ld-elf/pr19719a.c [new file with mode: 0644]
ld/testsuite/ld-elf/pr19719b.c [new file with mode: 0644]
ld/testsuite/ld-elf/pr19719c.c [new file with mode: 0644]
ld/testsuite/ld-elf/pr19719d.c [new file with mode: 0644]
ld/testsuite/ld-elf/shared.exp
ld/testsuite/ld-i386/i386.exp
ld/testsuite/ld-i386/pr19636-1.s [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-1a.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-1b.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-1c.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-1d-nacl.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-1d.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-1e.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-1f.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-1g.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-1h.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-1i.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-2.s [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-2a.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-2b.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-2c-nacl.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-2c.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-2d-nacl.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-2d.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-2e-nacl.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-2e.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-3.s [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-3a.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-3b.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-3c.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-3d.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-3e.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-3f.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-3g.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-4.s [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-4a.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-4b.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-4c.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19636-4d.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19704.out [new file with mode: 0644]
ld/testsuite/ld-i386/pr19704a.c [new file with mode: 0644]
ld/testsuite/ld-i386/pr19704b.c [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr13082-3b.d
ld/testsuite/ld-x86-64/pr13082-4b.d
ld/testsuite/ld-x86-64/pr19636-1.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-1a.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-1b.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-1c.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-1d.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-1e.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-1f.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-1g.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-2.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-2a.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-2b.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-2c.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-2d-nacl.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-2d.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-2e.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-2f.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-2g.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-2h.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-2i.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-3.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-3a.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-3b.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-3c.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19636-3d.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19704.out [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19704a.c [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19704b.c [new file with mode: 0644]
ld/testsuite/ld-x86-64/x86-64.exp

index c2fcf00bad44c842c09962d20aafd98874b97b48..19ae63226961d739ef0079cc2649da2b28d0d2b6 100644 (file)
@@ -1,3 +1,64 @@
+2016-02-26  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/19636
+       PR ld/19704
+       PR ld/19719
+       * elf32-i386.c (UNDEFINED_WEAK_RESOLVED_TO_ZERO): New.
+       (elf_i386_link_hash_entry): Add has_got_reloc and
+       has_non_got_reloc.
+       (elf_i386_link_hash_table): Add interp.
+       (elf_i386_link_hash_newfunc): Initialize has_got_reloc and
+       has_non_got_reloc.
+       (elf_i386_copy_indirect_symbol): Copy has_got_reloc and
+       has_non_got_reloc.
+       (elf_i386_check_relocs): Set has_got_reloc and has_non_got_reloc.
+       (elf_i386_fixup_symbol): New function.
+       (elf_i386_pie_finish_undefweak_symbol): Likewise.
+       (elf_i386_allocate_dynrelocs): Don't allocate space for dynamic
+       relocations and discard relocations against resolved undefined
+       weak symbols in executable.  Don't make resolved undefined weak
+       symbols in executable dynamic.  Keep dynamic non-GOT/non-PLT
+       relocation against undefined weak symbols in PIE.
+       (elf_i386_size_dynamic_sections): Set interp to .interp section.
+       (elf_i386_relocate_section): Don't generate dynamic relocations
+       against resolved undefined weak symbols in PIE, except for
+       R_386_PC32.
+       (elf_i386_finish_dynamic_symbol): Keep PLT/GOT entries without
+       dynamic PLT/GOT relocations for resolved undefined weak symbols.
+       Don't generate dynamic relocation against resolved undefined weak
+       symbol in executable.
+       (elf_i386_finish_dynamic_sections): Call
+       elf_i386_pie_finish_undefweak_symbol on all symbols in PIE.
+       (elf_backend_fixup_symbol): New.
+       * elf64-x86-64.c (UNDEFINED_WEAK_RESOLVED_TO_ZERO): New.
+       (elf_x86_64_link_hash_entry): Add has_got_reloc and
+       has_non_got_reloc.
+       (elf_x86_64_link_hash_table): Add interp.
+       (elf_x86_64_link_hash_newfunc): Initialize has_got_reloc and
+       has_non_got_reloc.
+       (elf_x86_64_copy_indirect_symbol): Copy has_got_reloc and
+       has_non_got_reloc.
+       (elf_x86_64_check_relocs): Set has_got_reloc and
+       has_non_got_reloc.
+       (elf_x86_64_fixup_symbol): New function.
+       (elf_x86_64_pie_finish_undefweak_symbol): Likewise.
+       (elf_x86_64_allocate_dynrelocs): Don't allocate space for dynamic
+       relocations and discard relocations against resolved undefined
+       weak symbols in executable.  Don't make resolved undefined weak
+       symbols in executable dynamic.
+       (elf_x86_64_size_dynamic_sections): Set interp to .interp section.
+       (elf_x86_64_relocate_section): Check relocation overflow for
+       dynamic relocations against unresolved weak undefined symbols.
+       Don't generate dynamic relocations against resolved weak
+       undefined symbols in PIE.
+       (elf_x86_64_finish_dynamic_symbol): Keep PLT/GOT entries without
+       dynamic PLT/GOT relocations for resolved undefined weak symbols.
+       Don't generate dynamic relocation against resolved undefined weak
+       symbol in executable.
+       (elf_x86_64_finish_dynamic_sections): Call
+       elf_x86_64_pie_finish_undefweak_symbol on all symbols in PIE.
+       (elf_backend_fixup_symbol): New.
+
 2016-02-26  Alan Modra  <amodra@gmail.com>
 
        * elf64-ppc.c (create_linkage_sections): Create sfpr when
index f6c9c657490cce4ebc88646f86061665c7dfd22c..2ae5e44fceeb879b2b2109c8bc65ccfaa1d33287 100644 (file)
@@ -737,6 +737,20 @@ static const struct elf_i386_backend_data elf_i386_arch_bed =
 
 #define        elf_backend_arch_data   &elf_i386_arch_bed
 
+/* Is a undefined weak symbol which is resolved to 0.  Reference to an
+   undefined weak symbol is resolved to 0 when building executable if
+   it isn't dynamic and
+   1. Has non-GOT/non-PLT relocations in text section.  Or
+   2. Has no GOT/PLT relocation.
+ */
+#define UNDEFINED_WEAK_RESOLVED_TO_ZERO(INFO, EH) \
+  ((EH)->elf.root.type == bfd_link_hash_undefweak              \
+   && bfd_link_executable (INFO)                               \
+   && (elf_i386_hash_table (INFO)->interp == NULL              \
+       || !(EH)->has_got_reloc                                 \
+       || (EH)->has_non_got_reloc                              \
+       || !(INFO)->dynamic_undefined_weak))
+
 /* i386 ELF linker hash entry.  */
 
 struct elf_i386_link_hash_entry
@@ -767,6 +781,12 @@ struct elf_i386_link_hash_entry
   /* Symbol is referenced by R_386_GOTOFF relocation.  */
   unsigned int gotoff_ref : 1;
 
+  /* Symbol has GOT or PLT relocations.  */
+  unsigned int has_got_reloc : 1;
+
+  /* Symbol has non-GOT/non-PLT relocations in text sections.  */
+  unsigned int has_non_got_reloc : 1;
+
   /* Reference count of C/C++ function pointer relocations in read-write
      section which can be resolved at run-time.  */
   bfd_signed_vma func_pointer_refcount;
@@ -821,6 +841,7 @@ struct elf_i386_link_hash_table
   struct elf_link_hash_table elf;
 
   /* Short-cuts to get to dynamic linker sections.  */
+  asection *interp;
   asection *sdynbss;
   asection *srelbss;
   asection *plt_eh_frame;
@@ -895,6 +916,8 @@ elf_i386_link_hash_newfunc (struct bfd_hash_entry *entry,
       eh->dyn_relocs = NULL;
       eh->tls_type = GOT_UNKNOWN;
       eh->gotoff_ref = 0;
+      eh->has_got_reloc = 0;
+      eh->has_non_got_reloc = 0;
       eh->func_pointer_refcount = 0;
       eh->plt_got.offset = (bfd_vma) -1;
       eh->tlsdesc_got = (bfd_vma) -1;
@@ -1138,6 +1161,9 @@ elf_i386_copy_indirect_symbol (struct bfd_link_info *info,
      generate a R_386_COPY reloc.  */
   edir->gotoff_ref |= eind->gotoff_ref;
 
+  edir->has_got_reloc |= eind->has_got_reloc;
+  edir->has_non_got_reloc |= eind->has_non_got_reloc;
+
   if (ELIMINATE_COPY_RELOCS
       && ind->root.type != bfd_link_hash_indirect
       && dir->dynamic_adjusted)
@@ -1630,6 +1656,7 @@ elf_i386_check_relocs (bfd *abfd,
          if (h == NULL)
            continue;
 
+         eh->has_got_reloc = 1;
          h->needs_plt = 1;
          h->plt.refcount += 1;
          break;
@@ -1760,18 +1787,27 @@ elf_i386_check_relocs (bfd *abfd,
                return FALSE;
            }
          if (r_type != R_386_TLS_IE)
-           break;
+           {
+             if (eh != NULL)
+               eh->has_got_reloc = 1;
+             break;
+           }
          /* Fall through */
 
        case R_386_TLS_LE_32:
        case R_386_TLS_LE:
+         if (eh != NULL)
+           eh->has_got_reloc = 1;
          if (bfd_link_executable (info))
            break;
          info->flags |= DF_STATIC_TLS;
-         /* Fall through */
+         goto do_relocation;
 
        case R_386_32:
        case R_386_PC32:
+         if (eh != NULL && (sec->flags & SEC_CODE) != 0)
+           eh->has_non_got_reloc = 1;
+do_relocation:
          if (h != NULL && bfd_link_executable (info))
            {
              /* If this reloc is in a read-only section, we might
@@ -2147,6 +2183,24 @@ elf_i386_gc_sweep_hook (bfd *abfd,
   return TRUE;
 }
 
+/* Remove undefined weak symbol from the dynamic symbol table if it
+   is resolved to 0.   */
+
+static bfd_boolean
+elf_i386_fixup_symbol (struct bfd_link_info *info,
+                      struct elf_link_hash_entry *h)
+{
+  if (h->dynindx != -1
+      && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info,
+                                         elf_i386_hash_entry (h)))
+    {
+      h->dynindx = -1;
+      _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
+                             h->dynstr_index);
+    }
+  return TRUE;
+}
+
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  The current definition is in some section of the
    dynamic object, but we're not including those sections.  We have to
@@ -2335,6 +2389,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   struct elf_i386_link_hash_entry *eh;
   struct elf_dyn_relocs *p;
   unsigned plt_entry_size;
+  bfd_boolean resolved_to_zero;
 
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
@@ -2348,6 +2403,8 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
   plt_entry_size = GET_PLT_ENTRY_SIZE (info->output_bfd);
 
+  resolved_to_zero = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh);
+
   /* Clear the reference count of function pointer relocations if
      symbol isn't a normal function.  */
   if (h->type != STT_FUNC)
@@ -2405,7 +2462,8 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       /* Make sure this symbol is output as a dynamic symbol.
         Undefined weak syms won't yet be marked as dynamic.  */
       if (h->dynindx == -1
-         && !h->forced_local)
+         && !h->forced_local
+         && !resolved_to_zero)
        {
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
            return FALSE;
@@ -2462,9 +2520,15 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
                 script.  */
              htab->elf.sgotplt->size += 4;
 
-             /* We also need to make an entry in the .rel.plt section.  */
-             htab->elf.srelplt->size += sizeof (Elf32_External_Rel);
-             htab->elf.srelplt->reloc_count++;
+             /* There should be no PLT relocation against resolved
+                undefined weak symbol in executable.  */
+             if (!resolved_to_zero)
+               {
+                 /* We also need to make an entry in the .rel.plt
+                    section.  */
+                 htab->elf.srelplt->size += sizeof (Elf32_External_Rel);
+                 htab->elf.srelplt->reloc_count++;
+               }
            }
 
          if (get_elf_i386_backend_data (info->output_bfd)->is_vxworks
@@ -2520,7 +2584,8 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       /* Make sure this symbol is output as a dynamic symbol.
         Undefined weak syms won't yet be marked as dynamic.  */
       if (h->dynindx == -1
-         && !h->forced_local)
+         && !h->forced_local
+         && !resolved_to_zero)
        {
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
            return FALSE;
@@ -2548,7 +2613,8 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
         R_386_TLS_IE resp. R_386_TLS_GOTIE needs one dynamic relocation,
         (but if both R_386_TLS_IE_32 and R_386_TLS_IE is present, we
         need two), R_386_TLS_GD needs one if local symbol and two if
-        global.  */
+        global.  No dynamic relocation against resolved undefined weak
+        symbol in executable.  */
       if (tls_type == GOT_TLS_IE_BOTH)
        htab->elf.srelgot->size += 2 * sizeof (Elf32_External_Rel);
       else if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1)
@@ -2557,7 +2623,8 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       else if (GOT_TLS_GD_P (tls_type))
        htab->elf.srelgot->size += 2 * sizeof (Elf32_External_Rel);
       else if (! GOT_TLS_GDESC_P (tls_type)
-              && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+              && ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                   && !resolved_to_zero)
                   || h->root.type != bfd_link_hash_undefweak)
               && (bfd_link_pic (info)
                   || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
@@ -2613,15 +2680,43 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
        }
 
       /* Also discard relocs on undefined weak syms with non-default
-        visibility.  */
+        visibility or in PIE.  */
       if (eh->dyn_relocs != NULL
          && h->root.type == bfd_link_hash_undefweak)
        {
-         if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
-           eh->dyn_relocs = NULL;
+         /* Undefined weak symbol is never bound locally in shared
+            library.  */
+         if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+             || resolved_to_zero)
+           {
+             if (h->non_got_ref)
+               {
+                 /* Keep dynamic non-GOT/non-PLT relocation so that we
+                    can branch to 0 without PLT.  */
+                 struct elf_dyn_relocs **pp;
+
+                 for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
+                   if (p->pc_count == 0)
+                     *pp = p->next;
+                   else
+                     {
+                       /* Remove non-R_386_PC32 relocation.  */
+                       p->count = p->pc_count;
+                       pp = &p->next;
+                     }
 
-         /* Make sure undefined weak symbols are output as a dynamic
-            symbol in PIEs.  */
+                 if (eh->dyn_relocs != NULL)
+                   {
+                     /* Make sure undefined weak symbols are output
+                        as dynamic symbols in PIEs for dynamic non-GOT
+                        non-PLT reloations.  */
+                     if (! bfd_elf_link_record_dynamic_symbol (info, h))
+                       return FALSE;
+                   }
+               }
+             else
+               eh->dyn_relocs = NULL;
+           }
          else if (h->dynindx == -1
                   && !h->forced_local)
            {
@@ -2637,7 +2732,10 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
         dynamic.  Keep dynamic relocations for run-time function
         pointer initialization.  */
 
-      if ((!h->non_got_ref || eh->func_pointer_refcount > 0)
+      if ((!h->non_got_ref
+          || eh->func_pointer_refcount > 0
+          || (h->root.type == bfd_link_hash_undefweak
+              && !resolved_to_zero))
          && ((h->def_dynamic
               && !h->def_regular)
              || (htab->elf.dynamic_sections_created
@@ -2647,7 +2745,8 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
          /* Make sure this symbol is output as a dynamic symbol.
             Undefined weak syms won't yet be marked as dynamic.  */
          if (h->dynindx == -1
-             && !h->forced_local)
+             && !h->forced_local
+             && !resolved_to_zero)
            {
              if (! bfd_elf_link_record_dynamic_symbol (info, h))
                return FALSE;
@@ -3110,6 +3209,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
            abort ();
          s->size = sizeof ELF_DYNAMIC_INTERPRETER;
          s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
+         htab->interp = s;
        }
     }
 
@@ -3640,6 +3740,7 @@ elf_i386_relocate_section (bfd *output_bfd,
       int tls_type;
       bfd_vma st_size;
       asection *resolved_plt;
+      bfd_boolean resolved_to_zero;
 
       r_type = ELF32_R_TYPE (rel->r_info);
       if (r_type == R_386_GNU_VTINHERIT
@@ -3981,6 +4082,9 @@ elf_i386_relocate_section (bfd *output_bfd,
        }
 
       eh = (struct elf_i386_link_hash_entry *) h;
+      resolved_to_zero = (eh != NULL
+                         && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh));
+
       switch (r_type)
        {
        case R_386_GOT32X:
@@ -4246,18 +4350,25 @@ r_386_got32:
              || is_vxworks_tls)
            break;
 
-         /* Copy dynamic function pointer relocations.  */
+         /* Copy dynamic function pointer relocations.  Don't generate
+            dynamic relocations against resolved undefined weak symbols
+            in PIE, except for R_386_PC32.  */
          if ((bfd_link_pic (info)
               && (h == NULL
-                  || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-                  || h->root.type != bfd_link_hash_undefweak)
+                  || ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                       && (!resolved_to_zero
+                           || r_type == R_386_PC32))
+                      || h->root.type != bfd_link_hash_undefweak))
               && ((r_type != R_386_PC32 && r_type != R_386_SIZE32)
                   || !SYMBOL_CALLS_LOCAL (info, h)))
              || (ELIMINATE_COPY_RELOCS
                  && !bfd_link_pic (info)
                  && h != NULL
                  && h->dynindx != -1
-                 && (!h->non_got_ref || eh->func_pointer_refcount > 0)
+                 && (!h->non_got_ref
+                     || eh->func_pointer_refcount > 0
+                     || (h->root.type == bfd_link_hash_undefweak
+                         && !resolved_to_zero))
                  && ((h->def_dynamic
                       && !h->def_regular)
                      || h->root.type == bfd_link_hash_undefweak
@@ -5011,6 +5122,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
   unsigned plt_entry_size;
   const struct elf_i386_backend_data *abed;
   struct elf_i386_link_hash_entry *eh;
+  bfd_boolean local_undefweak;
 
   htab = elf_i386_hash_table (info);
   if (htab == NULL)
@@ -5021,6 +5133,11 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
 
   eh = (struct elf_i386_link_hash_entry *) h;
 
+  /* We keep PLT/GOT entries without dynamic PLT/GOT relocations for
+     resolved undefined weak symbols in executable so that their
+     references have value 0 at run-time.  */
+  local_undefweak = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh);
+
   if (h->plt.offset != (bfd_vma) -1)
     {
       bfd_vma plt_index;
@@ -5048,6 +5165,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
         it up.  */
 
       if ((h->dynindx == -1
+          && !local_undefweak
           && !((h->forced_local || bfd_link_executable (info))
                && h->def_regular
                && h->type == STT_GNU_IFUNC))
@@ -5136,54 +5254,61 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
                       + abed->plt->plt_got_offset);
        }
 
-      /* Fill in the entry in the global offset table.  */
-      bfd_put_32 (output_bfd,
-                 (plt->output_section->vma
-                  + plt->output_offset
-                  + h->plt.offset
-                  + abed->plt->plt_lazy_offset),
-                 gotplt->contents + got_offset);
-
-      /* Fill in the entry in the .rel.plt section.  */
-      rel.r_offset = (gotplt->output_section->vma
-                     + gotplt->output_offset
-                     + got_offset);
-      if (h->dynindx == -1
-         || ((bfd_link_executable (info)
-              || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
-             && h->def_regular
-              && h->type == STT_GNU_IFUNC))
+      /* Fill in the entry in the global offset table.  Leave the entry
+        as zero for undefined weak symbol in PIE.  No PLT relocation
+        against undefined weak symbol in PIE.  */
+      if (!local_undefweak)
        {
-         /* If an STT_GNU_IFUNC symbol is locally defined, generate
-            R_386_IRELATIVE instead of R_386_JUMP_SLOT.  Store addend
-            in the .got.plt section.  */
          bfd_put_32 (output_bfd,
-                     (h->root.u.def.value
-                      + h->root.u.def.section->output_section->vma
-                      + h->root.u.def.section->output_offset),
+                     (plt->output_section->vma
+                      + plt->output_offset
+                      + h->plt.offset
+                      + abed->plt->plt_lazy_offset),
                      gotplt->contents + got_offset);
-         rel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
-         /* R_386_IRELATIVE comes last.  */
-         plt_index = htab->next_irelative_index--;
-       }
-      else
-       {
-         rel.r_info = ELF32_R_INFO (h->dynindx, R_386_JUMP_SLOT);
-         plt_index = htab->next_jump_slot_index++;
-       }
-      loc = relplt->contents + plt_index * sizeof (Elf32_External_Rel);
-      bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
 
-      /* Don't fill PLT entry for static executables.  */
-      if (plt == htab->elf.splt)
-       {
-         bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rel),
-                     plt->contents + h->plt.offset
-                      + abed->plt->plt_reloc_offset);
-         bfd_put_32 (output_bfd, - (h->plt.offset
-                                     + abed->plt->plt_plt_offset + 4),
-                     plt->contents + h->plt.offset
-                      + abed->plt->plt_plt_offset);
+         /* Fill in the entry in the .rel.plt section.  */
+         rel.r_offset = (gotplt->output_section->vma
+                         + gotplt->output_offset
+                         + got_offset);
+         if (h->dynindx == -1
+             || ((bfd_link_executable (info)
+                  || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+                 && h->def_regular
+                 && h->type == STT_GNU_IFUNC))
+           {
+             /* If an STT_GNU_IFUNC symbol is locally defined, generate
+                R_386_IRELATIVE instead of R_386_JUMP_SLOT.  Store addend
+                in the .got.plt section.  */
+             bfd_put_32 (output_bfd,
+                         (h->root.u.def.value
+                          + h->root.u.def.section->output_section->vma
+                          + h->root.u.def.section->output_offset),
+                         gotplt->contents + got_offset);
+             rel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
+             /* R_386_IRELATIVE comes last.  */
+             plt_index = htab->next_irelative_index--;
+           }
+         else
+           {
+             rel.r_info = ELF32_R_INFO (h->dynindx, R_386_JUMP_SLOT);
+             plt_index = htab->next_jump_slot_index++;
+           }
+
+         loc = relplt->contents + plt_index * sizeof (Elf32_External_Rel);
+         bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
+
+         /* Don't fill PLT entry for static executables.  */
+         if (plt == htab->elf.splt)
+           {
+             bfd_put_32 (output_bfd,
+                         plt_index * sizeof (Elf32_External_Rel),
+                         plt->contents + h->plt.offset
+                         + abed->plt->plt_reloc_offset);
+             bfd_put_32 (output_bfd, - (h->plt.offset
+                                        + abed->plt->plt_plt_offset + 4),
+                         plt->contents + h->plt.offset
+                         + abed->plt->plt_plt_offset);
+           }
        }
     }
   else if (eh->plt_got.offset != (bfd_vma) -1)
@@ -5229,7 +5354,8 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
                  plt->contents + plt_offset + plt_got_offset);
     }
 
-  if (!h->def_regular
+  if (!local_undefweak
+      && !h->def_regular
       && (h->plt.offset != (bfd_vma) -1
          || eh->plt_got.offset != (bfd_vma) -1))
     {
@@ -5246,9 +5372,12 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
        sym->st_value = 0;
     }
 
+  /* Don't generate dynamic GOT relocation against undefined weak
+     symbol in executable.  */
   if (h->got.offset != (bfd_vma) -1
       && ! GOT_TLS_GD_ANY_P (elf_i386_hash_entry(h)->tls_type)
-      && (elf_i386_hash_entry(h)->tls_type & GOT_TLS_IE) == 0)
+      && (elf_i386_hash_entry(h)->tls_type & GOT_TLS_IE) == 0
+      && !local_undefweak)
     {
       Elf_Internal_Rela rel;
 
@@ -5348,6 +5477,25 @@ elf_i386_finish_local_dynamic_symbol (void **slot, void *inf)
                                         h, NULL);
 }
 
+/* Finish up undefined weak symbol handling in PIE.  Fill its PLT entry
+   here since undefined weak symbol may not be dynamic and may not be
+   called for elf_i386_finish_dynamic_symbol.  */
+
+static bfd_boolean
+elf_i386_pie_finish_undefweak_symbol (struct bfd_hash_entry *bh,
+                                     void *inf)
+{
+  struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) bh;
+  struct bfd_link_info *info = (struct bfd_link_info *) inf;
+
+  if (h->root.type != bfd_link_hash_undefweak
+      || h->dynindx != -1)
+    return TRUE;
+
+  return elf_i386_finish_dynamic_symbol (info->output_bfd,
+                                            info, h, NULL);
+}
+
 /* Used to decide how to sort relocs in an optimal manner for the
    dynamic linker, before writing them out.  */
 
@@ -5626,6 +5774,12 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
                 elf_i386_finish_local_dynamic_symbol,
                 info);
 
+  /* Fill PLT entries for undefined weak symbols in PIE.  */
+  if (bfd_link_pie (info))
+    bfd_hash_traverse (&info->hash->table,
+                      elf_i386_pie_finish_undefweak_symbol,
+                      info);
+
   return TRUE;
 }
 
@@ -5803,6 +5957,7 @@ elf_i386_add_symbol_hook (bfd * abfd,
   ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
 #define elf_backend_hash_symbol                      elf_i386_hash_symbol
 #define elf_backend_add_symbol_hook           elf_i386_add_symbol_hook
+#define elf_backend_fixup_symbol             elf_i386_fixup_symbol
 
 #include "elf32-target.h"
 
index 48d263e388c7f9b359b796b2310a3ce85df8ea96..6ca3b2e06a416e15fb1b871f94b2d36f240fdb9a 100644 (file)
@@ -742,6 +742,20 @@ static const struct elf_x86_64_backend_data elf_x86_64_bnd_arch_bed =
 
 #define        elf_backend_arch_data   &elf_x86_64_arch_bed
 
+/* Is a undefined weak symbol which is resolved to 0.  Reference to an
+   undefined weak symbol is resolved to 0 when building executable if
+   it isn't dynamic and
+   1. Has non-GOT/non-PLT relocations in text section.  Or
+   2. Has no GOT/PLT relocation.
+ */
+#define UNDEFINED_WEAK_RESOLVED_TO_ZERO(INFO, EH) \
+  ((EH)->elf.root.type == bfd_link_hash_undefweak              \
+   && bfd_link_executable (INFO)                               \
+   && (elf_x86_64_hash_table (INFO)->interp == NULL            \
+       || !(EH)->has_got_reloc                                 \
+       || (EH)->has_non_got_reloc                              \
+       || !(INFO)->dynamic_undefined_weak))
+
 /* x86-64 ELF linker hash entry.  */
 
 struct elf_x86_64_link_hash_entry
@@ -776,6 +790,12 @@ struct elf_x86_64_link_hash_entry
   /* TRUE if symbol has at least one BND relocation.  */
   unsigned int has_bnd_reloc : 1;
 
+  /* TRUE if symbol has GOT or PLT relocations.  */
+  unsigned int has_got_reloc : 1;
+
+  /* TRUE if symbol has non-GOT/non-PLT relocations in text sections.  */
+  unsigned int has_non_got_reloc : 1;
+
   /* Reference count of C/C++ function pointer relocations in read-write
      section which can be resolved at run-time.  */
   bfd_signed_vma func_pointer_refcount;
@@ -835,6 +855,7 @@ struct elf_x86_64_link_hash_table
   struct elf_link_hash_table elf;
 
   /* Short-cuts to get to dynamic linker sections.  */
+  asection *interp;
   asection *sdynbss;
   asection *srelbss;
   asection *plt_eh_frame;
@@ -919,6 +940,8 @@ elf_x86_64_link_hash_newfunc (struct bfd_hash_entry *entry,
       eh->tls_type = GOT_UNKNOWN;
       eh->needs_copy = 0;
       eh->has_bnd_reloc = 0;
+      eh->has_got_reloc = 0;
+      eh->has_non_got_reloc = 0;
       eh->func_pointer_refcount = 0;
       eh->plt_bnd.offset = (bfd_vma) -1;
       eh->plt_got.offset = (bfd_vma) -1;
@@ -1136,6 +1159,12 @@ elf_x86_64_copy_indirect_symbol (struct bfd_link_info *info,
   if (!edir->has_bnd_reloc)
     edir->has_bnd_reloc = eind->has_bnd_reloc;
 
+  if (!edir->has_got_reloc)
+    edir->has_got_reloc = eind->has_got_reloc;
+
+  if (!edir->has_non_got_reloc)
+    edir->has_non_got_reloc = eind->has_non_got_reloc;
+
   if (eind->dyn_relocs != NULL)
     {
       if (edir->dyn_relocs != NULL)
@@ -1595,6 +1624,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
       unsigned int r_type;
       unsigned long r_symndx;
       struct elf_link_hash_entry *h;
+      struct elf_x86_64_link_hash_entry *eh;
       Elf_Internal_Sym *isym;
       const char *name;
       bfd_boolean size_reloc;
@@ -1760,6 +1790,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
                                       rel, rel_end, h, r_symndx))
        return FALSE;
 
+      eh = (struct elf_x86_64_link_hash_entry *) h;
       switch (r_type)
        {
        case R_X86_64_TLSLD:
@@ -1781,6 +1812,8 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
              bfd_set_error (bfd_error_bad_value);
              return FALSE;
            }
+         if (eh != NULL)
+           eh->has_got_reloc = 1;
          break;
 
        case R_X86_64_GOTTPOFF:
@@ -1815,7 +1848,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
            if (h != NULL)
              {
                h->got.refcount += 1;
-               old_tls_type = elf_x86_64_hash_entry (h)->tls_type;
+               old_tls_type = eh->tls_type;
              }
            else
              {
@@ -1873,8 +1906,8 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
            if (old_tls_type != tls_type)
              {
-               if (h != NULL)
-                 elf_x86_64_hash_entry (h)->tls_type = tls_type;
+               if (eh != NULL)
+                 eh->tls_type = tls_type;
                else
                  elf_x86_64_local_got_tls_type (abfd) [r_symndx] = tls_type;
              }
@@ -1885,6 +1918,8 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_X86_64_GOTPC32:
        case R_X86_64_GOTPC64:
        create_got:
+         if (eh != NULL)
+           eh->has_got_reloc = 1;
          if (htab->elf.sgot == NULL)
            {
              if (htab->elf.dynobj == NULL)
@@ -1909,6 +1944,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
          if (h == NULL)
            continue;
 
+         eh->has_got_reloc = 1;
          h->needs_plt = 1;
          h->plt.refcount += 1;
          break;
@@ -1961,6 +1997,8 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_X86_64_PC64:
        case R_X86_64_64:
 pointer:
+         if (eh != NULL && (sec->flags & SEC_CODE) != 0)
+           eh->has_non_got_reloc = 1;
          if (h != NULL && bfd_link_executable (info))
            {
              /* If this reloc is in a read-only section, we might
@@ -1994,11 +2032,7 @@ pointer:
                          || (!ABI_64_P (abfd)
                              && (r_type == R_X86_64_32
                                  || r_type == R_X86_64_32S))))
-                   {
-                     struct elf_x86_64_link_hash_entry *eh
-                       = (struct elf_x86_64_link_hash_entry *) h;
-                     eh->func_pointer_refcount += 1;
-                   }
+                   eh->func_pointer_refcount += 1;
                }
            }
 
@@ -2061,9 +2095,7 @@ do_size:
              /* If this is a global symbol, we count the number of
                 relocations we need for this symbol.  */
              if (h != NULL)
-               {
-                 head = &((struct elf_x86_64_link_hash_entry *) h)->dyn_relocs;
-               }
+               head = &eh->dyn_relocs;
              else
                {
                  /* Track dynamic relocs needed for local syms too.
@@ -2363,6 +2395,24 @@ pointer:
   return TRUE;
 }
 
+/* Remove undefined weak symbol from the dynamic symbol table if it
+   is resolved to 0.   */
+
+static bfd_boolean
+elf_x86_64_fixup_symbol (struct bfd_link_info *info,
+                      struct elf_link_hash_entry *h)
+{
+  if (h->dynindx != -1
+      && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info,
+                                         elf_x86_64_hash_entry (h)))
+    {
+      h->dynindx = -1;
+      _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
+                             h->dynstr_index);
+    }
+  return TRUE;
+}
+
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  The current definition is in some section of the
    dynamic object, but we're not including those sections.  We have to
@@ -2552,6 +2602,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
   struct elf_dyn_relocs *p;
   const struct elf_backend_data *bed;
   unsigned int plt_entry_size;
+  bfd_boolean resolved_to_zero;
 
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
@@ -2565,6 +2616,8 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
   bed = get_elf_backend_data (info->output_bfd);
   plt_entry_size = GET_PLT_ENTRY_SIZE (info->output_bfd);
 
+  resolved_to_zero = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh);
+
   /* We can't use the GOT PLT if pointer equality is needed since
      finish_dynamic_symbol won't clear symbol value and the dynamic
      linker won't update the GOT slot.  We will get into an infinite
@@ -2641,7 +2694,8 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
       /* Make sure this symbol is output as a dynamic symbol.
         Undefined weak syms won't yet be marked as dynamic.  */
       if (h->dynindx == -1
-         && !h->forced_local)
+         && !h->forced_local
+         && !resolved_to_zero)
        {
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
            return FALSE;
@@ -2715,10 +2769,15 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
                 script.  */
              htab->elf.sgotplt->size += GOT_ENTRY_SIZE;
 
-             /* We also need to make an entry in the .rela.plt
-                section.  */
-             htab->elf.srelplt->size += bed->s->sizeof_rela;
-             htab->elf.srelplt->reloc_count++;
+             /* There should be no PLT relocation against resolved
+                undefined weak symbol in executable.  */
+             if (!resolved_to_zero)
+               {
+                 /* We also need to make an entry in the .rela.plt
+                    section.  */
+                 htab->elf.srelplt->size += bed->s->sizeof_rela;
+                 htab->elf.srelplt->reloc_count++;
+               }
            }
        }
       else
@@ -2755,7 +2814,8 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
       /* Make sure this symbol is output as a dynamic symbol.
         Undefined weak syms won't yet be marked as dynamic.  */
       if (h->dynindx == -1
-         && !h->forced_local)
+         && !h->forced_local
+         && !resolved_to_zero)
        {
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
            return FALSE;
@@ -2779,15 +2839,17 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
        }
       dyn = htab->elf.dynamic_sections_created;
       /* R_X86_64_TLSGD needs one dynamic relocation if local symbol
-        and two if global.
-        R_X86_64_GOTTPOFF needs one dynamic relocation.  */
+        and two if global.  R_X86_64_GOTTPOFF needs one dynamic
+        relocation.  No dynamic relocation against resolved undefined
+        weak symbol in executable.  */
       if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1)
          || tls_type == GOT_TLS_IE)
        htab->elf.srelgot->size += bed->s->sizeof_rela;
       else if (GOT_TLS_GD_P (tls_type))
        htab->elf.srelgot->size += 2 * bed->s->sizeof_rela;
       else if (! GOT_TLS_GDESC_P (tls_type)
-              && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+              && ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                   && !resolved_to_zero)
                   || h->root.type != bfd_link_hash_undefweak)
               && (bfd_link_pic (info)
                   || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
@@ -2834,16 +2896,16 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
        }
 
       /* Also discard relocs on undefined weak syms with non-default
-        visibility.  */
+        visibility or in PIE.  */
       if (eh->dyn_relocs != NULL)
        {
          if (h->root.type == bfd_link_hash_undefweak)
            {
-             if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+             /* Undefined weak symbol is never bound locally in shared
+                library.  */
+             if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+                 || resolved_to_zero)
                eh->dyn_relocs = NULL;
-
-             /* Make sure undefined weak symbols are output as a dynamic
-                symbol in PIEs.  */
              else if (h->dynindx == -1
                       && ! h->forced_local
                       && ! bfd_elf_link_record_dynamic_symbol (info, h))
@@ -2875,7 +2937,10 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
         dynamic.  Keep dynamic relocations for run-time function
         pointer initialization.  */
 
-      if ((!h->non_got_ref || eh->func_pointer_refcount > 0)
+      if ((!h->non_got_ref
+          || eh->func_pointer_refcount > 0
+          || (h->root.type == bfd_link_hash_undefweak
+              && !resolved_to_zero))
          && ((h->def_dynamic
               && !h->def_regular)
              || (htab->elf.dynamic_sections_created
@@ -2886,6 +2951,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
             Undefined weak syms won't yet be marked as dynamic.  */
          if (h->dynindx == -1
              && ! h->forced_local
+             && ! resolved_to_zero
              && ! bfd_elf_link_record_dynamic_symbol (info, h))
            return FALSE;
 
@@ -3398,6 +3464,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
            abort ();
          s->size = htab->dynamic_interpreter_size;
          s->contents = (unsigned char *) htab->dynamic_interpreter;
+         htab->interp = s;
        }
     }
 
@@ -3949,6 +4016,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
       int tls_type;
       asection *base_got, *resolved_plt;
       bfd_vma st_size;
+      bfd_boolean resolved_to_zero;
 
       r_type = ELF32_R_TYPE (rel->r_info);
       if (r_type == (int) R_X86_64_GNU_VTINHERIT
@@ -4259,6 +4327,9 @@ elf_x86_64_relocate_section (bfd *output_bfd,
            }
        }
 
+      resolved_to_zero = (eh != NULL
+                         && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh));
+
       /* When generating a shared object, the relocations handled here are
         copied into the output file to be resolved at run time.  */
       switch (r_type)
@@ -4539,13 +4610,16 @@ elf_x86_64_relocate_section (bfd *output_bfd,
        case R_X86_64_PC32:
        case R_X86_64_PC32_BND:
          /* Don't complain about -fPIC if the symbol is undefined when
-            building executable.  */
-         if (bfd_link_pic (info)
-             && (input_section->flags & SEC_ALLOC) != 0
+            building executable unless it is unresolved weak symbol.  */
+          if ((input_section->flags & SEC_ALLOC) != 0
              && (input_section->flags & SEC_READONLY) != 0
              && h != NULL
-             && !(bfd_link_executable (info)
-                  && h->root.type == bfd_link_hash_undefined))
+             && ((bfd_link_executable (info)
+                 && h->root.type == bfd_link_hash_undefweak
+                 && !resolved_to_zero)
+                 || (bfd_link_pic (info)
+                     && !(bfd_link_pie (info)
+                          && h->root.type == bfd_link_hash_undefined))))
            {
              bfd_boolean fail = FALSE;
              bfd_boolean branch
@@ -4559,7 +4633,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
                     defined locally or for a branch.  */
                  fail = !h->def_regular && !branch;
                }
-             else if (!(bfd_link_executable (info)
+             else if (!(bfd_link_pie (info)
                         && (h->needs_copy || eh->needs_copy)))
                {
                  /* Symbol doesn't need copy reloc and isn't referenced
@@ -4589,17 +4663,19 @@ direct:
           /* Don't copy a pc-relative relocation into the output file
              if the symbol needs copy reloc or the symbol is undefined
              when building executable.  Copy dynamic function pointer
-             relocations.  */
+             relocations.  Don't generate dynamic relocations against
+             resolved undefined weak symbols in PIE.  */
          if ((bfd_link_pic (info)
-              && !(bfd_link_executable (info)
+              && !(bfd_link_pie (info)
                    && h != NULL
                    && (h->needs_copy
                        || eh->needs_copy
                        || h->root.type == bfd_link_hash_undefined)
                    && IS_X86_64_PCREL_TYPE (r_type))
               && (h == NULL
-                  || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-                  || h->root.type != bfd_link_hash_undefweak)
+                  || ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                       && !resolved_to_zero)
+                      || h->root.type != bfd_link_hash_undefweak))
               && ((! IS_X86_64_PCREL_TYPE (r_type)
                      && r_type != R_X86_64_SIZE32
                      && r_type != R_X86_64_SIZE64)
@@ -4608,7 +4684,10 @@ direct:
                  && !bfd_link_pic (info)
                  && h != NULL
                  && h->dynindx != -1
-                 && (!h->non_got_ref || eh->func_pointer_refcount > 0)
+                 && (!h->non_got_ref
+                     || eh->func_pointer_refcount > 0
+                     || (h->root.type == bfd_link_hash_undefweak
+                         && !resolved_to_zero))
                  && ((h->def_dynamic
                       && !h->def_regular)
                      || h->root.type == bfd_link_hash_undefweak
@@ -4647,6 +4726,11 @@ direct:
                           || ! SYMBOLIC_BIND (info, h)
                           || ! h->def_regular))
                {
+                 if ((r_type != R_X86_64_PC64 && r_type != R_X86_64_64)
+                     && bfd_link_executable (info)
+                     && h->root.type == bfd_link_hash_undefweak
+                     && !resolved_to_zero)
+                   return elf_x86_64_need_pic (input_bfd, h, howto);
                  outrel.r_info = htab->r_info (h->dynindx, r_type);
                  outrel.r_addend = rel->r_addend;
                }
@@ -5340,12 +5424,13 @@ static bfd_boolean
 elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
                                  struct bfd_link_info *info,
                                  struct elf_link_hash_entry *h,
-                                 Elf_Internal_Sym *sym ATTRIBUTE_UNUSED)
+                                 Elf_Internal_Sym *sym)
 {
   struct elf_x86_64_link_hash_table *htab;
   const struct elf_x86_64_backend_data *abed;
   bfd_boolean use_plt_bnd;
   struct elf_x86_64_link_hash_entry *eh;
+  bfd_boolean local_undefweak;
 
   htab = elf_x86_64_hash_table (info);
   if (htab == NULL)
@@ -5360,6 +5445,11 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
 
   eh = (struct elf_x86_64_link_hash_entry *) h;
 
+  /* We keep PLT/GOT entries without dynamic PLT/GOT relocations for
+     resolved undefined weak symbols in executable so that their
+     references have value 0 at run-time.  */
+  local_undefweak = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh);
+
   if (h->plt.offset != (bfd_vma) -1)
     {
       bfd_vma plt_index;
@@ -5389,6 +5479,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
       /* This symbol has an entry in the procedure linkage table.  Set
         it up.  */
       if ((h->dynindx == -1
+          && !local_undefweak
           && !((h->forced_local || bfd_link_executable (info))
                && h->def_regular
                && h->type == STT_GNU_IFUNC))
@@ -5489,60 +5580,67 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
                  resolved_plt->contents + plt_offset + plt_got_offset);
 
       /* Fill in the entry in the global offset table, initially this
-        points to the second part of the PLT entry.  */
-      bfd_put_64 (output_bfd, (plt->output_section->vma
-                              + plt->output_offset
-                              + h->plt.offset + abed->plt_lazy_offset),
-                 gotplt->contents + got_offset);
-
-      /* Fill in the entry in the .rela.plt section.  */
-      rela.r_offset = (gotplt->output_section->vma
-                      + gotplt->output_offset
-                      + got_offset);
-      if (h->dynindx == -1
-         || ((bfd_link_executable (info)
-              || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
-             && h->def_regular
-             && h->type == STT_GNU_IFUNC))
+        points to the second part of the PLT entry.  Leave the entry
+        as zero for undefined weak symbol in PIE.  No PLT relocation
+        against undefined weak symbol in PIE.  */
+      if (!local_undefweak)
        {
-         /* If an STT_GNU_IFUNC symbol is locally defined, generate
-            R_X86_64_IRELATIVE instead of R_X86_64_JUMP_SLOT.  */
-         rela.r_info = htab->r_info (0, R_X86_64_IRELATIVE);
-         rela.r_addend = (h->root.u.def.value
-                          + h->root.u.def.section->output_section->vma
-                          + h->root.u.def.section->output_offset);
-         /* R_X86_64_IRELATIVE comes last.  */
-         plt_index = htab->next_irelative_index--;
-       }
-      else
-       {
-         rela.r_info = htab->r_info (h->dynindx, R_X86_64_JUMP_SLOT);
-         rela.r_addend = 0;
-         plt_index = htab->next_jump_slot_index++;
-       }
+         bfd_put_64 (output_bfd, (plt->output_section->vma
+                                  + plt->output_offset
+                                  + h->plt.offset
+                                  + abed->plt_lazy_offset),
+                     gotplt->contents + got_offset);
+
+         /* Fill in the entry in the .rela.plt section.  */
+         rela.r_offset = (gotplt->output_section->vma
+                          + gotplt->output_offset
+                          + got_offset);
+         if (h->dynindx == -1
+             || ((bfd_link_executable (info)
+                  || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+                 && h->def_regular
+                 && h->type == STT_GNU_IFUNC))
+           {
+             /* If an STT_GNU_IFUNC symbol is locally defined, generate
+                R_X86_64_IRELATIVE instead of R_X86_64_JUMP_SLOT.  */
+             rela.r_info = htab->r_info (0, R_X86_64_IRELATIVE);
+             rela.r_addend = (h->root.u.def.value
+                              + h->root.u.def.section->output_section->vma
+                              + h->root.u.def.section->output_offset);
+             /* R_X86_64_IRELATIVE comes last.  */
+             plt_index = htab->next_irelative_index--;
+           }
+         else
+           {
+             rela.r_info = htab->r_info (h->dynindx, R_X86_64_JUMP_SLOT);
+             rela.r_addend = 0;
+             plt_index = htab->next_jump_slot_index++;
+           }
 
-      /* Don't fill PLT entry for static executables.  */
-      if (plt == htab->elf.splt)
-       {
-         bfd_vma plt0_offset = h->plt.offset + plt_plt_insn_end;
-
-         /* Put relocation index.  */
-         bfd_put_32 (output_bfd, plt_index,
-                     plt->contents + h->plt.offset + abed->plt_reloc_offset);
-
-         /* Put offset for jmp .PLT0 and check for overflow.  We don't
-            check relocation index for overflow since branch displacement
-            will overflow first.  */
-         if (plt0_offset > 0x80000000)
-           info->callbacks->einfo (_("%F%B: branch displacement overflow in PLT entry for `%s'\n"),
-                                   output_bfd, h->root.root.string);
-         bfd_put_32 (output_bfd, - plt0_offset,
-                     plt->contents + h->plt.offset + plt_plt_offset);
-       }
+         /* Don't fill PLT entry for static executables.  */
+         if (plt == htab->elf.splt)
+           {
+             bfd_vma plt0_offset = h->plt.offset + plt_plt_insn_end;
+
+             /* Put relocation index.  */
+             bfd_put_32 (output_bfd, plt_index,
+                         (plt->contents + h->plt.offset
+                          + abed->plt_reloc_offset));
+
+             /* Put offset for jmp .PLT0 and check for overflow.  We don't
+                check relocation index for overflow since branch displacement
+                will overflow first.  */
+             if (plt0_offset > 0x80000000)
+               info->callbacks->einfo (_("%F%B: branch displacement overflow in PLT entry for `%s'\n"),
+                                       output_bfd, h->root.root.string);
+             bfd_put_32 (output_bfd, - plt0_offset,
+                         plt->contents + h->plt.offset + plt_plt_offset);
+           }
 
-      bed = get_elf_backend_data (output_bfd);
-      loc = relplt->contents + plt_index * bed->s->sizeof_rela;
-      bed->s->swap_reloca_out (output_bfd, &rela, loc);
+         bed = get_elf_backend_data (output_bfd);
+         loc = relplt->contents + plt_index * bed->s->sizeof_rela;
+         bed->s->swap_reloca_out (output_bfd, &rela, loc);
+       }
     }
   else if (eh->plt_got.offset != (bfd_vma) -1)
     {
@@ -5604,7 +5702,8 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
                  plt->contents + plt_offset + plt_got_offset);
     }
 
-  if (!h->def_regular
+  if (!local_undefweak
+      && !h->def_regular
       && (h->plt.offset != (bfd_vma) -1
          || eh->plt_got.offset != (bfd_vma) -1))
     {
@@ -5621,9 +5720,12 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
        sym->st_value = 0;
     }
 
+  /* Don't generate dynamic GOT relocation against undefined weak
+     symbol in executable.  */
   if (h->got.offset != (bfd_vma) -1
       && ! GOT_TLS_GD_ANY_P (elf_x86_64_hash_entry (h)->tls_type)
-      && elf_x86_64_hash_entry (h)->tls_type != GOT_TLS_IE)
+      && elf_x86_64_hash_entry (h)->tls_type != GOT_TLS_IE
+      && !local_undefweak)
     {
       Elf_Internal_Rela rela;
 
@@ -5729,6 +5831,25 @@ elf_x86_64_finish_local_dynamic_symbol (void **slot, void *inf)
                                             info, h, NULL);
 }
 
+/* Finish up undefined weak symbol handling in PIE.  Fill its PLT entry
+   here since undefined weak symbol may not be dynamic and may not be
+   called for elf_x86_64_finish_dynamic_symbol.  */
+
+static bfd_boolean
+elf_x86_64_pie_finish_undefweak_symbol (struct bfd_hash_entry *bh,
+                                       void *inf)
+{
+  struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) bh;
+  struct bfd_link_info *info = (struct bfd_link_info *) inf;
+
+  if (h->root.type != bfd_link_hash_undefweak
+      || h->dynindx != -1)
+    return TRUE;
+
+  return elf_x86_64_finish_dynamic_symbol (info->output_bfd,
+                                            info, h, NULL);
+}
+
 /* Used to decide how to sort relocs in an optimal manner for the
    dynamic linker, before writing them out.  */
 
@@ -6002,6 +6123,12 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
                 elf_x86_64_finish_local_dynamic_symbol,
                 info);
 
+  /* Fill PLT entries for undefined weak symbols in PIE.  */
+  if (bfd_link_pie (info))
+    bfd_hash_traverse (&info->hash->table,
+                      elf_x86_64_pie_finish_undefweak_symbol,
+                      info);
+
   return TRUE;
 }
 
@@ -6413,6 +6540,8 @@ static const struct bfd_elf_special_section
   elf_x86_64_hash_symbol
 #define elf_backend_omit_section_dynsym \
   ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
+#define elf_backend_fixup_symbol \
+  elf_x86_64_fixup_symbol
 
 #include "elf64-target.h"
 
index f9e56e244df9e872f5931ca33eef0fd153244934..ae4d7ff894988e6f10592af00a619cf561afb6ac 100644 (file)
@@ -1,3 +1,10 @@
+2016-02-26  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/19636
+       PR ld/19704
+       PR ld/19719
+       * bfdlink.h (bfd_link_info): Add dynamic_undefined_weak.
+
 2016-02-19  Matthew Wahab  <matthew.wahab@arm.com>
            Jiong Wang  <jiong.wang@arm.com>
 
index 9b849aa761e1e59d5f31f2ec6f2769f28421d251..860811c2a7867e21dbd649cc862813dde10ead09 100644 (file)
@@ -542,6 +542,10 @@ struct bfd_link_info
      backend to decide.  */
   int extern_protected_data;
 
+  /* > 0 to treat undefined weak symbol in the executable as dynamic,
+     requiring dynamic relocation.  */
+  int dynamic_undefined_weak;
+
   /* Non-zero if auto-import thunks for DATA items in pei386 DLLs
      should be generated/linked against.  Set to 1 if this feature
      is explicitly requested by the user, -1 if enabled by default.  */
index 103719804feb2f44a2a9203bead452f5a9aac483..0318956163ec401df3d9508ac213c9b4da654925 100644 (file)
@@ -1,3 +1,102 @@
+2016-02-26  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/19636
+       PR ld/19704
+       PR ld/19719
+       * Makefile.am (ELF_X86_DEPS): Add dynamic_undefined_weak.sh.
+       * Makefile.in: Regenerated.
+       * NEWS: Mention -z nodynamic-undefined-weak.
+       * ld.texinfo: Document -z nodynamic-undefined-weak.
+       * ldmain.c (main): Initialize dynamic_undefined_weak to -1.
+       * emulparams/dynamic_undefined_weak.sh: New file.
+       * emulparams/elf32_x86_64.sh: Source dynamic_undefined_weak.sh.
+       * emulparams/elf_i386.sh: Likewise.
+       * emulparams/elf_i386_be.sh: Likewise.
+       * emulparams/elf_i386_chaos.sh: Likewise.
+       * emulparams/elf_i386_ldso.sh: Likewise.
+       * emulparams/elf_i386_vxworks.sh: Likewise.
+       * emulparams/elf_iamcu.sh: Likewise.
+       * emulparams/elf_k1om.sh: Likewise.
+       * emulparams/elf_l1om.sh: Likewise.
+       * emulparams/elf_x86_64.sh: Likewise.
+       * emulparams/extern_protected_data.sh (PARSE_AND_LIST_OPTIONS):
+       Append.
+       (PARSE_AND_LIST_ARGS_CASE_Z): Likewise.
+       * testsuite/ld-elf/pr19719a.c: New file.
+       * testsuite/ld-elf/pr19719b.c: Likewise.
+       * testsuite/ld-elf/pr19719c.c: Likewise.
+       * testsuite/ld-elf/pr19719d.c: Likewise.
+       * testsuite/ld-i386/pr19636-1.s: Likewise.
+       * testsuite/ld-i386/pr19636-1a.d: Likewise.
+       * testsuite/ld-i386/pr19636-1b.d: Likewise.
+       * testsuite/ld-i386/pr19636-1c.d: Likewise.
+       * testsuite/ld-i386/pr19636-1d-nacl.d: Likewise.
+       * testsuite/ld-i386/pr19636-1d.d: Likewise.
+       * testsuite/ld-i386/pr19636-1e.d: Likewise.
+       * testsuite/ld-i386/pr19636-1f.d: Likewise.
+       * testsuite/ld-i386/pr19636-1g.d: Likewise.
+       * testsuite/ld-i386/pr19636-1h.d: Likewise.
+       * testsuite/ld-i386/pr19636-1i.d: Likewise.
+       * testsuite/ld-i386/pr19636-2.s: Likewise.
+       * testsuite/ld-i386/pr19636-2a.d: Likewise.
+       * testsuite/ld-i386/pr19636-2b.d: Likewise.
+       * testsuite/ld-i386/pr19636-2c-nacl.d: Likewise.
+       * testsuite/ld-i386/pr19636-2c.d: Likewise.
+       * testsuite/ld-i386/pr19636-2d-nacl.d: Likewise.
+       * testsuite/ld-i386/pr19636-2d.d: Likewise.
+       * testsuite/ld-i386/pr19636-2e-nacl.d: Likewise.
+       * testsuite/ld-i386/pr19636-2e.d: Likewise.
+       * testsuite/ld-i386/pr19636-3.s: Likewise.
+       * testsuite/ld-i386/pr19636-3a.d: Likewise.
+       * testsuite/ld-i386/pr19636-3b.d: Likewise.
+       * testsuite/ld-i386/pr19636-3c.d: Likewise.
+       * testsuite/ld-i386/pr19636-3d.d: Likewise.
+       * testsuite/ld-i386/pr19636-3e.d: Likewise.
+       * testsuite/ld-i386/pr19636-3f.d: Likewise.
+       * testsuite/ld-i386/pr19636-3g.d: Likewise.
+       * testsuite/ld-i386/pr19636-4.s: Likewise.
+       * testsuite/ld-i386/pr19636-4a.d: Likewise.
+       * testsuite/ld-i386/pr19636-4b.d: Likewise.
+       * testsuite/ld-i386/pr19636-4c.d: Likewise.
+       * testsuite/ld-i386/pr19636-4d.d: Likewise.
+       * testsuite/ld-i386/pr19704.out: Likewise.
+       * testsuite/ld-i386/pr19704a.c: Likewise.
+       * testsuite/ld-i386/pr19704b.c: Likewise.
+       * testsuite/ld-x86-64/pr19636-1.s: Likewise.
+       * testsuite/ld-x86-64/pr19636-1a.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-1b.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-1c.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-1d.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-1e.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-1f.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-1g.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-2.s: Likewise.
+       * testsuite/ld-x86-64/pr19636-2a.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-2b.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-2c.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-2d-nacl.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-2d.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-2e.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-2f.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-2g.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-2h.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-2i.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-3.s: Likewise.
+       * testsuite/ld-x86-64/pr19636-3a.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-3b.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-3c.d: Likewise.
+       * testsuite/ld-x86-64/pr19636-3d.d: Likewise.
+       * testsuite/ld-x86-64/pr19704.out: Likewise.
+       * testsuite/ld-x86-64/pr19704a.c: Likewise.
+       * testsuite/ld-x86-64/pr19704b.c: Likewise.
+       * testsuite/ld-elf/shared.exp (mix_pic_and_non_pic): New.
+       Run mix_pic_and_non_pic.
+       * testsuite/ld-i386/i386.exp (undefined_weak): New.
+       Run undefined_weak and PR ld/19636 tests.
+       * testsuite/ld-x86-64/x86-64.exp: Likewise.
+       * testsuite/ld-x86-64/pr13082-3b.d: Updated.
+       * testsuite/ld-x86-64/pr13082-4b.d: Likewise.
+
 2016-02-25  Nick Clifton  <nickc@redhat.com>
 
        * ld.h (struct ld_config_type): Remove specified_data_size field.
index 7339298fa9920981a58d558b3c22c37dcaccac5f..4a8c0b6e87576bc3cea3592a1e85c6d33833e5ca 100644 (file)
@@ -671,6 +671,7 @@ ELF_DEPS = $(srcdir)/emultempl/elf32.em $(srcdir)/emultempl/elf-generic.em $(src
 ELF_GEN_DEPS = $(srcdir)/emultempl/generic.em $(srcdir)/emultempl/elf-generic.em $(srcdir)/emultempl/genelf.em $(srcdir)/scripttempl/DWARF.sc
 ELF_X86_DEPS = $(ELF_DEPS) $(srcdir)/emulparams/plt_unwind.sh \
               $(srcdir)/emulparams/extern_protected_data.sh \
+              $(srcdir)/emulparams/dynamic_undefined_weak.sh \
               $(srcdir)/emulparams/call_nop.sh
 
 @TDIRS@
index 8803e22c7fa4f7c0f1ebee83f7f79ba601638b28..45388d7bacfe7d46eeaf1a21f054733e9fbb2df9 100644 (file)
@@ -887,6 +887,7 @@ ELF_DEPS = $(srcdir)/emultempl/elf32.em $(srcdir)/emultempl/elf-generic.em $(src
 ELF_GEN_DEPS = $(srcdir)/emultempl/generic.em $(srcdir)/emultempl/elf-generic.em $(srcdir)/emultempl/genelf.em $(srcdir)/scripttempl/DWARF.sc
 ELF_X86_DEPS = $(ELF_DEPS) $(srcdir)/emulparams/plt_unwind.sh \
               $(srcdir)/emulparams/extern_protected_data.sh \
+              $(srcdir)/emulparams/dynamic_undefined_weak.sh \
               $(srcdir)/emulparams/call_nop.sh
 
 
diff --git a/ld/NEWS b/ld/NEWS
index d80cdcfe1b4731f25f3c6ec9428d23419fdf0882..dce600d3d9482cdf24e91fa24b606a2fe88bd85b 100644 (file)
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,8 @@
 -*- text -*-
 
+* Support for -z nodynamic-undefined-weak in the x86 ELF linker, which
+  avoids dynamic relocations against undefined weak symbols in executable.
+
 Changes in 2.26:
 
 * Add --fix-stm32l4xx-629360 to the ARM linker to enable a link-time
diff --git a/ld/emulparams/dynamic_undefined_weak.sh b/ld/emulparams/dynamic_undefined_weak.sh
new file mode 100644 (file)
index 0000000..82d88d6
--- /dev/null
@@ -0,0 +1,12 @@
+PARSE_AND_LIST_OPTIONS_NODYNAMIC_UNDEFINED_WEAK='
+  fprintf (file, _("\
+  -z nodynamic-undefined-weak Do not treat undefined weak symbol as dynamic\n"));
+'
+
+PARSE_AND_LIST_ARGS_CASE_Z_NODYNAMIC_UNDEFINED_WEAK='
+      else if (strcmp (optarg, "nodynamic-undefined-weak") == 0)
+       link_info.dynamic_undefined_weak = FALSE;
+'
+
+PARSE_AND_LIST_OPTIONS="$PARSE_AND_LIST_OPTIONS $PARSE_AND_LIST_OPTIONS_NODYNAMIC_UNDEFINED_WEAK"
+PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_NODYNAMIC_UNDEFINED_WEAK"
index 0a0354839231cfca21af0bf1900ff4f7947224c8..1b285c559a1f6ccb99027c827c69e9a98d5eca34 100644 (file)
@@ -1,5 +1,6 @@
 . ${srcdir}/emulparams/plt_unwind.sh
 . ${srcdir}/emulparams/extern_protected_data.sh
+. ${srcdir}/emulparams/dynamic_undefined_weak.sh
 . ${srcdir}/emulparams/call_nop.sh
 SCRIPT_NAME=elf
 ELFSIZE=32
index 7dceea9a2dde7dfc13e92e550c1869027f7691a2..3451bb2b1ea7a20c146ba8facb8262458f558387 100644 (file)
@@ -1,5 +1,6 @@
 . ${srcdir}/emulparams/plt_unwind.sh
 . ${srcdir}/emulparams/extern_protected_data.sh
+. ${srcdir}/emulparams/dynamic_undefined_weak.sh
 . ${srcdir}/emulparams/call_nop.sh
 SCRIPT_NAME=elf
 OUTPUT_FORMAT="elf32-i386"
index 40ed8c6608bc1292b5e08f98e3a5642db0ac5b62..70db443239597eeef9575777104c4572bfbc4f64 100644 (file)
@@ -1,4 +1,5 @@
 . ${srcdir}/emulparams/extern_protected_data.sh
+. ${srcdir}/emulparams/dynamic_undefined_weak.sh
 . ${srcdir}/emulparams/call_nop.sh
 SCRIPT_NAME=elf
 OUTPUT_FORMAT="elf32-i386"
index 33757bfd9e10f0fcfa2f03af658b0129fe66a463..aa36cb51c2d38962df88bf87b66fa15bac5b6d1a 100644 (file)
@@ -1,5 +1,6 @@
 . ${srcdir}/emulparams/plt_unwind.sh
 . ${srcdir}/emulparams/extern_protected_data.sh
+. ${srcdir}/emulparams/dynamic_undefined_weak.sh
 . ${srcdir}/emulparams/call_nop.sh
 SCRIPT_NAME=elf_chaos
 OUTPUT_FORMAT="elf32-i386"
index f7805819b9b28fea3851a2b44d5dfdeb493a5964..1328520c57cfc5828cde151abd78efeab994ea40 100644 (file)
@@ -1,5 +1,6 @@
 . ${srcdir}/emulparams/plt_unwind.sh
 . ${srcdir}/emulparams/extern_protected_data.sh
+. ${srcdir}/emulparams/dynamic_undefined_weak.sh
 . ${srcdir}/emulparams/call_nop.sh
 SCRIPT_NAME=elf
 OUTPUT_FORMAT="elf32-i386"
index cb289e6307d3f173725fddbe290cd28ffef0f7d7..aaea8c48743438ca8c5eac2999755532b91e66fc 100644 (file)
@@ -12,4 +12,5 @@ GENERATE_PIE_SCRIPT=yes
 NO_SMALL_DATA=yes
 . ${srcdir}/emulparams/vxworks.sh
 . ${srcdir}/emulparams/extern_protected_data.sh
+. ${srcdir}/emulparams/dynamic_undefined_weak.sh
 . ${srcdir}/emulparams/call_nop.sh
index 5fae6515ea36705959d19ec3dcd68e1279588182..863027b57b4a2799efbb48e20c9f9922995c6252 100644 (file)
@@ -1,5 +1,6 @@
 . ${srcdir}/emulparams/plt_unwind.sh
 . ${srcdir}/emulparams/extern_protected_data.sh
+. ${srcdir}/emulparams/dynamic_undefined_weak.sh
 . ${srcdir}/emulparams/call_nop.sh
 SCRIPT_NAME=elf
 OUTPUT_FORMAT="elf32-iamcu"
index 289274daca652351bced41587f33c1d39e0abb6e..494efcc6c909bd19b90d2c453d7457338552c0e8 100644 (file)
@@ -1,5 +1,6 @@
 . ${srcdir}/emulparams/plt_unwind.sh
 . ${srcdir}/emulparams/extern_protected_data.sh
+. ${srcdir}/emulparams/dynamic_undefined_weak.sh
 . ${srcdir}/emulparams/call_nop.sh
 SCRIPT_NAME=elf
 ELFSIZE=64
index 17fa8e2579c3d614a1789bdefbc898649abf3ddd..b1158791f46820032a0fdd05bfce47800a618b13 100644 (file)
@@ -1,5 +1,6 @@
 . ${srcdir}/emulparams/plt_unwind.sh
 . ${srcdir}/emulparams/extern_protected_data.sh
+. ${srcdir}/emulparams/dynamic_undefined_weak.sh
 . ${srcdir}/emulparams/call_nop.sh
 SCRIPT_NAME=elf
 ELFSIZE=64
index 5d31da1ba1bdbb716b57c67274653039fa1e4e5d..0159a6ca44c980a8aa53384dbc166ffdfcaca255 100644 (file)
@@ -1,5 +1,6 @@
 . ${srcdir}/emulparams/plt_unwind.sh
 . ${srcdir}/emulparams/extern_protected_data.sh
+. ${srcdir}/emulparams/dynamic_undefined_weak.sh
 . ${srcdir}/emulparams/call_nop.sh
 SCRIPT_NAME=elf
 ELFSIZE=64
index fd4bd3b3c821879ce6e02f3d881f886ddd0cf3bc..65c68adb0b28a95df0f3144126a726204284c886 100644 (file)
@@ -1,9 +1,13 @@
-PARSE_AND_LIST_OPTIONS='
+PARSE_AND_LIST_OPTIONS_NOEXTEN_PROTECTED_DATA='
   fprintf (file, _("\
   -z noextern-protected-data  Do not treat protected data symbol as external\n"));
 '
 
-PARSE_AND_LIST_ARGS_CASE_Z='
+PARSE_AND_LIST_ARGS_CASE_Z_NOEXTEN_PROTECTED_DATA='
       else if (strcmp (optarg, "noextern-protected-data") == 0)
        link_info.extern_protected_data = FALSE;
 '
+
+
+PARSE_AND_LIST_OPTIONS="$PARSE_AND_LIST_OPTIONS $PARSE_AND_LIST_OPTIONS_NOEXTEN_PROTECTED_DATA"
+PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_NOEXTEN_PROTECTED_DATA"
index 723e5e8ca2c228ecd0b313c124e845d37b1f611a..ee462c5f7e5bbdb9e3198a1ac9255f03fa368b9f 100644 (file)
@@ -1199,6 +1199,12 @@ generated by compiler.  Updates on protected data symbols by another
 module aren't visible to the resulting shared library.  Supported for
 i386 and x86-64.
 
+@item nodynamic-undefined-weak
+Don't treat undefined weak symbols as dynamic when building executable.
+This option overrides linker backend default.  It can be used to avoid
+dynamic relocations against undefined weak symbols in executable.
+Supported for i386 and x86-64.
+
 @item call-nop=prefix-addr
 @itemx call-nop=prefix-nop
 @itemx call-nop=suffix-nop
index 7425da013561c1b4838d3c751a0c786edb9c72c1..21133ab72090a6e2f8fcb80a2c11f40f8fc12fb0 100644 (file)
@@ -278,6 +278,7 @@ main (int argc, char **argv)
   link_info.fini_function = "_fini";
   link_info.relax_pass = 1;
   link_info.extern_protected_data = -1;
+  link_info.dynamic_undefined_weak = -1;
   link_info.pei386_auto_import = -1;
   link_info.spare_dynamic_tags = 5;
   link_info.path_separator = ':';
diff --git a/ld/testsuite/ld-elf/pr19719a.c b/ld/testsuite/ld-elf/pr19719a.c
new file mode 100644 (file)
index 0000000..72249a5
--- /dev/null
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+extern int foo (void);
+extern int bar (void);
+
+int
+main (void)
+{
+  if (foo () == bar ())
+    printf ("PASS\n");
+  return 0;
+}
diff --git a/ld/testsuite/ld-elf/pr19719b.c b/ld/testsuite/ld-elf/pr19719b.c
new file mode 100644 (file)
index 0000000..6ef6268
--- /dev/null
@@ -0,0 +1,8 @@
+extern int __attribute__ ((weak)) fun (void);
+int
+foo (void)
+{
+  if (&fun != 0)
+    return fun ();
+  return 0;
+}
diff --git a/ld/testsuite/ld-elf/pr19719c.c b/ld/testsuite/ld-elf/pr19719c.c
new file mode 100644 (file)
index 0000000..5c877d9
--- /dev/null
@@ -0,0 +1,8 @@
+extern int __attribute__ ((weak)) fun (void);
+int
+bar (void)
+{
+  if (&fun != 0)
+    return fun ();
+  return 0;
+}
diff --git a/ld/testsuite/ld-elf/pr19719d.c b/ld/testsuite/ld-elf/pr19719d.c
new file mode 100644 (file)
index 0000000..231eeef
--- /dev/null
@@ -0,0 +1,5 @@
+int
+fun (void)
+{
+  return 20;
+}
index a8644304cc954064a0ea28d5a786aab11e3576f4..e615f55b95156d82f650be00dba343db10d00956 100644 (file)
@@ -582,3 +582,63 @@ if { [istarget *-*-linux*]
        ] \
     ]
 }
+
+proc mix_pic_and_non_pic {cflags ldflags} {
+    set testname "Mixing PIC and non-PIC"
+    if { ![ string match "" $cflags$ldflags] } {
+       set testname "$testname ($cflags $ldflags)"
+    }
+
+    run_cc_link_tests [list \
+       [list \
+           "Build libpr19719a.so" \
+           "-shared -Wl,-soname,libpr19719.so" \
+           "-fPIC" \
+           { pr19719d.c } \
+           {} \
+           "libpr19719a.so" \
+       ] \
+       [list \
+           "Build libpr19719b.so" \
+           "-shared -Wl,-soname,libpr19719.so" \
+           "-fPIC" \
+           { dummy.c } \
+           {} \
+           "libpr19719b.so" \
+       ] \
+       [list \
+           "Build pr19073b.o" \
+           "-r -nostdlib" \
+           "-fPIC" \
+           { pr19719b.c } \
+           {} \
+           "libpr19719b.o" \
+       ] \
+    ]
+
+    exec cp tmpdir/libpr19719b.so tmpdir/libpr19719.so
+
+    run_ld_link_exec_tests [] [list \
+       [list \
+           "Run pr19719" \
+           "$ldflags tmpdir/libpr19719b.o tmpdir/libpr19719.so -R tmpdir" \
+           "" \
+           { pr19719a.c pr19719c.c } \
+           "pr19719" \
+           "pass.out" \
+           "$cflags" \
+       ] \
+    ]
+
+    exec cp tmpdir/libpr19719a.so tmpdir/libpr19719.so
+
+    set exec_output [run_host_cmd tmpdir/pr19719 ""]
+    if {![string match "PASS" $exec_output]} {
+       fail $testname
+    } else {
+       pass $testname
+    }
+}
+
+mix_pic_and_non_pic "" ""
+mix_pic_and_non_pic "-fPIE" "-pie"
index 1a79694943bb2d6af33d27c93c2d3c591a216223..ab8f017c93746df2e137859564a9c5ed3d71239c 100644 (file)
@@ -320,6 +320,35 @@ run_dump_test "load5b"
 run_dump_test "load6"
 run_dump_test "pr19175"
 run_dump_test "pr19615"
+run_dump_test "pr19636-1a"
+run_dump_test "pr19636-1b"
+run_dump_test "pr19636-1c"
+run_dump_test "pr19636-1d"
+run_dump_test "pr19636-1d-nacl"
+run_dump_test "pr19636-1e"
+run_dump_test "pr19636-1f"
+run_dump_test "pr19636-1g"
+run_dump_test "pr19636-1h"
+run_dump_test "pr19636-1i"
+run_dump_test "pr19636-2a"
+run_dump_test "pr19636-2b"
+run_dump_test "pr19636-2c"
+run_dump_test "pr19636-2c-nacl"
+run_dump_test "pr19636-2d"
+run_dump_test "pr19636-2d-nacl"
+run_dump_test "pr19636-2e"
+run_dump_test "pr19636-2e-nacl"
+run_dump_test "pr19636-3a"
+run_dump_test "pr19636-3b"
+run_dump_test "pr19636-3c"
+run_dump_test "pr19636-3d"
+run_dump_test "pr19636-3e"
+run_dump_test "pr19636-3f"
+run_dump_test "pr19636-3g"
+run_dump_test "pr19636-4a"
+run_dump_test "pr19636-4b"
+run_dump_test "pr19636-4c"
+run_dump_test "pr19636-4d"
 
 if { !([istarget "i?86-*-linux*"]
        || [istarget "i?86-*-gnu*"]
@@ -339,6 +368,62 @@ run_dump_test "pr17935-2"
 run_dump_test "pr18801"
 run_dump_test "pr18815"
 
+proc undefined_weak {cflags ldflags} {
+    set testname "Undefined weak symbol"
+    if { ![ string match "" $cflags$ldflags] } {
+       set testname "$testname ($cflags $ldflags)"
+    }
+
+    if { [ regexp "\-fPIE" $cflags]
+        && ![ regexp "\-z nodynamic-undefined-weak" $ldflags] } {
+       set weak_symbol "Weak defined"
+    } else {
+       set weak_symbol "Weak undefined"
+    }
+
+    run_cc_link_tests [list \
+       [list \
+           "Build libpr19704a.so" \
+           "-shared -Wl,-soname,libpr19704.so" \
+           "" \
+           { dummy.s } \
+           {} \
+           "libpr19704a.so" \
+       ] \
+       [list \
+           "Build libpr19704b.so" \
+           "-shared -Wl,-soname,libpr19704.so" \
+           "-fPIC" \
+           { pr19704b.c } \
+           {} \
+           "libpr19704b.so" \
+       ] \
+    ]
+
+    exec cp tmpdir/libpr19704a.so tmpdir/libpr19704.so
+
+    run_ld_link_exec_tests [] [list \
+       [list \
+           "Run pr19704" \
+           "$ldflags tmpdir/libpr19704.so -R tmpdir" \
+           "" \
+           { pr19704a.c } \
+           "pr19704" \
+           "pr19704.out" \
+           "$cflags" \
+       ] \
+    ]
+
+    exec cp tmpdir/libpr19704b.so tmpdir/libpr19704.so
+
+    set exec_output [run_host_cmd tmpdir/pr19704 ""]
+    if {![string match $weak_symbol $exec_output]} {
+       fail $testname
+    } else {
+       pass $testname
+    }
+}
+
 # Add $PLT_CFLAGS if PLT is expected.
 global PLT_CFLAGS
 
@@ -636,6 +721,12 @@ if { [isnative]
            "got1.out" \
        ] \
     ]
+
+    undefined_weak "" ""
+    undefined_weak "-fPIE" ""
+    undefined_weak "-fPIE" "-pie"
+    undefined_weak "-fPIE" "-z nodynamic-undefined-weak"
+    undefined_weak "-fPIE" "-pie -z nodynamic-undefined-weak"
 }
 
 if { !([istarget "i?86-*-linux*"]
diff --git a/ld/testsuite/ld-i386/pr19636-1.s b/ld/testsuite/ld-i386/pr19636-1.s
new file mode 100644 (file)
index 0000000..b2bc4df
--- /dev/null
@@ -0,0 +1,9 @@
+       .text
+       .weak func1
+       .weak func2
+       .weak func3
+       .globl _start
+_start:
+       cmp func1@GOT(%eax), %eax
+       jmp *func2@GOT(%eax)
+       call func3@PLT
diff --git a/ld/testsuite/ld-i386/pr19636-1a.d b/ld/testsuite/ld-i386/pr19636-1a.d
new file mode 100644 (file)
index 0000000..47b946f
--- /dev/null
@@ -0,0 +1,16 @@
+#source: pr19636-1.s
+#as: --32 -mrelax-relocations=no
+#ld: -pie -m elf_i386 --no-dynamic-linker
+#readelf : -r --wide -x .got -x .got.plt --dyn-syms
+
+There are no relocations in this file.
+
+Symbol table '\.dynsym' contains 1 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
+
+Hex dump of section '.got':
+  0x[0-9a-f]+ [0 ]+\.+
+
+Hex dump of section '.got.plt':
+  0x[0-9a-f]+ +[0-9a-f]+ +[0 ]+ .\.+
diff --git a/ld/testsuite/ld-i386/pr19636-1b.d b/ld/testsuite/ld-i386/pr19636-1b.d
new file mode 100644 (file)
index 0000000..bc67f9d
--- /dev/null
@@ -0,0 +1,19 @@
+#source: pr19636-1.s
+#as: --32 -mrelax-relocations=no
+#ld: -pie -E -m elf_i386 --no-dynamic-linker
+#readelf : -r --wide -x .got -x .got.plt --dyn-syms
+
+There are no relocations in this file.
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +_start
+#...
+
+Hex dump of section '.got':
+  0x[0-9a-f]+ [0 ]+\.+
+
+Hex dump of section '.got.plt':
+  0x[0-9a-f]+ +[0-9a-f]+ +[0 ]+ .\.+
diff --git a/ld/testsuite/ld-i386/pr19636-1c.d b/ld/testsuite/ld-i386/pr19636-1c.d
new file mode 100644 (file)
index 0000000..9aebbb1
--- /dev/null
@@ -0,0 +1,9 @@
+#source: pr19636-1.s
+#as: --32 -mrelax-relocations=no
+#ld: -pie -E -m elf_i386 --no-dynamic-linker
+#readelf : --wide --dyn-syms
+
+#failif
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func[0-9]?
+#...
diff --git a/ld/testsuite/ld-i386/pr19636-1d-nacl.d b/ld/testsuite/ld-i386/pr19636-1d-nacl.d
new file mode 100644 (file)
index 0000000..fef5eea
--- /dev/null
@@ -0,0 +1,124 @@
+#source: pr19636-1.s
+#as: --32 -mrelax-relocations=no
+#ld: -pie -m elf_i386 --no-dynamic-linker
+#objdump: -dw
+#target: i?86-*-nacl* x86_64-*-nacl*
+
+.*: +file format .*
+
+
+Disassembly of section .plt:
+
+0+ <.plt>:
+[      ]*[a-f0-9]+:    ff 73 04                pushl  0x4\(%ebx\)
+[      ]*[a-f0-9]+:    8b 4b 08                mov    0x8\(%ebx\),%ecx
+[      ]*[a-f0-9]+:    83 e1 e0                and    \$0xffffffe0,%ecx
+[      ]*[a-f0-9]+:    ff e1                   jmp    \*%ecx
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    8b 8b 0c 00 00 00       mov    0xc\(%ebx\),%ecx
+[      ]*[a-f0-9]+:    83 e1 e0                and    \$0xffffffe0,%ecx
+[      ]*[a-f0-9]+:    ff e1                   jmp    \*%ecx
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    68 00 00 00 00          push   \$0x0
+[      ]*[a-f0-9]+:    e9 00 00 00 00          jmp    6a <_start-0x16>
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+
+Disassembly of section .text:
+
+0+80 <_start>:
+[      ]*[a-f0-9]+:    3b 80 f8 ff ff ff       cmp    -0x8\(%eax\),%eax
+[      ]*[a-f0-9]+:    ff a0 fc ff ff ff       jmp    \*-0x4\(%eax\)
+[      ]*[a-f0-9]+:    e8 af ff ff ff          call   40 <_start-0x40>
diff --git a/ld/testsuite/ld-i386/pr19636-1d.d b/ld/testsuite/ld-i386/pr19636-1d.d
new file mode 100644 (file)
index 0000000..16e316c
--- /dev/null
@@ -0,0 +1,26 @@
+#source: pr19636-1.s
+#as: --32 -mrelax-relocations=no
+#ld: -pie -m elf_i386 --no-dynamic-linker
+#objdump: -dw
+#notarget: i?86-*-nacl* x86_64-*-nacl*
+
+.*: +file format .*
+
+
+Disassembly of section .plt:
+
+0+c0 <.plt>:
+[      ]*[a-f0-9]+:    ff b3 04 00 00 00       pushl  0x4\(%ebx\)
+[      ]*[a-f0-9]+:    ff a3 08 00 00 00       jmp    \*0x8\(%ebx\)
+[      ]*[a-f0-9]+:    00 00                   add    %al,\(%eax\)
+[      ]*[a-f0-9]+:    00 00                   add    %al,\(%eax\)
+[      ]*[a-f0-9]+:    ff a3 0c 00 00 00       jmp    \*0xc\(%ebx\)
+[      ]*[a-f0-9]+:    68 00 00 00 00          push   \$0x0
+[      ]*[a-f0-9]+:    e9 00 00 00 00          jmp    [a-f0-9]+ <.*>
+
+Disassembly of section .text:
+
+0+e0 <_start>:
+[      ]*[a-f0-9]+:    3b 80 f8 ff ff ff       cmp    -0x8\(%eax\),%eax
+[      ]*[a-f0-9]+:    ff a0 fc ff ff ff       jmp    \*-0x4\(%eax\)
+[      ]*[a-f0-9]+:    e8 df ff ff ff          call   d0 <_start-0x10>
diff --git a/ld/testsuite/ld-i386/pr19636-1e.d b/ld/testsuite/ld-i386/pr19636-1e.d
new file mode 100644 (file)
index 0000000..25a5b64
--- /dev/null
@@ -0,0 +1,19 @@
+#source: pr19636-1.s
+#as: --32 -mrelax-relocations=no
+#ld: -shared -m elf_i386 --no-dynamic-linker
+#readelf : -r --wide --dyn-syms
+
+Relocation section '\.rel\.dyn' at offset [0x0-9a-f]+ contains 2 entries:
+ +Offset +Info +Type +Sym. Value +Symbol's Name
+[0-9a-f]+ +[0-9a-f]+ +R_386_GLOB_DAT +0+ +func1
+[0-9a-f]+ +[0-9a-f]+ +R_386_GLOB_DAT +0+ +func2
+
+Relocation section '\.rel\.plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym. Value +Symbol's Name
+[0-9a-f]+ +[0-9a-f]+ +R_386_JUMP_SLOT +0+ +func3
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func[0-9]?
+#pass
diff --git a/ld/testsuite/ld-i386/pr19636-1f.d b/ld/testsuite/ld-i386/pr19636-1f.d
new file mode 100644 (file)
index 0000000..0bf7595
--- /dev/null
@@ -0,0 +1,19 @@
+#source: pr19636-1.s
+#as: --32 -mrelax-relocations=no
+#ld: -shared -Bsymbolic -m elf_i386 --no-dynamic-linker
+#readelf : -r --wide --dyn-syms
+
+Relocation section '\.rel\.dyn' at offset [0x0-9a-f]+ contains 2 entries:
+ +Offset +Info +Type +Sym. Value +Symbol's Name
+[0-9a-f]+ +[0-9a-f]+ +R_386_GLOB_DAT +0+ +func1
+[0-9a-f]+ +[0-9a-f]+ +R_386_GLOB_DAT +0+ +func2
+
+Relocation section '\.rel\.plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym. Value +Symbol's Name
+[0-9a-f]+ +[0-9a-f]+ +R_386_JUMP_SLOT +0+ +func3
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func[0-9]?
+#pass
diff --git a/ld/testsuite/ld-i386/pr19636-1g.d b/ld/testsuite/ld-i386/pr19636-1g.d
new file mode 100644 (file)
index 0000000..1b3233f
--- /dev/null
@@ -0,0 +1,12 @@
+#source: pr19636-1.s
+#as: --32 -mrelax-relocations=no
+#ld: -m elf_i386 --no-dynamic-linker
+#readelf : -r --wide -x .got -x .got.plt --dyn-syms
+
+There are no relocations in this file.
+
+Hex dump of section '.got':
+  0x[0-9a-f]+ [0 ]+\.+
+
+Hex dump of section '.got.plt':
+  0x[0-9a-f]+ [0 ]+\.+
diff --git a/ld/testsuite/ld-i386/pr19636-1h.d b/ld/testsuite/ld-i386/pr19636-1h.d
new file mode 100644 (file)
index 0000000..f9c4837
--- /dev/null
@@ -0,0 +1,19 @@
+#source: pr19636-1.s
+#as: --32 -mrelax-relocations=no
+#ld: -E -m elf_i386 --no-dynamic-linker
+#readelf : -r --wide -x .got -x .got.plt --dyn-syms
+
+There are no relocations in this file.
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +_start
+#...
+
+Hex dump of section '.got':
+  0x[0-9a-f]+ [0 ]+\.+
+
+Hex dump of section '.got.plt':
+  0x[0-9a-f]+ +[0-9a-f]+ +[0 ]+ .\.+
diff --git a/ld/testsuite/ld-i386/pr19636-1i.d b/ld/testsuite/ld-i386/pr19636-1i.d
new file mode 100644 (file)
index 0000000..f67e39b
--- /dev/null
@@ -0,0 +1,9 @@
+#source: pr19636-1.s
+#as: --32 -mrelax-relocations=no
+#ld: -E -m elf_i386 --no-dynamic-linker
+#readelf : --wide --dyn-syms
+
+#failif
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func[0-9]?
+#...
diff --git a/ld/testsuite/ld-i386/pr19636-2.s b/ld/testsuite/ld-i386/pr19636-2.s
new file mode 100644 (file)
index 0000000..e8e7c9f
--- /dev/null
@@ -0,0 +1,9 @@
+       .text
+       .weak func
+       .globl _start
+_start:
+       cmp func@GOT(%eax), %eax
+       jmp *func@GOT(%eax)
+       call func@PLT
+       cmp $func, %eax
+       call func
diff --git a/ld/testsuite/ld-i386/pr19636-2a.d b/ld/testsuite/ld-i386/pr19636-2a.d
new file mode 100644 (file)
index 0000000..fbed7e7
--- /dev/null
@@ -0,0 +1,19 @@
+#source: pr19636-2.s
+#as: --32 -mrelax-relocations=no
+#ld: -pie -m elf_i386
+#readelf : -r --wide -x .got -x .got.plt --dyn-syms
+
+Relocation section '\.rel\.dyn' at offset [0x0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym. Value +Symbol's Name
+[0-9a-f]+ +[0-9a-f]+ +R_386_PC32 +0+ +func
+
+Symbol table '\.dynsym' contains 2 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func
+
+Hex dump of section '.got':
+  0x[0-9a-f]+ [0 ]+\.+
+
+Hex dump of section '.got.plt':
+  0x[0-9a-f]+ +[0-9a-f]+ +[0 ]+ .\.+
diff --git a/ld/testsuite/ld-i386/pr19636-2b.d b/ld/testsuite/ld-i386/pr19636-2b.d
new file mode 100644 (file)
index 0000000..9a0a263
--- /dev/null
@@ -0,0 +1,22 @@
+#source: pr19636-2.s
+#as: --32 -mrelax-relocations=no
+#ld: -pie -E -m elf_i386
+#readelf : -r --wide -x .got -x .got.plt --dyn-syms
+
+Relocation section '\.rel\.dyn' at offset [0x0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym. Value +Symbol's Name
+[0-9a-f]+ +[0-9a-f]+ +R_386_PC32 +0+ +func
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +_start
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func
+#...
+
+Hex dump of section '.got':
+  0x[0-9a-f]+ [0 ]+\.+
+
+Hex dump of section '.got.plt':
+  0x[0-9a-f]+ +[0-9a-f]+ +[0 ]+ .\.+
diff --git a/ld/testsuite/ld-i386/pr19636-2c-nacl.d b/ld/testsuite/ld-i386/pr19636-2c-nacl.d
new file mode 100644 (file)
index 0000000..7543e0e
--- /dev/null
@@ -0,0 +1,126 @@
+#source: pr19636-2.s
+#as: --32 -mrelax-relocations=no
+#ld: -pie -m elf_i386
+#objdump: -dw
+#target: i?86-*-nacl* x86_64-*-nacl*
+
+.*: +file format .*
+
+
+Disassembly of section .plt:
+
+0+ <.plt>:
+[      ]*[a-f0-9]+:    ff 73 04                pushl  0x4\(%ebx\)
+[      ]*[a-f0-9]+:    8b 4b 08                mov    0x8\(%ebx\),%ecx
+[      ]*[a-f0-9]+:    83 e1 e0                and    \$0xffffffe0,%ecx
+[      ]*[a-f0-9]+:    ff e1                   jmp    \*%ecx
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    8b 8b 0c 00 00 00       mov    0xc\(%ebx\),%ecx
+[      ]*[a-f0-9]+:    83 e1 e0                and    \$0xffffffe0,%ecx
+[      ]*[a-f0-9]+:    ff e1                   jmp    \*%ecx
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    68 00 00 00 00          push   \$0x0
+[      ]*[a-f0-9]+:    e9 00 00 00 00          jmp    6a <_start-0x16>
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    90                      nop
+
+Disassembly of section .text:
+
+0+80 <_start>:
+[      ]*[a-f0-9]+:    3b 80 fc ff ff ff       cmp    -0x4\(%eax\),%eax
+[      ]*[a-f0-9]+:    ff a0 fc ff ff ff       jmp    \*-0x4\(%eax\)
+[      ]*[a-f0-9]+:    e8 af ff ff ff          call   40 <_start-0x40>
+[      ]*[a-f0-9]+:    3d 00 00 00 00          cmp    \$0x0,%eax
+[      ]*[a-f0-9]+:    e8 fc ff ff ff          call   97 <_start\+0x17>
diff --git a/ld/testsuite/ld-i386/pr19636-2c.d b/ld/testsuite/ld-i386/pr19636-2c.d
new file mode 100644 (file)
index 0000000..98b53aa
--- /dev/null
@@ -0,0 +1,28 @@
+#source: pr19636-2.s
+#as: --32 -mrelax-relocations=no
+#ld: -pie -m elf_i386
+#objdump: -dw
+#notarget: i?86-*-nacl* x86_64-*-nacl*
+
+.*: +file format .*
+
+
+Disassembly of section .plt:
+
+0+130 <.plt>:
+[      ]*[a-f0-9]+:    ff b3 04 00 00 00       pushl  0x4\(%ebx\)
+[      ]*[a-f0-9]+:    ff a3 08 00 00 00       jmp    \*0x8\(%ebx\)
+[      ]*[a-f0-9]+:    00 00                   add    %al,\(%eax\)
+[      ]*[a-f0-9]+:    00 00                   add    %al,\(%eax\)
+[      ]*[a-f0-9]+:    ff a3 0c 00 00 00       jmp    \*0xc\(%ebx\)
+[      ]*[a-f0-9]+:    68 00 00 00 00          push   \$0x0
+[      ]*[a-f0-9]+:    e9 00 00 00 00          jmp    150 <_start>
+
+Disassembly of section .text:
+
+0+150 <_start>:
+[      ]*[a-f0-9]+:    3b 80 fc ff ff ff       cmp    -0x4\(%eax\),%eax
+[      ]*[a-f0-9]+:    ff a0 fc ff ff ff       jmp    \*-0x4\(%eax\)
+[      ]*[a-f0-9]+:    e8 df ff ff ff          call   140 <_start-0x10>
+[      ]*[a-f0-9]+:    3d 00 00 00 00          cmp    \$0x0,%eax
+[      ]*[a-f0-9]+:    e8 fc ff ff ff          call   167 <_start\+0x17>
diff --git a/ld/testsuite/ld-i386/pr19636-2d-nacl.d b/ld/testsuite/ld-i386/pr19636-2d-nacl.d
new file mode 100644 (file)
index 0000000..99c491f
--- /dev/null
@@ -0,0 +1,21 @@
+#source: pr19636-2.s
+#as: --32 -mrelax-relocations=no
+#ld: -shared -m elf_i386
+#readelf : -r --wide --dyn-syms
+#target: i?86-*-nacl* x86_64-*-nacl*
+
+Relocation section '\.rel\.dyn' at offset [0x0-9a-f]+ contains 3 entries:
+ +Offset +Info +Type +Sym. Value +Symbol's Name
+[0-9a-f]+ +[0-9a-f]+ +R_386_32 +0+ +func
+[0-9a-f]+ +[0-9a-f]+ +R_386_PC32 +0+ +func
+[0-9a-f]+ +[0-9a-f]+ +R_386_GLOB_DAT +0+ +func
+
+Relocation section '\.rel\.plt' at offset [0x0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym. Value +Symbol's Name
+[0-9a-f]+ +[0-9a-f]+ +R_386_JUMP_SLOT +0+ +func
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func
+#pass
diff --git a/ld/testsuite/ld-i386/pr19636-2d.d b/ld/testsuite/ld-i386/pr19636-2d.d
new file mode 100644 (file)
index 0000000..28eaa04
--- /dev/null
@@ -0,0 +1,17 @@
+#source: pr19636-2.s
+#as: --32 -mrelax-relocations=no
+#ld: -shared -m elf_i386
+#readelf : -r --wide --dyn-syms
+#notarget: i?86-*-nacl* x86_64-*-nacl*
+
+Relocation section '\.rel\.dyn' at offset [0x0-9a-f]+ contains 3 entries:
+ +Offset +Info +Type +Sym. Value +Symbol's Name
+[0-9a-f]+ +[0-9a-f]+ +R_386_32 +0+ +func
+[0-9a-f]+ +[0-9a-f]+ +R_386_PC32 +0+ +func
+[0-9a-f]+ +[0-9a-f]+ +R_386_GLOB_DAT +0+ +func
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func
+#pass
diff --git a/ld/testsuite/ld-i386/pr19636-2e-nacl.d b/ld/testsuite/ld-i386/pr19636-2e-nacl.d
new file mode 100644 (file)
index 0000000..f791128
--- /dev/null
@@ -0,0 +1,21 @@
+#source: pr19636-2.s
+#as: --32 -mrelax-relocations=no
+#ld: -shared -Bsymbolic -m elf_i386
+#readelf : -r --wide --dyn-syms
+#target: i?86-*-nacl* x86_64-*-nacl*
+
+Relocation section '\.rel\.dyn' at offset [0x0-9a-f]+ contains 3 entries:
+ +Offset +Info +Type +Sym. Value +Symbol's Name
+[0-9a-f]+ +[0-9a-f]+ +R_386_32 +0+ +func
+[0-9a-f]+ +[0-9a-f]+ +R_386_PC32 +0+ +func
+[0-9a-f]+ +[0-9a-f]+ +R_386_GLOB_DAT +0+ +func
+
+Relocation section '\.rel\.plt' at offset [0x0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym. Value +Symbol's Name
+[0-9a-f]+ +[0-9a-f]+ +R_386_JUMP_SLOT +0+ +func
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func
+#pass
diff --git a/ld/testsuite/ld-i386/pr19636-2e.d b/ld/testsuite/ld-i386/pr19636-2e.d
new file mode 100644 (file)
index 0000000..148e306
--- /dev/null
@@ -0,0 +1,17 @@
+#source: pr19636-2.s
+#as: --32 -mrelax-relocations=no
+#ld: -shared -Bsymbolic -m elf_i386
+#readelf : -r --wide --dyn-syms
+#notarget: i?86-*-nacl* x86_64-*-nacl*
+
+Relocation section '\.rel\.dyn' at offset [0x0-9a-f]+ contains 3 entries:
+ +Offset +Info +Type +Sym. Value +Symbol's Name
+[0-9a-f]+ +[0-9a-f]+ +R_386_32 +0+ +func
+[0-9a-f]+ +[0-9a-f]+ +R_386_PC32 +0+ +func
+[0-9a-f]+ +[0-9a-f]+ +R_386_GLOB_DAT +0+ +func
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func
+#pass
diff --git a/ld/testsuite/ld-i386/pr19636-3.s b/ld/testsuite/ld-i386/pr19636-3.s
new file mode 100644 (file)
index 0000000..9bd7e4a
--- /dev/null
@@ -0,0 +1,5 @@
+       .text
+       .weak func
+       .globl _start
+_start:
+       .dc.a func
diff --git a/ld/testsuite/ld-i386/pr19636-3a.d b/ld/testsuite/ld-i386/pr19636-3a.d
new file mode 100644 (file)
index 0000000..078896e
--- /dev/null
@@ -0,0 +1,10 @@
+#source: pr19636-3.s
+#as: --32
+#ld: -pie -m elf_i386
+#readelf : -r --dyn-syms --wide
+
+There are no relocations in this file.
+
+Symbol table '\.dynsym' contains 1 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
diff --git a/ld/testsuite/ld-i386/pr19636-3b.d b/ld/testsuite/ld-i386/pr19636-3b.d
new file mode 100644 (file)
index 0000000..e8f9138
--- /dev/null
@@ -0,0 +1,6 @@
+#source: pr19636-3.s
+#as: --32
+#ld: -pie -E -m elf_i386
+#readelf : -r --wide
+
+There are no relocations in this file.
diff --git a/ld/testsuite/ld-i386/pr19636-3c.d b/ld/testsuite/ld-i386/pr19636-3c.d
new file mode 100644 (file)
index 0000000..701b131
--- /dev/null
@@ -0,0 +1,9 @@
+#source: pr19636-3.s
+#as: --32
+#ld: -pie -E -m elf_i386
+#readelf : --dyn-syms --wide
+
+#failif
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func
+#...
diff --git a/ld/testsuite/ld-i386/pr19636-3d.d b/ld/testsuite/ld-i386/pr19636-3d.d
new file mode 100644 (file)
index 0000000..12ff6b8
--- /dev/null
@@ -0,0 +1,14 @@
+#source: pr19636-3.s
+#as: --32
+#ld: -shared -m elf_i386
+#readelf : -r --wide --dyn-syms
+
+Relocation section '\.rela?\..*' at offset 0x[0-9a-f]+ contains [0-9]+ entries:
+#...
+[0-9a-f]+[ \t]+[0-9a-f]+[ \t]+R_.*[ \t]+[0-9a-f]+[ \t]+func.*
+#...
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func
+#...
diff --git a/ld/testsuite/ld-i386/pr19636-3e.d b/ld/testsuite/ld-i386/pr19636-3e.d
new file mode 100644 (file)
index 0000000..a0f3344
--- /dev/null
@@ -0,0 +1,14 @@
+#source: pr19636-3.s
+#as: --32
+#ld: -shared -Bsymbolic -m elf_i386
+#readelf : -r --wide --dyn-syms
+
+Relocation section '\.rela?\..*' at offset 0x[0-9a-f]+ contains [0-9]+ entries:
+#...
+[0-9a-f]+[ \t]+[0-9a-f]+[ \t]+R_.*[ \t]+[0-9a-f]+[ \t]+func.*
+#...
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func
+#...
diff --git a/ld/testsuite/ld-i386/pr19636-3f.d b/ld/testsuite/ld-i386/pr19636-3f.d
new file mode 100644 (file)
index 0000000..858850b
--- /dev/null
@@ -0,0 +1,6 @@
+#source: pr19636-3.s
+#as: --32
+#ld: -E -m elf_i386
+#readelf : -r --wide
+
+There are no relocations in this file.
diff --git a/ld/testsuite/ld-i386/pr19636-3g.d b/ld/testsuite/ld-i386/pr19636-3g.d
new file mode 100644 (file)
index 0000000..1b0d668
--- /dev/null
@@ -0,0 +1,9 @@
+#source: pr19636-3.s
+#as: --32
+#ld: -E -m elf_i386
+#readelf : --dyn-syms --wide
+
+#failif
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func
+#...
diff --git a/ld/testsuite/ld-i386/pr19636-4.s b/ld/testsuite/ld-i386/pr19636-4.s
new file mode 100644 (file)
index 0000000..6c981f5
--- /dev/null
@@ -0,0 +1,14 @@
+       .text
+       .type start,"function"
+       .global start
+start:
+       .type _start,"function"
+       .global _start
+_start:
+       .type __start,"function"
+       .global __start
+__start:
+       .type main,"function"
+       .global main
+main:
+       .long 0
diff --git a/ld/testsuite/ld-i386/pr19636-4a.d b/ld/testsuite/ld-i386/pr19636-4a.d
new file mode 100644 (file)
index 0000000..8cdbc1c
--- /dev/null
@@ -0,0 +1,8 @@
+#source: pr19636-4.s
+#as: --32
+#ld: -pie --defsym foobar=0x100 -m elf_i386
+#readelf : --dyn-syms --wide
+
+Symbol table '\.dynsym' contains 1 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
diff --git a/ld/testsuite/ld-i386/pr19636-4b.d b/ld/testsuite/ld-i386/pr19636-4b.d
new file mode 100644 (file)
index 0000000..7ac3629
--- /dev/null
@@ -0,0 +1,10 @@
+#source: pr19636-4.s
+#as: --32
+#ld: -pie -E --defsym foobar=0x100 -m elf_i386
+#readelf : --dyn-syms --wide
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +0+100 +0 +NOTYPE +GLOBAL +DEFAULT +ABS +foobar
+#pass
diff --git a/ld/testsuite/ld-i386/pr19636-4c.d b/ld/testsuite/ld-i386/pr19636-4c.d
new file mode 100644 (file)
index 0000000..a3891c4
--- /dev/null
@@ -0,0 +1,10 @@
+#source: pr19636-4.s
+#as: --32
+#ld: -shared -Bsymbolic --defsym foobar=0x100 -m elf_i386
+#readelf : --dyn-syms --wide
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +0+100 +0 +NOTYPE +GLOBAL +DEFAULT +ABS +foobar
+#pass
diff --git a/ld/testsuite/ld-i386/pr19636-4d.d b/ld/testsuite/ld-i386/pr19636-4d.d
new file mode 100644 (file)
index 0000000..a9487f0
--- /dev/null
@@ -0,0 +1,10 @@
+#source: pr19636-4.s
+#as: --32
+#ld: -E --defsym foobar=0x100 -m elf_i386
+#readelf : --dyn-syms --wide
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +0+100 +0 +NOTYPE +GLOBAL +DEFAULT +ABS +foobar
+#pass
diff --git a/ld/testsuite/ld-i386/pr19704.out b/ld/testsuite/ld-i386/pr19704.out
new file mode 100644 (file)
index 0000000..3506f46
--- /dev/null
@@ -0,0 +1 @@
+Weak undefined
diff --git a/ld/testsuite/ld-i386/pr19704a.c b/ld/testsuite/ld-i386/pr19704a.c
new file mode 100644 (file)
index 0000000..aa52e00
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdio.h>
+
+extern int __attribute__ ((weak)) fun (void);
+
+int
+main (void)
+{
+  if (&fun != 0)
+    fun ();
+  else
+    printf ("Weak undefined\n");
+  return 0;
+}
diff --git a/ld/testsuite/ld-i386/pr19704b.c b/ld/testsuite/ld-i386/pr19704b.c
new file mode 100644 (file)
index 0000000..1d688e1
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+void
+fun (void)
+{
+  printf ("Weak defined\n");
+}
index 12efaf096469c0d53f6342b82f7a15dd7742b9bc..766dd741bbbb40429cf259ef0535f8d04eb9181e 100644 (file)
@@ -4,6 +4,4 @@
 #ld: -pie -melf32_x86_64
 #readelf: -r --wide
 
-Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entries:
- Offset     Info    Type                Sym. Value  Symbol's Name \+ Addend
-[0-9a-f]+ +[0-9a-f]+ +R_X86_64_32 +[0-9a-f]+ +func \+ 0
+There are no relocations in this file.
index cb4d90af198d3e0c02fc206909ec754a3a06ba05..6d4a35b7d65129e907d0ac32b9bbad88780fa8a3 100644 (file)
@@ -4,6 +4,4 @@
 #ld: -pie -melf32_x86_64
 #readelf: -r --wide
 
-Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entries:
- Offset     Info    Type                Sym. Value  Symbol's Name \+ Addend
-[0-9a-f]+ +[0-9a-f]+ +R_X86_64_64 +[0-9a-f]+ +func \+ 1
+There are no relocations in this file.
diff --git a/ld/testsuite/ld-x86-64/pr19636-1.s b/ld/testsuite/ld-x86-64/pr19636-1.s
new file mode 100644 (file)
index 0000000..9bd7e4a
--- /dev/null
@@ -0,0 +1,5 @@
+       .text
+       .weak func
+       .globl _start
+_start:
+       .dc.a func
diff --git a/ld/testsuite/ld-x86-64/pr19636-1a.d b/ld/testsuite/ld-x86-64/pr19636-1a.d
new file mode 100644 (file)
index 0000000..5cdfcb9
--- /dev/null
@@ -0,0 +1,10 @@
+#source: pr19636-1.s
+#as: --64
+#ld: -pie -m elf_x86_64
+#readelf : -r --dyn-syms --wide
+
+There are no relocations in this file.
+
+Symbol table '\.dynsym' contains 1 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
diff --git a/ld/testsuite/ld-x86-64/pr19636-1b.d b/ld/testsuite/ld-x86-64/pr19636-1b.d
new file mode 100644 (file)
index 0000000..e68e399
--- /dev/null
@@ -0,0 +1,6 @@
+#source: pr19636-1.s
+#as: --64
+#ld: -pie -E -m elf_x86_64
+#readelf : -r --wide
+
+There are no relocations in this file.
diff --git a/ld/testsuite/ld-x86-64/pr19636-1c.d b/ld/testsuite/ld-x86-64/pr19636-1c.d
new file mode 100644 (file)
index 0000000..5262a51
--- /dev/null
@@ -0,0 +1,9 @@
+#source: pr19636-1.s
+#as: --64
+#ld: -pie -E -m elf_x86_64
+#readelf : --dyn-syms --wide
+
+#failif
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func
+#...
diff --git a/ld/testsuite/ld-x86-64/pr19636-1d.d b/ld/testsuite/ld-x86-64/pr19636-1d.d
new file mode 100644 (file)
index 0000000..00da41e
--- /dev/null
@@ -0,0 +1,14 @@
+#source: pr19636-1.s
+#as: --64
+#ld: -shared -m elf_x86_64
+#readelf : -r --wide --dyn-syms
+
+Relocation section '\.rela?\..*' at offset 0x[0-9a-f]+ contains [0-9]+ entries:
+#...
+[0-9a-f]+[ \t]+[0-9a-f]+[ \t]+R_.*[ \t]+[0-9a-f]+[ \t]+func.*
+#...
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func
+#...
diff --git a/ld/testsuite/ld-x86-64/pr19636-1e.d b/ld/testsuite/ld-x86-64/pr19636-1e.d
new file mode 100644 (file)
index 0000000..ea369b2
--- /dev/null
@@ -0,0 +1,14 @@
+#source: pr19636-1.s
+#as: --64
+#ld: -shared -Bsymbolic -m elf_x86_64
+#readelf : -r --wide --dyn-syms
+
+Relocation section '\.rela?\..*' at offset 0x[0-9a-f]+ contains [0-9]+ entries:
+#...
+[0-9a-f]+[ \t]+[0-9a-f]+[ \t]+R_.*[ \t]+[0-9a-f]+[ \t]+func.*
+#...
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func
+#...
diff --git a/ld/testsuite/ld-x86-64/pr19636-1f.d b/ld/testsuite/ld-x86-64/pr19636-1f.d
new file mode 100644 (file)
index 0000000..4fc721a
--- /dev/null
@@ -0,0 +1,6 @@
+#source: pr19636-1.s
+#as: --64
+#ld: -E -m elf_x86_64
+#readelf : -r --wide
+
+There are no relocations in this file.
diff --git a/ld/testsuite/ld-x86-64/pr19636-1g.d b/ld/testsuite/ld-x86-64/pr19636-1g.d
new file mode 100644 (file)
index 0000000..7cd52a5
--- /dev/null
@@ -0,0 +1,9 @@
+#source: pr19636-1.s
+#as: --64
+#ld: -E -m elf_x86_64
+#readelf : --dyn-syms --wide
+
+#failif
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func
+#...
diff --git a/ld/testsuite/ld-x86-64/pr19636-2.s b/ld/testsuite/ld-x86-64/pr19636-2.s
new file mode 100644 (file)
index 0000000..8814ecd
--- /dev/null
@@ -0,0 +1,9 @@
+       .text
+       .weak func1
+       .weak func2
+       .weak func3
+       .globl _start
+_start:
+       cmp func1@GOTPCREL(%rip),%rax
+       jmp *func2@GOTPCREL(%rip)
+       call func3@PLT
diff --git a/ld/testsuite/ld-x86-64/pr19636-2a.d b/ld/testsuite/ld-x86-64/pr19636-2a.d
new file mode 100644 (file)
index 0000000..1efb87e
--- /dev/null
@@ -0,0 +1,17 @@
+#source: pr19636-2.s
+#as: --64 -mrelax-relocations=no
+#ld: -pie -m elf_x86_64 --no-dynamic-linker
+#readelf : -r --wide -x .got -x .got.plt --dyn-syms
+
+There are no relocations in this file.
+
+Symbol table '\.dynsym' contains 1 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
+
+Hex dump of section '.got':
+  0x[0-9a-f]+ [0 ]+\.+
+
+Hex dump of section '.got.plt':
+  0x[0-9a-f]+ +[0-9a-f]+ +[0 ]+ .+
+  0x[0-9a-f]+ [0 ]+\.+
diff --git a/ld/testsuite/ld-x86-64/pr19636-2b.d b/ld/testsuite/ld-x86-64/pr19636-2b.d
new file mode 100644 (file)
index 0000000..7e3b6ff
--- /dev/null
@@ -0,0 +1,20 @@
+#source: pr19636-2.s
+#as: --64 -mrelax-relocations=no
+#ld: -pie -E -m elf_x86_64 --no-dynamic-linker
+#readelf : -r --wide -x .got -x .got.plt --dyn-syms
+
+There are no relocations in this file.
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +_start
+#...
+
+Hex dump of section '.got':
+  0x[0-9a-f]+ [0 ]+\.+
+
+Hex dump of section '.got.plt':
+  0x[0-9a-f]+ +[0-9a-f]+ +[0 ]+ .+
+  0x[0-9a-f]+ [0 ]+\.+
diff --git a/ld/testsuite/ld-x86-64/pr19636-2c.d b/ld/testsuite/ld-x86-64/pr19636-2c.d
new file mode 100644 (file)
index 0000000..4659da7
--- /dev/null
@@ -0,0 +1,9 @@
+#source: pr19636-2.s
+#as: --64 -mrelax-relocations=no
+#ld: -pie -E -m elf_x86_64 --no-dynamic-linker
+#readelf : --wide --dyn-syms
+
+#failif
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func[0-9]?
+#...
diff --git a/ld/testsuite/ld-x86-64/pr19636-2d-nacl.d b/ld/testsuite/ld-x86-64/pr19636-2d-nacl.d
new file mode 100644 (file)
index 0000000..67851a6
--- /dev/null
@@ -0,0 +1,37 @@
+#source: pr19636-2.s
+#as: --64 -mrelax-relocations=no
+#ld: -pie -m elf_x86_64 --no-dynamic-linker
+#objdump: -dw
+#target: x86_64-*-nacl*
+
+.*: +file format .*
+
+
+Disassembly of section .plt:
+
+0+ <.plt>:
+[      ]*[a-f0-9]+:    ff 35 42 02 01 10       pushq  0x10010242\(%rip\)        # 10010248 <_GLOBAL_OFFSET_TABLE_\+0x8>
+[      ]*[a-f0-9]+:    4c 8b 1d 43 02 01 10    mov    0x10010243\(%rip\),%r11        # 10010250 <_GLOBAL_OFFSET_TABLE_\+0x10>
+[      ]*[a-f0-9]+:    41 83 e3 e0             and    \$0xffffffe0,%r11d
+[      ]*[a-f0-9]+:    4d 01 fb                add    %r15,%r11
+[      ]*[a-f0-9]+:    41 ff e3                jmpq   \*%r11
+[      ]*[a-f0-9]+:    66 0f 1f 84 00 00 00 00 00      nopw   0x0\(%rax,%rax,1\)
+[      ]*[a-f0-9]+:    66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00    data16 data16 data16 data16 data16 nopw %cs:0x0\(%rax,%rax,1\)
+[      ]*[a-f0-9]+:    66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00    data16 data16 data16 data16 data16 nopw %cs:0x0\(%rax,%rax,1\)
+[      ]*[a-f0-9]+:    66 90                   xchg   %ax,%ax
+[      ]*[a-f0-9]+:    4c 8b 1d 11 02 01 10    mov    0x10010211\(%rip\),%r11        # 10010258 <_GLOBAL_OFFSET_TABLE_\+0x18>
+[      ]*[a-f0-9]+:    41 83 e3 e0             and    \$0xffffffe0,%r11d
+[      ]*[a-f0-9]+:    4d 01 fb                add    %r15,%r11
+[      ]*[a-f0-9]+:    41 ff e3                jmpq   \*%r11
+[      ]*[a-f0-9]+:    66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00    data16 data16 data16 data16 data16 nopw %cs:0x0\(%rax,%rax,1\)
+[      ]*[a-f0-9]+:    68 00 00 00 00          pushq  \$0x0
+[      ]*[a-f0-9]+:    e9 00 00 00 00          jmpq   6a <_start-0x16>
+[      ]*[a-f0-9]+:    66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00    data16 data16 data16 data16 data16 nopw %cs:0x0\(%rax,%rax,1\)
+[      ]*[a-f0-9]+:    0f 1f 80 00 00 00 00    nopl   0x0\(%rax\)
+
+Disassembly of section .text:
+
+0+80 <_start>:
+[      ]*[a-f0-9]+:    48 3b 05 a9 01 01 10    cmp    0x100101a9\(%rip\),%rax        # 10010230 <_DYNAMIC\+0xe0>
+[      ]*[a-f0-9]+:    ff 25 ab 01 01 10       jmpq   \*0x100101ab\(%rip\)        # 10010238 <_DYNAMIC\+0xe8>
+[      ]*[a-f0-9]+:    e8 ae ff ff ff          callq  40 <_start-0x40>
diff --git a/ld/testsuite/ld-x86-64/pr19636-2d.d b/ld/testsuite/ld-x86-64/pr19636-2d.d
new file mode 100644 (file)
index 0000000..ff25ec1
--- /dev/null
@@ -0,0 +1,25 @@
+#source: pr19636-2.s
+#as: --64 -mrelax-relocations=no
+#ld: -pie -m elf_x86_64 --no-dynamic-linker
+#objdump: -dw
+#notarget: x86_64-*-nacl*
+
+.*: +file format .*
+
+
+Disassembly of section .plt:
+
+0+120 <.plt>:
+[      ]*[a-f0-9]+:    ff 35 2a 01 20 00       pushq  0x20012a\(%rip\)        # 200250 <_GLOBAL_OFFSET_TABLE_\+0x8>
+[      ]*[a-f0-9]+:    ff 25 2c 01 20 00       jmpq   \*0x20012c\(%rip\)        # 200258 <_GLOBAL_OFFSET_TABLE_\+0x10>
+[      ]*[a-f0-9]+:    0f 1f 40 00             nopl   0x0\(%rax\)
+[      ]*[a-f0-9]+:    ff 25 2a 01 20 00       jmpq   \*0x20012a\(%rip\)        # 200260 <_GLOBAL_OFFSET_TABLE_\+0x18>
+[      ]*[a-f0-9]+:    68 00 00 00 00          pushq  \$0x0+
+[      ]*[a-f0-9]+:    e9 00 00 00 00          jmpq   [a-f0-9]+ <.*>
+
+Disassembly of section .text:
+
+0+140 <_start>:
+[      ]*[a-f0-9]+:    48 3b 05 f1 00 20 00    cmp    0x2000f1\(%rip\),%rax        # 200238 <_DYNAMIC\+0xe0>
+[      ]*[a-f0-9]+:    ff 25 f3 00 20 00       jmpq   \*0x2000f3\(%rip\)        # 200240 <_DYNAMIC\+0xe8>
+[      ]*[a-f0-9]+:    e8 de ff ff ff          callq  130 <_start-0x10>
diff --git a/ld/testsuite/ld-x86-64/pr19636-2e.d b/ld/testsuite/ld-x86-64/pr19636-2e.d
new file mode 100644 (file)
index 0000000..3689d75
--- /dev/null
@@ -0,0 +1,19 @@
+#source: pr19636-2.s
+#as: --64 -mrelax-relocations=no
+#ld: -shared -m elf_x86_64 --no-dynamic-linker
+#readelf : -r --wide --dyn-syms
+
+Relocation section '\.rela\.dyn' at offset [0x0-9a-f]+ contains 2 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_GLOB_DAT +0+ +func1 \+ 0
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_GLOB_DAT +0+ +func2 \+ 0
+
+Relocation section '\.rela\.plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_JUMP_SLOT +0+ +func3 \+ 0
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func[0-9]?
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr19636-2f.d b/ld/testsuite/ld-x86-64/pr19636-2f.d
new file mode 100644 (file)
index 0000000..605fa24
--- /dev/null
@@ -0,0 +1,19 @@
+#source: pr19636-2.s
+#as: --64 -mrelax-relocations=no
+#ld: -shared -Bsymbolic -m elf_x86_64 --no-dynamic-linker
+#readelf : -r --wide --dyn-syms
+
+Relocation section '\.rela\.dyn' at offset [0x0-9a-f]+ contains 2 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_GLOB_DAT +0+ +func1 \+ 0
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_GLOB_DAT +0+ +func2 \+ 0
+
+Relocation section '\.rela\.plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_JUMP_SLOT +0+ +func3 \+ 0
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func[0-9]?
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr19636-2g.d b/ld/testsuite/ld-x86-64/pr19636-2g.d
new file mode 100644 (file)
index 0000000..f4553d8
--- /dev/null
@@ -0,0 +1,13 @@
+#source: pr19636-2.s
+#as: --64 -mrelax-relocations=no
+#ld: -m elf_x86_64 --no-dynamic-linker
+#readelf : -r --wide -x .got -x .got.plt --dyn-syms
+
+There are no relocations in this file.
+
+Hex dump of section '.got':
+  0x[0-9a-f]+ [0 ]+\.+
+
+Hex dump of section '.got.plt':
+  0x[0-9a-f]+ [0 ]+\.+
+  0x[0-9a-f]+ [0 ]+\.+
diff --git a/ld/testsuite/ld-x86-64/pr19636-2h.d b/ld/testsuite/ld-x86-64/pr19636-2h.d
new file mode 100644 (file)
index 0000000..4353fbc
--- /dev/null
@@ -0,0 +1,20 @@
+#source: pr19636-2.s
+#as: --64 -mrelax-relocations=no
+#ld: -E -m elf_x86_64 --no-dynamic-linker
+#readelf : -r --wide -x .got -x .got.plt --dyn-syms
+
+There are no relocations in this file.
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +_start
+#...
+
+Hex dump of section '.got':
+  0x[0-9a-f]+ [0 ]+\.+
+
+Hex dump of section '.got.plt':
+  0x[0-9a-f]+ +[0-9a-f]+ +[0 ]+ .+
+  0x[0-9a-f]+ [0 ]+\.+
diff --git a/ld/testsuite/ld-x86-64/pr19636-2i.d b/ld/testsuite/ld-x86-64/pr19636-2i.d
new file mode 100644 (file)
index 0000000..7a4003a
--- /dev/null
@@ -0,0 +1,9 @@
+#source: pr19636-2.s
+#as: --64 -mrelax-relocations=no
+#ld: -E -m elf_x86_64 --no-dynamic-linker
+#readelf : --wide --dyn-syms
+
+#failif
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func[0-9]?
+#...
diff --git a/ld/testsuite/ld-x86-64/pr19636-3.s b/ld/testsuite/ld-x86-64/pr19636-3.s
new file mode 100644 (file)
index 0000000..6c981f5
--- /dev/null
@@ -0,0 +1,14 @@
+       .text
+       .type start,"function"
+       .global start
+start:
+       .type _start,"function"
+       .global _start
+_start:
+       .type __start,"function"
+       .global __start
+__start:
+       .type main,"function"
+       .global main
+main:
+       .long 0
diff --git a/ld/testsuite/ld-x86-64/pr19636-3a.d b/ld/testsuite/ld-x86-64/pr19636-3a.d
new file mode 100644 (file)
index 0000000..af01939
--- /dev/null
@@ -0,0 +1,8 @@
+#source: pr19636-3.s
+#as: --64
+#ld: -pie --defsym foobar=0x100 -m elf_x86_64
+#readelf : --dyn-syms --wide
+
+Symbol table '\.dynsym' contains 1 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
diff --git a/ld/testsuite/ld-x86-64/pr19636-3b.d b/ld/testsuite/ld-x86-64/pr19636-3b.d
new file mode 100644 (file)
index 0000000..be8c4f6
--- /dev/null
@@ -0,0 +1,10 @@
+#source: pr19636-3.s
+#as: --64
+#ld: -pie -E --defsym foobar=0x100 -m elf_x86_64
+#readelf : --dyn-syms --wide
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +0+100 +0 +NOTYPE +GLOBAL +DEFAULT +ABS +foobar
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr19636-3c.d b/ld/testsuite/ld-x86-64/pr19636-3c.d
new file mode 100644 (file)
index 0000000..02b6464
--- /dev/null
@@ -0,0 +1,10 @@
+#source: pr19636-3.s
+#as: --64
+#ld: -shared -Bsymbolic --defsym foobar=0x100 -m elf_x86_64
+#readelf : --dyn-syms --wide
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +0+100 +0 +NOTYPE +GLOBAL +DEFAULT +ABS +foobar
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr19636-3d.d b/ld/testsuite/ld-x86-64/pr19636-3d.d
new file mode 100644 (file)
index 0000000..3d9a6d7
--- /dev/null
@@ -0,0 +1,10 @@
+#source: pr19636-3.s
+#as: --64
+#ld: -E --defsym foobar=0x100 -m elf_x86_64
+#readelf : --dyn-syms --wide
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +0+100 +0 +NOTYPE +GLOBAL +DEFAULT +ABS +foobar
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr19704.out b/ld/testsuite/ld-x86-64/pr19704.out
new file mode 100644 (file)
index 0000000..3506f46
--- /dev/null
@@ -0,0 +1 @@
+Weak undefined
diff --git a/ld/testsuite/ld-x86-64/pr19704a.c b/ld/testsuite/ld-x86-64/pr19704a.c
new file mode 100644 (file)
index 0000000..aa52e00
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdio.h>
+
+extern int __attribute__ ((weak)) fun (void);
+
+int
+main (void)
+{
+  if (&fun != 0)
+    fun ();
+  else
+    printf ("Weak undefined\n");
+  return 0;
+}
diff --git a/ld/testsuite/ld-x86-64/pr19704b.c b/ld/testsuite/ld-x86-64/pr19704b.c
new file mode 100644 (file)
index 0000000..1d688e1
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+void
+fun (void)
+{
+  printf ("Weak defined\n");
+}
index 7248377c9b66cb7ba1230bc0231e245ac0d261d6..214b08b05fde778f3acb730584aa16d34890562f 100644 (file)
@@ -355,6 +355,82 @@ run_dump_test "pr19162"
 run_dump_test "pr19175"
 run_dump_test "pr18591"
 run_dump_test "pr19615"
+run_dump_test "pr19636-1a"
+run_dump_test "pr19636-1b"
+run_dump_test "pr19636-1c"
+run_dump_test "pr19636-1d"
+run_dump_test "pr19636-1e"
+run_dump_test "pr19636-1f"
+run_dump_test "pr19636-1g"
+run_dump_test "pr19636-2a"
+run_dump_test "pr19636-2b"
+run_dump_test "pr19636-2c"
+run_dump_test "pr19636-2d"
+run_dump_test "pr19636-2d-nacl"
+run_dump_test "pr19636-2e"
+run_dump_test "pr19636-2f"
+run_dump_test "pr19636-2g"
+run_dump_test "pr19636-2h"
+run_dump_test "pr19636-2i"
+run_dump_test "pr19636-3a"
+run_dump_test "pr19636-3b"
+run_dump_test "pr19636-3c"
+
+proc undefined_weak {cflags ldflags} {
+    set testname "Undefined weak symbol"
+    if { ![ string match "" $cflags$ldflags] } {
+       set testname "$testname ($cflags $ldflags)"
+    }
+
+    if { [ regexp "\-fPIE" $cflags]
+        && ![ regexp "\-z nodynamic-undefined-weak" $ldflags] } {
+       set weak_symbol "Weak defined"
+    } else {
+       set weak_symbol "Weak undefined"
+    }
+
+    run_cc_link_tests [list \
+       [list \
+           "Build libpr19704a.so" \
+           "-shared -Wl,-soname,libpr19704.so" \
+           "" \
+           { dummy.s } \
+           {} \
+           "libpr19704a.so" \
+       ] \
+       [list \
+           "Build libpr19704b.so" \
+           "-shared -Wl,-soname,libpr19704.so" \
+           "-fPIC" \
+           { pr19704b.c } \
+           {} \
+           "libpr19704b.so" \
+       ] \
+    ]
+
+    exec cp tmpdir/libpr19704a.so tmpdir/libpr19704.so
+
+    run_ld_link_exec_tests [] [list \
+       [list \
+           "Run pr19704" \
+           "$ldflags tmpdir/libpr19704.so -R tmpdir" \
+           "" \
+           { pr19704a.c } \
+           "pr19704" \
+           "pr19704.out" \
+           "$cflags" \
+       ] \
+    ]
+
+    exec cp tmpdir/libpr19704b.so tmpdir/libpr19704.so
+
+    set exec_output [run_host_cmd tmpdir/pr19704 ""]
+    if {![string match $weak_symbol $exec_output]} {
+       fail $testname
+    } else {
+       pass $testname
+    }
+}
 
 # Add $PLT_CFLAGS if PLT is expected.
 global PLT_CFLAGS
@@ -686,6 +762,12 @@ if { [isnative] && [which $CC] != 0 } {
            ] \
        ]
     }
+
+    undefined_weak "" ""
+    undefined_weak "-fPIE" ""
+    undefined_weak "-fPIE" "-pie"
+    undefined_weak "-fPIE" "-z nodynamic-undefined-weak"
+    undefined_weak "-fPIE" "-pie -z nodynamic-undefined-weak"
 }
 
 if { ![istarget "x86_64-*-linux*"]} {