Bug 19636

Summary: -pie changes program behavior and generate unnecessary dynamic symbols.
Product: binutils Reporter: H.J. Lu <hjl.tools>
Component: ldAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal    
Priority: P2    
Version: 2.27   
Target Milestone: 2.27   
Host: Target:
Build: Last reconfirmed:
Bug Depends on:    
Bug Blocks: 22269    

Description H.J. Lu 2016-02-14 04:01:35 UTC
[hjl@gnu-tools-1 pie-1]$ cat x.s
	.text
	.globl _start
_start:
	.byte 0
	.section	.data.rel.ro.local,"aw",%progbits
	.weak func
	.dc.a func
[hjl@gnu-tools-1 pie-1]$ make
as   -o x.o x.s
./ld -pie -o x x.o
./ld -o y x.o
readelf -r --dyn-syms x

Relocation section '.rela.dyn' at offset 0x248 contains 1 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000200268  000300000001 R_X86_64_64       0000000000000000 func + 0

Symbol table '.dynsym' contains 6 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000260     0 SECTION LOCAL  DEFAULT    6 
     2: 0000000000200370     0 NOTYPE  GLOBAL DEFAULT    9 __bss_start
     3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND func
     4: 0000000000200370     0 NOTYPE  GLOBAL DEFAULT    9 _edata
     5: 0000000000200370     0 NOTYPE  GLOBAL DEFAULT    9 _end
readelf -r --dyn-syms y

There are no relocations in this file.
[hjl@gnu-tools-1 pie-1]$ 

-pie generates a dynamic relocation for func, which changes program
behavior and makes weak symbol a run-time decision instead of link-time.
Also

     2: 0000000000200370     0 NOTYPE  GLOBAL DEFAULT    9 __bss_start
     4: 0000000000200370     0 NOTYPE  GLOBAL DEFAULT    9 _edata
     5: 0000000000200370     0 NOTYPE  GLOBAL DEFAULT    9 _end

are odd since there are no dynamic relocations for those symbols.

With gold, I got

[hjl@gnu-tools-1 pie-1]$ make LD=ld.gold
as   -o x.o x.s
ld.gold -pie -o x x.o
ld.gold -o y x.o
readelf -r --dyn-syms x

There are no relocations in this file.

Symbol table '.dynsym' contains 1 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
readelf -r --dyn-syms y

There are no relocations in this file.
[hjl@gnu-tools-1 pie-1]$
Comment 1 Sourceware Commits 2016-02-26 12:56:49 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 2 H.J. Lu 2016-02-26 13:17:15 UTC
Fixed.
Comment 3 Sourceware Commits 2017-10-11 20:37:18 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=853ee16fcdf7e60f297b3456353b3a69f4822bec

commit 853ee16fcdf7e60f297b3456353b3a69f4822bec
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Wed Oct 11 13:32:20 2017 -0700

    x86: Run PR ld/19636 tests with -z dynamic-undefined-weak
    
    "-z dynamic-undefined-weak" makes undefined weak symbols dynamic, but
    undefined weak symbols are still resolved to 0 at link-time if there
    is no dynamic linker in executable.
    
    	* testsuite/ld-i386/i386.exp: Run pr19636-1j, pr19636-1k,
    	pr19636-1l, pr19636-3h and pr19636-3i.
    	* testsuite/ld-i386/pr19636-1j.d: New file.
    	* testsuite/ld-i386/pr19636-1k.d: Likewise.
    	* testsuite/ld-i386/pr19636-1l.d: Likewise.
    	* testsuite/ld-i386/pr19636-3h.d: Likewise.
    	* testsuite/ld-i386/pr19636-3i.d: Likewise.
    	* testsuite/ld-x86-64/pr19636-1h.d: Likewise.
    	* testsuite/ld-x86-64/pr19636-1i.d: Likewise.
    	* testsuite/ld-x86-64/pr19636-1j.d: Likewise.
    	* testsuite/ld-x86-64/pr19636-2j.d: Likewise.
    	* testsuite/ld-x86-64/pr19636-2k.d: Likewise.
    	* testsuite/ld-x86-64/pr19636-2l.d: Likewise.
    	* testsuite/ld-x86-64/pr19636-2m.d: Likewise.
    	* testsuite/ld-x86-64/x86-64.exp: Run pr19636-1h, pr19636-1i,
    	pr19636-1j, pr19636-2j, pr19636-2k, pr19636-2l and pr19636-2m.