2

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.

Alex
  • 871
  • 7
  • 23
  • See [How exactly does __attribute__((constructor)) work?](https://stackoverflow.com/questions/2053029/how-exactly-does-attribute-constructor-work) – David C. Rankin Jan 12 '18 at 15:52

2 Answers2

3

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.

Alex
  • 871
  • 7
  • 23
1

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.

Cosinus
  • 534
  • 4
  • 10
  • If I use a second source file with a main function and link to an executable, it works. Linking as a shared library does not work. – Alex Jan 12 '18 at 10:24
  • I think your problem was that the linker does not access the object file and thereby misses the constructor if nothing in the file is used. For me, nm shows that the constructor is in the binary. Even the .init_array seems to be populated correctly. – Alex Jan 12 '18 at 10:26