Explicit loader invocation "ld.so ./a.out" on a PIE binary calls global ctors twice. Confirmed with current trunk (e646a161cef3069fe1a6c92b750a87350630c62d). Test: #include <assert.h> int g; void init_g () __attribute__((constructor)); void init_g () { assert (g == 0); g = 1; } int main () { return 0; } gcc -g t.c -fPIE -pie ./a.out && echo ok ok /tmp/build/elf/ld.so --library-path /tmp/build ./a.out a.out: t.c:10: init_g: Assertion `g == 0' failed. Aborted (core dumped) The first call to init_g is here: Breakpoint 1, init_g () at t.c:10 10 assert (g == 0); (gdb) bt #0 init_g () at t.c:10 #1 0x00005555555631ca in call_init (l=<optimized out>, argc=argc@entry=1, argv=argv@entry=0x7fffffffe370, env=env@entry=0x7fffffffe380) at dl-init.c:78 #2 0x00005555555632db in call_init (env=0x7fffffffe380, argv=0x7fffffffe370, argc=1, l=<optimized out>) at dl-init.c:36 #3 _dl_init (main_map=0x555555777190, argc=1, argv=0x7fffffffe370, env=0x7fffffffe380) at dl-init.c:126 #4 0x0000555555554dba in _dl_start_user () from /tmp/build/elf/ld.so The second: (gdb) bt #0 init_g () at t.c:10 #1 0x00007ffff7dfc82d in __libc_csu_init () #2 0x00007ffff7a6804f in __libc_start_main (main=0x7ffff7dfc7bb <main>, argc=1, argv=0x7fffffffe370, init=0x7ffff7dfc7d0 <__libc_csu_init>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe368) at libc-start.c:244 #3 0x00007ffff7dfc6a9 in _start ()
Patch: http://cygwin.com/ml/libc-alpha/2014-01/msg00240.html
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "GNU C Library master sources". The branch, master has been updated via 798212a01311491d5e14fcda687460b75f8ca286 (commit) from abe6d90cc8c1c212dab7cde4468f9ed895d6ba86 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=798212a01311491d5e14fcda687460b75f8ca286 commit 798212a01311491d5e14fcda687460b75f8ca286 Author: Paul Pluzhnikov <ppluzhnikov@google.com> Date: Wed Mar 12 15:58:39 2014 -0700 2014-03-12 Paul Pluzhnikov <ppluzhnikov@google.com> [BZ #16381] * elf/Makefile (tests): Add tst-pie2. (tests-pie): Add tst-pie2. * elf/tst-pie2.c: New file. * elf/dl-load.c (_dl_map_object_from_fd): Assert correct l_type for ET_EXEC. * elf/rtld.c (map_doit): Load executable as lt_executable. (dl_main): Likewise. ----------------------------------------------------------------------- Summary of changes: ChangeLog | 12 ++++++++++++ NEWS | 6 +++--- elf/Makefile | 5 +++-- elf/dl-load.c | 4 ++-- elf/rtld.c | 5 +++-- 5 files changed, 23 insertions(+), 9 deletions(-)
Should be fixed now.
*** Bug 17769 has been marked as a duplicate of this bug. ***
I appreciate that this issue is more than ten years old, but for the benefit of anyone repeating the archaeological dig that I just did: I think that the fix for this issue also fixed another issue at the same time - explicit loader invocation "ld.so ./a.out" on a PIE binary didn't handle copy relocations properly. Test for that: #include <stdio.h> int main(int argc, const char** argv) { fputs("Hello World!\n", stdout); } gcc -g t.c -fPIE -pie With glibc 2.19 (i.e. before this fix): $ ld-linux-x86-64.so.2 ./a.out Segmentation fault (core dumped) Versus correct behaviour with this fix: $ ld-linux-x86-64.so.2 ./a.out Hello World!