Search code examples
c++cgccobjdump

__do_global_ctors_aux not shown in objdump


Consider the following code:

#include <stdio.h> 

void __attribute__ ((constructor)) a_constructor() 
{ 
    printf("%s\n", __func__); 
}

void __attribute__ ((constructor)) b_constructor() 
{ 
    printf("%s\n", __func__); 
} 

int main() 
{ 
    printf("%s\n",__func__); 
}

I compile the above code as : gcc -ggdb prog2.c -o prog2. The code runs as expected.

a_constructor
b_constructor
main

But when I see its dump using objdump -d prog2 > f. There is neither a call to __do_global_ctors_aux anywhere in _init or anywhere else, nor a definition of __do_global_ctors_aux. So, how do the constructors get called? Where is the definition of __do_global_ctors_aux? Is this some optimization?

I also tried compiling it with no optimization like this: gcc -ggdb -O0 prog2.c -o prog2. Please Clarify. The compilation is being done on 32 bit linux machine.

EDIT

My output from gdb bt is:

Breakpoint 1, a_constructor () at prog2.c:5
5       printf("%s\n", __func__); 
(gdb) bt
#0  a_constructor () at prog2.c:5
#1  0x080484b2 in __libc_csu_init ()
#2  0xb7e31a1a in __libc_start_main (main=0x8048445 <main>, argc=1, argv=0xbffff014, init=0x8048460 <__libc_csu_init>, 
fini=0x80484d0 <__libc_csu_fini>, rtld_fini=0xb7fed180 <_dl_fini>, stack_end=0xbffff00c) at libc-start.c:246
#3  0x08048341 in _start ()

Solution

  • So, how do the constructors get called?

    If you look at the disassembly produced with gcc -g -O0 -S -fverbose-asm prog2.c -o prog2.s, there is the following:

        .text
    .Ltext0:
        .globl  a_constructor
        .type   a_constructor, @function
    a_constructor:
    .LFB0:
        .file 1 "test.c"
        .loc 1 4 0
        .cfi_startproc
        pushq   %rbp    #
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp  #,
        .cfi_def_cfa_register 6
        .loc 1 5 0
        movl    $__func__.2199, %edi    #,
        call    puts    #
        .loc 1 6 0
        popq    %rbp    #
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
    .LFE0:
        .size   a_constructor, .-a_constructor
        .section    .init_array,"aw"
        .align 8
        .quad   a_constructor
    

    In the above, function a_constructor is put into .text section. And a pointer to the function is also appended to .init_array section. Before calling main glibc iterates over this array and invokes all constructor functions found there.