Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LD_PRELOAD compile .so using gcc or g++

I have a wrapper for a socket API which I preload before my application using LD_PRELOAD. However when I compile my .so wrapper library using g++ it doesn't work, i.e., glibc version of the socket implementation is picketd instead.

This is how I compile the wrapper .so library (one of these):

gcc -Wall -fPIC -shared socket_hooks.c -o socket_hooks.so
or
g++ -Wall -fPIC -shared socket_hooks.c -o socket_hooks.so

This is how I compile and run my udp client:

g++ -Wall udp_client.cpp  -o udp_client
LD_PRELOAD=./socket_hooks.so ./udp_client

Now when I enable debug (export LD_DEBUG=all) and run with .so compiled using gcc (working version) compiled example I see:

 17278: symbol=socket;  lookup in file=./udp_client [0]
 17278: symbol=socket;  lookup in file=./socket_hooks.so [0]
 17278: binding file ./udp_client [0] to ./socket_hooks.so [0]: normal symbol `socket' [GLIBC_2.2.5]

When I compile .so using g++ I see the following:

 17285: symbol=socket;  lookup in file=./udp_client [0]
 17285: symbol=socket;  lookup in file=./socket_hooks.so [0]
 17285: symbol=socket;  lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
 17285: binding file ./udp_client [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `socket' [GLIBC_2.2.5]

In both cases "socket" symbol is found, but in the latter case it is not picked up, but libc is used instead.

Could you explain what is happening here?

like image 207
kirbo Avatar asked Jan 17 '26 13:01

kirbo


1 Answers

When you compile your module with C++ compiler, your symbols are name mangled to support function overloading, for example socket may be transformed to _Z10socketiii. That's why runtime loader doesn't find it - it's looking for socket, not _Z10socketiii.

In order to disable name mangling, you have to declare your functions with C linkage using extern "C", probably with conjunction with __cplusplus macro, in order to stay compatible with C compilers:

#ifdef __cplusplus
extern "C" {
#endif

int socket(int domain, int type, int protocol);

#ifdef __cplusplus
}
#endif

Alternatively, set linkage on per-symbol basis:

#ifdef __cplusplus
#define DONT_MANGLE_ME extern "C"
#else
#define DONT_MANGLE_ME
#endif

DONT_MANGLE_ME int socket(int domain, int type, int protocol);
like image 76
el.pescado - нет войне Avatar answered Jan 21 '26 02:01

el.pescado - нет войне