2016-12-14 3 views
3

Я пытаюсь обернуть функцию GLIBC fstat (это может быть любой другой: это просто доказательство концепции), введя мою библиотеку в исполняемый файл. Я делаю это, поместив свою библиотеку, где указатель исполнителя указывает с именем libc.so.6.Обтекание функции glibc с использованием динамического компоновщика

Исходный код моей библиотеки является один ниже:

#define _GNU_SOURCE 

#include <stdio.h> 
#include <sys/stat.h> 
#include <sys/types.h> 
#include <dlfcn.h> 



int fstat(int fd, struct stat *buf){ 

     typeof(fstat) *old_fstat; 

     // Try with a printf... 

     printf("HOOT! fstat wrapped!"); 

     old_fstat = dlsym(RTLD_NEXT, "fstat"); 
     return (*old_fstat)(fd, buf); 
} 

я скомпилировать его с --version-script (добавить символ управления версиями) и статически связать его с libgcc.

gcc -Wall -fPIC -c -o wrapperlib.o wrapperlib.c 
gcc -shared -static-libgcc -fPIC -Wl,-soname -Wl,libc.so.6 -Wl,--version-script=wrapperlib.map,-Bstatic -o libc.so.6 wrapperlib.o 

С wrapperlib.map, содержащий:

GLIBC_2.0 { 
}; 

Когда я исполняю целевую программу моя библиотека будет загружена, но я получаю следующее сообщение об ошибке:

./target: relocation error: ./target: symbol __libc_start_main, version GLIBC_2.0 not defined in file libc.so.6 with link time reference 

Если я обеспечиваю свою собственную реализацию __libc_start_main Я не получаю эту ошибку (но, конечно, сбой).

int __libc_start_main(int (*main) (int, char **, char **), int argc, char *argv, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void *stack_end) { 
     system("echo I am in __libc_start_main"); 
     printf("printf: I am in __libc_start_main"); 
     fflush(stdin); 
    return 0; 
} 

Почему возникает ошибка перемещения на __libc_start_main и не на system?

(Кстати, призыв к system не делает работу, но вызов printf не выводит Я пропускаю что-то очевидное здесь.?)

Спасибо

Edit: Запуск цели с LD_DEBUG=all выходы это: http://pastebin.com/iVVbwf6n

ответ

1

I [place] my library where the executable's RPATH is pointing with the name libc.so.6 .

И поэтому процесс загружает библиотеку ИНСТЕ объявление GLIBC's libc.so.6. Это, безусловно, не то, что вы хотите, если не предоставляете независимый не менее всю стандартную библиотеку C. Для этого требуется, чтобы ваша библиотека предоставляла все в libc.so.6, а также для динамической загрузки реального libc. Я вижу, что вы пытаетесь достичь полноты статически связывая libgcc (я предполагаю, что вы имеете в виду, используя -lstatic-libgcc), но

  1. это неправильный библиотеки. Он предоставляет функции поддержки скомпилированных двоичных файлов GCC, которые могут включать в себя обертки или альтернативы для некоторых функций C-библиотеки, но он не предоставляет сама библиотеку C.

  2. , даже если вы связали библиотеку C статически (например, -lc_nonshared), библиотека, которую вы получите таким образом, не будет содержать динамически загружаемый символ, с помощью которого вы можете получить доступ к завернутой функции. Это прямое следствие статической привязки.

  3. Ваша библиотека в любом случае не является независимой, поскольку она пытается обернуть реализацию GLIBC fstat(), которая недоступна для нее.

Why is there a relocation error on __libc_start_main and not on system ?

Существует ошибка перемещения на __libc_start_main, потому что функция обеспечивается libc.so.6 в GLibC, но не вашим, ни самой или любой другой библиотеки бинарным динамически связаны с бинарным , (см (1) выше)

Если нет ошибки перемещения для system или printf функций, то из этого следует, что либо это не те внешние динамические символы с бинарным или они удовлетворены какой-либо другой библиотекой динамически связанных с вашим двоичным кодом. (Обновление: информация об отладчике компоновщика показывает, что в первом случае это не внешние символы, под которыми я подразумевал символы, для которых не задано определение, они предоставляются вашей библиотекой, предположительно в результате ссылки в libgcc.) Детали не имеют большого значения, поскольку дело в том, что ваша стратегия совершенно неработоспособна. Вместо этого используйте вместо этого LD_PRELOAD.

Update: альтернативой может быть, чтобы дать общей библиотеке функцию конструктора, которая dlopen() s реальный libc.so.6 с флагом RTLD_GLOBAL включена. Таким образом, ваша библиотека не должна предоставлять полную библиотеку C, но она должна знать, как найти настоящую библиотеку. Это, безусловно, решит проблему того, что обернутая функция недоступна в оболочке.

+0

Спасибо за ответ. Я не использую LD_PRELOAD, потому что все дело в том, чтобы обернуть вызов функции GLIBC с единственным использованием RPATH цели. Тем не менее, я не вижу, какая другая библиотека может удовлетворить этим символам: я отредактировал, чтобы включить вывод LD_DEBUG. – 0xdeda10

+0

@mr_sparxx, я существенно пересмотрел и обновил ответ, заметив ваше замечание о том, что вы статически связываете libgcc, который я ранее забыл. –

+0

Да, я имел в виду -lstatic-gcc (я отредактировал мой пост), и это было мое заблуждение, я попробую путь, который вы открыли при обновлении. – 0xdeda10

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