LINUX.ORG.RU

dlfcn


0

0

Добрый вечер всем!

Не раз работал с функциями семейства `man dlopen` и только сейчас наткнулся на такое препятствие.


Традиционно dlsym вызывается по отношению к подгруженной библиотеке (см. хрестоматийный пример с косинусом). Всю жизнь только так и использовал. А наоборот? Вот загрузил я библиотку(dlopen), нашёл функцию(dlsym), запустил её. Функция эта, в свою очередь, пытается найти символ в основной программе(грубо говоря, в main.c). Может и по-дурацки это, но так досталось в наследство, а бэк-компатибилити соблюдать надо.

Прочитав в мане dlopen строки

"If filename is a NULL pointer, then the returned handle is for the main program."

решил, что вот он способ из библиотеки обратиться к основной программе, и с лёгким сердцем стал искать нужный символ таким образом..
Сначала dlopen(NULL,RTLD_LAZY). Хендлер нормально возвращается. Обрадовался, что всё идёт как нужно. НО! При попытке dlsym необходимого символа из main.c, получаю сообщение про unresolved, хотя символ этот точно есть.

Дебаг с применением методов вроде

#define _GNU_SOURCE

дал следующий результат. dlopen(NULL,...) возвращает хендлер для "/lib64/ld-linux-x86-64.so.2"(симлинк на /lib/ld-2.5.so), где, понятное дело, никаких нужных мне символов нет.

Не подскажете, что делать? Заранее благодарен.

PS Если вдруг требуется
$ cat maps
00400000-00401000 r-xp 00000000 08:12 9618567 /tmp/dlfcn/main
00601000-00602000 rw-p 00001000 08:12 9618567 /tmp/dlfcn/main
00602000-00623000 rw-p 00602000 00:00 0 [heap]
2b453f5f1000-2b453f60d000 r-xp 00000000 08:03 271195 /lib/ld-2.5.so
2b453f60d000-2b453f610000 rw-p 2b453f60d000 00:00 0
2b453f80c000-2b453f80e000 rw-p 0001b000 08:03 271195 /lib/ld-2.5.so
2b453f80e000-2b453f811000 r-xp 00000000 08:12 9093861 /tmp/dlfcn/lib.so
2b454058c000-2b454058d000 rw-p 2b454058c000 00:00 0
7fff6b4a4000-7fff6b4b9000 rw-p 7fff6b4a4000 00:00 0 [stack]
ffffffffff600000-ffffffffffe00000 ---p 00000000 00:00 0 [vdso]

dlopen(NULL, RTLD_LAZY), вызываемая из подгруженной библиотеки, даёт хендлер со значением 2b453f5f1000 - адрес начала /lib/ld-2.5.so в памяти процесса (см. PS в начальном посте)

farisey
() автор топика
Ответ на: комментарий от anonymous

>Попробуйте при линковке главной программы добавить -Bdynamic в командную строку линкера.

Один хрен :-((((

farisey
() автор топика

У меня работает, вот пример:

$ cat main.c
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>

int mymain(int val){
    printf("Function mymain, val %i\n", val);
    return 1;
}

int main(){
    void *handle;
    int (*mylibf)(int val);

    if ( (handle=dlopen ("./mylib.so", RTLD_LAZY)) == NULL )
        return 2;
    mylibf = dlsym(handle, "libf");
    if ( dlerror() != NULL )
        return 3;
    printf("libf addr is %p, ret value is %i\n", mylibf, (int)(*mylibf)(30));
    return 0;
}

$ cat mylib.c 
#define _GNU_SOURCE                                                             
#include <stdio.h>                                                              
#include <dlfcn.h>

int libf(int val)
{
    int (*mymainf)(int val);

    printf("Function libf, val %i\n", val);
    mymainf=dlsym( RTLD_DEFAULT, "mymain" );
    if ( dlerror() != NULL )
        return 33;
    printf("libf addr is %p, ret value is %i\n", mymainf, (int)(*mymainf)(60));
    return 10;    
}

$ gcc -o main  -fPIC -ldl -rdynamic main.c; gcc -o mylib.so -fPIC -shared mylib.c

$ ./main ; echo $?
Function libf, val 30
Function mymain, val 60
libf addr is 0x80486c4, ret value is 1
libf addr is 0x40017714, ret value is 10
0

mky ★★★★★
()
Ответ на: комментарий от mky

>У меня работает, вот пример:

Спасибо огромное. Завелось. Дело было всё-таки во флагах сборки.

farisey
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.