Alex
Alex

Reputation: 961

Why is __attribute__((constructor)) in my shared library not working?

I have this code in ctor.c:

#include<stdio.h>

static void __attribute__((constructor)) ctor() {
        printf("HAHA");
}

I compile it with:

clang -o shared.so -fPIC ctor.c -shared

then I run:

LD_PRELOAD=shared.so echo Hallo

it prints

Hallo

I was expecting to see:

HAHAHallo

Why is this not working?

Some info about the binary:

> objdump -s -j .init_array shared.so

shared.so:     file format elf64-x86-64

Contents of section .init_array:
 200798 b0060000 00000000 e0060000 00000000  ................

> nm shared.so
00000000002007b8 d _DYNAMIC
00000000002009b0 d _GLOBAL_OFFSET_TABLE_
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
0000000000000790 r __FRAME_END__
00000000002007b0 d __JCR_END__
00000000002007b0 d __JCR_LIST__
00000000002009e8 d __TMC_END__
00000000002009e8 B __bss_start
                 w __cxa_finalize@@GLIBC_2.2.5
0000000000000670 t __do_global_dtors_aux
00000000002007a8 t __do_global_dtors_aux_fini_array_entry
00000000002009e0 d __dso_handle
0000000000200798 t __frame_dummy_init_array_entry
                 w __gmon_start__
00000000002009e8 D _edata
00000000002009f0 B _end
0000000000000700 T _fini
0000000000000578 T _init
00000000002009e8 b completed.6661
00000000000006e0 t ctor
00000000000005e0 t deregister_tm_clones
00000000000006b0 t frame_dummy
                 U printf@@GLIBC_2.2.5
0000000000000620 t register_tm_clones

This indicates:

(a) the ctor function is present. It is not removed by the linker, as for some people with similar problems.

(b) The .init_array looks okay to me. There are two entries (instead of one), and they point to frame_dummy and ctor. (I used this answer: https://reverseengineering.stackexchange.com/a/12793)

(c) shared library constructor not working solved the problem by compiling and linking in one step, which I am already doing

PS: It also does not work when I compile with gcc.

Upvotes: 2

Views: 2795

Answers (2)

Alex
Alex

Reputation: 961

There were two mistakes:

(a) LD_PRELOAD needs an absolute path.

(b) "echo" is a shell-builtin, so no binary will be started and thereby nothing will be preloaded. With my own "hello world" program, it works.

Upvotes: 3

Cosinus
Cosinus

Reputation: 659

I had a similar problem with a c++-constructor

struct Foo {
    Foo() {
        printf("foo");
    }
} foo;

This should print "foo" before the main() is called, but it didn't. But I had very similar stuff in my project that worked well.

I have found out that the constructor isn't called if there is nothing else in the source-file that is called from outside.

Try calling a dummy-function from outside.

Upvotes: 1

Related Questions