Bug 19704 - Missing dynamic relocation against undefined weak symbol
Summary: Missing dynamic relocation against undefined weak symbol
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.27
: P2 normal
Target Milestone: 2.27
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-02-22 17:49 UTC by H.J. Lu
Modified: 2017-04-10 11:48 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Last reconfirmed:
Project(s) to access:
ssh public key:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description H.J. Lu 2016-02-22 17:49:30 UTC
Currently when building executable, undefined weak symbol is resolved
differently, depending on if the relocatable input is compiled with PIC or
not:

hjl@gnu-tools-1 weak-1]$ cat x.c
extern void __attribute__ ((weak)) fun (void);
int main (void)
{
  if (&fun != 0)
    fun ();
  return 0;
}
[hjl@gnu-tools-1 weak-1]$ make
gcc -B./ -O2 -o x x.c
gcc -B./ -O2 -o y x.c -fPIC
readelf -r x

Relocation section '.rela.dyn' at offset 0x328 contains 1 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000600870  000200000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0

Relocation section '.rela.plt' at offset 0x340 contains 1 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000600890  000100000007 R_X86_64_JUMP_SLO 0000000000000000
__libc_start_main@GLIBC_2.2.5 + 0

There is no dynamic relocation against fun, whose value is
resolved to zero at link-time.

readelf -r y

Relocation section '.rela.dyn' at offset 0x348 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
0000006008a0  000100000006 R_X86_64_GLOB_DAT 0000000000000000 fun + 0
0000006008a8  000300000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0

Relocation section '.rela.plt' at offset 0x378 contains 1 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
0000006008c8  000200000007 R_X86_64_JUMP_SLO 0000000000000000
__libc_start_main@GLIBC_2.2.5 + 0
[hjl@gnu-tools-1 weak-1]$

There is dynamic relocation against fun, whose value is resolved
at runt-time. We should make it consistent, regardless if input
relocatable file is compiled with PIC or not.  GNU ABI should be
extended to:

When creating executable, if dynamic relocation is available at
run-time, the link editor should generate dynamic relocations
against unresolved weak symbols so that their values will be
resolved at run-time.
Comment 1 H.J. Lu 2016-02-25 17:09:29 UTC
We have to resolve R_X86_64_32/R_X86_64_PC32 relocations against undefined
weak symbols to zero.  Otherwise, we will get run-time relocation overflow
for dynamic R_X86_64_32/R_X86_64_PC32 relocations.
Comment 2 Sourceware Commits 2016-02-26 12:56:50 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=aec6b87e0b66d707ead62ca40d220ee78b4cf5a5

commit aec6b87e0b66d707ead62ca40d220ee78b4cf5a5
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Feb 26 04:16:15 2016 -0800

    [x86] Resolve non-PIC undefweak symbols in executable
    
    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.
Comment 3 H.J. Lu 2016-02-26 13:15:31 UTC
Fixed.
Comment 4 Sourceware Commits 2017-04-10 11:48:03 UTC
The master branch has been updated by Nick Clifton <nickc@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=bb1dd176fb6f38ae3cc30dc61ce55a7fbf9d0d7b

commit bb1dd176fb6f38ae3cc30dc61ce55a7fbf9d0d7b
Author: Qing Zhao <qing.zhao@oracle.com>
Date:   Mon Apr 10 12:46:30 2017 +0100

    Port the bug fix for PR 19704 (Missing dynamic relocation against undefined weak symbol) to the SPARC architecture.
    
           * elf32-sparc.c (elf_backend_fixup_symbol): New.
            * elf64-sparc.c (elf_backend_fixup_symbol): New.
            * elfxx-sparc.c (UNDEFINED_WEAK_RESOLVED_TO_ZERO): New.
            (_bfd_sparc_elf_link_hash_entry): Add has_got_reloc and
            has_non_got_reloc.
            (link_hash_newfunc): Initialize has_got_reloc and
    	has_non_got_reloc.
            (_bfd_sparc_elf_size_dynamic_sections): Set interp to .interp
            section.
            (_bfd_sparc_elf_copy_indirect_symbol): Copy has_got_reloc and
            has_non_got_reloc.
            (_bfd_sparc_elf_check_relocs): Set has_got_reloc and
            has_non_got_reloc.
            (_bfd_sparc_elf_fixup_symbol): New function.
            (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.
            (_bfd_sparc_elf_relocate_section): Don't generate dynamic
            relocations against resolved undefined weak symbols in PIE
            (_bfd_sparc_elf_finish_dynamic_symbol): Keep PLT/GOT entries
            without ynamic PLT/GOT relocations for resolved undefined weak
            symbols.
            Don't generate dynamic relocation against resolved undefined
            weak symbol in executable.
            (pie_finish_undefweak_symbol): New function.
            (_bfd_sparc_elf_finish_dynamic_sections): Call
            pie_finish_undefweak_symbol on all symbols in PIE.
            * elfxx-sparc.h (_bfd_sparc_elf_link_hash_table): Add interp.
            (_bfd_sparc_elf_fixup_symbol): New function.