2016-06-17 4 views
1

У меня есть оболочка для API сокетов, которую я предварительно загружаю перед своим приложением, используя LD_PRELOAD. Однако, когда я скомпилирую мою библиотеку-оболочку .so с помощью g ++, она не работает, то есть glibc-версия реализации сокета вместо этого пикет.LD_PRELOAD компилировать .so использовать gcc или g ++

Это, как я скомпилировать обертку .so библиотеки (один из них):

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

Это, как я скомпилировать и запустить мой UdP клиента:

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

Теперь, когда я включаю отладки (экспорт LD_DEBUG = все) и работать с .so скомпилирован с использованием GCC (рабочая версия) скомпилированный примера я вижу:

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] 

Когда я компилирую .so используя г ++ я вижу следующее:

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] 

В обоих случаях символ «Гнездо» найден, но в последнем случае он не поднял, но Libc используется вместо.

Не могли бы вы объяснить, что здесь происходит?

+1

Показать 'objdump -T socket_hooks.so' или' nm -D socket_hooks.so'. Я думаю, что имена функций искажены на C++, поэтому вам нужно объявить свои функции как 'extern 'C". –

+0

Спасибо, это была именно проблема! – kirbo

ответ

1

При компиляции вашего модуля с помощью компилятора C++ ваши символы называются искаженными для поддержки перегрузки функций, например socket могут быть преобразованы в _Z10socketiii. Вот почему runtime loader его не находит - он ищет socket, а не _Z10socketiii.

Для того, чтобы отключить имя коверкая, вы должны объявить свои функции с C связи с использованием extern "C", вероятно, с сочетании с __cplusplus макросъемки, чтобы остаться совместимым с компиляторами C:

#ifdef __cplusplus 
extern "C" { 
#endif 

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

#ifdef __cplusplus 
} 
#endif 

В качестве альтернативы, установить связь на основе каждого символа:

#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); 

 Смежные вопросы

  • Нет связанных вопросов^_^