Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine static initialization order after compilation?

In C++, I know that the compiler can choose to initialize static objects in any order that it chooses (subject to a few constraints), and that in general you cannot choose or determine the static initialization order.

However, once a program has been compiled, the compiler has to have made a decision about what order to initialize these objects in. Is there any way to determine, from a compiled program with debugging symbols, in what order static constructors will be called?

The context is this: I have a sizeable program that is suddenly segfaulting before main() when it is built under a new toolchain. Either this is a static initialization order problem, or it is something wrong with one of the libraries that it is loading. However, when I debug with gdb, the crash location is simply reported as a raw address without any symbolic information or backtrace. I would like to decide which of these two problems it is by placing a breakpoint at the constructor of the very first statically-initialized object, but I don't know how to tell which object that is.

like image 773
Tyler McHenry Avatar asked Aug 03 '09 20:08

Tyler McHenry


1 Answers

In G++ on Linux, static constructor and destructor ordering is determined by function pointers in the .ctors and .dtors sections. Note that with sufficient debugging available, you can actually get a backtrace:

(gdb) bt
#0  0xb7fe3402 in __kernel_vsyscall ()
#1  0xb7d59680 in *__GI_raise (sig=6)
    at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2  0xb7d5cd68 in *__GI_abort () at abort.c:88
#3  0x08048477 in foo::foo() ()
#4  0x0804844e in __static_initialization_and_destruction_0(int, int) ()
#5  0x0804846a in global constructors keyed to foo_inst ()
#6  0x0804850d in __do_global_ctors_aux ()
#7  0x08048318 in _init ()
#8  0x080484a9 in __libc_csu_init ()
#9  0xb7d4470c in __libc_start_main (main=0x8048414 <main>, argc=1,
    ubp_av=0xbfffcbc4, init=0x8048490 <__libc_csu_init>,
    fini=0x8048480 <__libc_csu_fini>, rtld_fini=0xb7ff2820 <_dl_fini>,
    stack_end=0xbfffcbbc) at libc-start.c:181
#10 0x08048381 in _start () at ../sysdeps/i386/elf/start.S:119

This is with debugging symbols for libc and libstdc++ installed. As you can see, the crash here occured in the foo::foo() constructor for the static object foo_inst.

If you want to break into the initialization process, you could then set a breakpoint on __do_global_ctors_aux and step through its disassembly, I suppose. Or just wait for it to crash to get the backtrace like the above.

like image 164
bdonlan Avatar answered Oct 05 '22 16:10

bdonlan