From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28874 invoked by alias); 20 Jul 2012 19:12:29 -0000 Received: (qmail 28866 invoked by uid 22791); 20 Jul 2012 19:12:28 -0000 X-SWARE-Spam-Status: No, hits=-3.0 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_00 X-Spam-Check-By: sourceware.org Received: from localhost (HELO sourceware.org) (127.0.0.1) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 20 Jul 2012 19:12:15 +0000 From: "luto at mit dot edu" To: glibc-bugs@sources.redhat.com Subject: [Bug dynamic-link/14379] New: shared object constructors are called in the wrong order Date: Fri, 20 Jul 2012 19:12:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: glibc X-Bugzilla-Component: dynamic-link X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: luto at mit dot edu X-Bugzilla-Status: NEW X-Bugzilla-Priority: P2 X-Bugzilla-Assigned-To: unassigned at sourceware dot org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Changed-Fields: Message-ID: X-Bugzilla-URL: http://sourceware.org/bugzilla/ Auto-Submitted: auto-generated Content-Type: text/plain; charset="UTF-8" MIME-Version: 1.0 Mailing-List: contact glibc-bugs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: glibc-bugs-owner@sourceware.org X-SW-Source: 2012-07/txt/msg00171.txt.bz2 http://sourceware.org/bugzilla/show_bug.cgi?id=14379 Bug #: 14379 Summary: shared object constructors are called in the wrong order Product: glibc Version: unspecified Status: NEW Severity: normal Priority: P2 Component: dynamic-link AssignedTo: unassigned@sourceware.org ReportedBy: luto@mit.edu Classification: Unclassified [This is not clearly a bug in the strictest sense, as the ELF spec, AFAICT, has nothing useful to say. It's rather unfortunate behavior, though, that makes writing efficient and reliable malloc replacements very difficult, for example.] glibc's dynamic elf loader makes some effort to initialize an SO's DT_NEEDED dependencies before initializing the SO that depended on them. This is nice. Unfortunately, for sibling dependencies, it appears that the first library is searched first for symbols (as required by the ELF spec) but the *last* library is initialized first. This means that, if an earlier library overrides a symbol called by the constructor of a later library, then the earlier library is called before it is initialized. This is quite unfortunate for malloc replacements. I have one that is intended to be used with LD_PRELOAD, which causes its symbols to be searched first (as desired) but causes it to be constructed last (which is bad). Fixing this would be more complicated than just reversing the order of initialization: it would still be good for deeper dependencies to be initialized first. As a demonstration, create lib.c and bin.c, as below. Then do: $ for name in lib1 lib2 preload_lib; do gcc -DLIBNAME="\"$name\"" -fPIC -shared -o ${name}.so lib.c -Wl,--no-undefined; done $ gcc -Wl,--no-as-needed -o bin_12 bin.c lib1.so lib2.so -Wl,-rpath -Wl,. $ gcc -Wl,--no-as-needed -o bin_1 bin.c lib1.so -Wl,-rpath -Wl,. $ ./bin_12 lib2: ctor called. calling the_func lib1: the_func called lib1: NOT INITED! lib1: ctor called. calling the_func lib1: the_func called main: calling the_func lib1: the_func called $ LD_PRELOAD=preload_lib.so ./bin_1 lib1: ctor called. calling the_func preload_lib: the_func called preload_lib: NOT INITED! preload_lib: ctor called. calling the_func preload_lib: the_func called main: calling the_func preload_lib: the_func called -- start of lib.c -- #include #define PRINT(x) do { static const char __s[] = x; write(1, __s, sizeof(__s)-1); } while(0) static int inited = 0; void the_func(void) { PRINT(" " LIBNAME ": the_func called\n"); if (!inited) PRINT(" " LIBNAME ": NOT INITED!\n"); } __attribute__((constructor)) static void ctor(void) { inited = 1; PRINT(LIBNAME ": ctor called. calling the_func\n"); the_func(); } -- end of lib.c -- -- start of bin.c -- #include #define PRINT(x) do { static const char __s[] = x; write(1, __s, sizeof(__s)-1); } while(0) extern void the_func(void); int main() { PRINT("main: calling the_func\n"); the_func(); return 0; } -- end of bin.c -- -- Configure bugmail: http://sourceware.org/bugzilla/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are on the CC list for the bug.