In my shared library I have to do certain initialization at the load time. If I define the function with the GCC attribute __attribute__ ((constructor))
it doesn't work, i.e. it doesn't get called when the program linking my shared library is loaded.
If I change the function name to _init()
, it works. Apparently the usage of _init()
and _fini()
functions are not recommended now.
Any idea why __attribute__ ((constructor))
wouldn't work? This is with Linux 2.6.9, gcc
version 3.4.6
Edit:
For example, let's say the library code is this the following:
#include <stdio.h>
int smlib_count;
void __attribute__ ((constructor)) setup(void) {
smlib_count = 100;
printf("smlib_count starting at %d\n", smlib_count);
}
void smlib_count_incr() {
smlib_count++;
smlib_count++;
}
int smlib_count_get() {
return smlib_count;
}
For building the .so I do the following:
gcc -fPIC -c smlib.c
ld -shared -soname libsmlib.so.1 -o libsmlib.so.1.0 -lc smlib.o
ldconfig -v -n .
ln -sf libsmlib.so.1 libsmlib.so
Since the .so is not in one of the standard locations I update the LD_LIBRARY_PATH
and link the .so from a another program. The constructor doesn't get called. If I change it to _init()
, it works.
From this link :
"Shared libraries must not be compiled with the gcc arguments -nostartfiles'' or-nostdlib''. If those arguments are used, the constructor/destructor routines will not be executed (unless special measures are taken)."
gcc/ld doesn't set the DT_INIT bit in the elf header when -nostdlib is used . You can check objdump -p and look for the section INIT in both cases. In attribute ((constructor)) case you wont find that INIT section . But for __init case you will find INIT section in the shared library.
Okay, so I've taken a look at this, and it looks like what's happening is that your intermediate
gcc
step (using-c
) is causing the issue. Here's my interpretation of what I'm seeing.When you compile as a
.o
withsetup()
,gcc
just treats it as a normal function (since you're not compiling as a.so
, so it doesn't care). Then,ld
doesn't see any_init()
or anything like aDT_INIT
in the ELF's dynamic section, and assumes there's no constructors.When you compile as a
.o
with_init()
,gcc
also treats it as a normal function. In fact, it looks to me like the object files are identical except for the names of the functions themselves! So once again,ld
looks at the.o
file, but this time sees a_init()
function, which it knows it's looking for, and decides it's a constructor, and correspondingly creates aDT_INIT
entry in the new.so
.Finally, if you do the compilation and linking in one step, like this:
Then what happens is that
gcc
sees and understands the__attribute__ ((constructor))
in the context of creating a shared object, and creates aDT_INIT
entry accordingly.Short version: use
gcc
to compile and link in one step. You can use-Wl
(see the man page) for passing in extra options like-soname
if required, like-Wl,-soname,libsmlib.so.1
.