LINUX.ORG.RU

Как в .so-библиотеке узнать адрес функции из главной программы?


0

0

Этот код либо возвращает 0 из dlsym (хотя dlopen срабатывает), либо сегфолтится, если основной бинарник скомпилировать с опцией -rdynamic. Что нужно сделать, чтобы пример работал? Какие-то опции?

void init()
{
	void* handle = dlopen(NULL, RTLD_NOW);
	ksfree = dlsym(handle, "ksfree");
	ksmalloc = dlsym(handle, "ksmalloc");
	neuro_unref = dlsym(handle, "neuro_unref");
}

★★
Ответ на: комментарий от Spectr

man dlopen: If filename is NULL, then the returned handle is for the main program. И в интернете есть примеры использования, так что на первый взгляд все правильно.

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

If the first argument is NULL, dlopen() returns a handle on > the global symbol object. This object provides access to all symbols from > an ordered set of objects consisting of the original program image and > any dependencies loaded during startup.

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

Ди и вообще как оно может помочь? Это к генерации кода относится, а мне надо хотя бы адрес функции найти.

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

#include <stdio.h>
#include <dlfcn.h>

int main(void) {
void *handle = dlopen(NULL, RTLD_NOW);
void *dlopen_ptr = dlsym(handle, "dlopen");
fprintf(stderr, "0x%08X\n", (long)dlopen_ptr);
return 0;
}

gcc -ldl test.c
./a.out
0x4003DE90

я конечно понимаю что раз я не телепат то я не в теме, но все же отнюдь не очевидно что за функции ты пытаешся найти, какого типа у тебя переменные куда ты их пытаешся сохранить, подключается ли твоя либа с функциями вообще при сборке и/или запуске, и могут ли тебе помочь флаги RTLD_GLOBAL etc.

Spectr ★★★
()
#include <stdio.h>
#include <dlfcn.h>

int say_hello(void) {
        printf("hello\n");
        return 1234;
}

int main() {
        void *handle = dlopen(NULL, RTLD_NOW);
        int (*hello_func)(void) = handle ? dlsym(handle, "say_hello") : NULL;

        if (hello_func)
                printf("=> %d\n", hello_func());

        return 0;
}
$ gcc -ldl -rdynamic test.c -o test
$ ./test
hello
=> 1234

я даже хз почему у вас не работает…

arsi ★★★★★
()

Посмотрел исходники glade_xml_signal_autoconnect(), там все точно как у меня. Не понимаю, что не так?

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

>man ld<CR> /-export-dynamic<CR>

делаю -rdynamic
Pass the flag -export-dynamic to the ELF linker, on targets that support it. This instructs the linker to add all symbols, not only used ones, to the dynamic symbol
table. This option is needed for some uses of "dlopen" or to allow obtaining backtraces from within a program.

не помогает

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

Простые примеры работают. Не работает в более крупном проекте http://bitbucket.org/wieker/agtevo/, но понятное дело разгребать мой быдлокод Вам не захочется. Когда же я найду минимальный неработающий пример, все, думается, станет очевидным (в чем ошибка).

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

Вообще странная задача какая-то. Просто указателями на функции без всяких dlopen/dlsym воспользоваться нельзя?

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

Указатели на функции передавать в функциию инициализации библиотеки? Можно, но мне это показалось некрасиво.
Но проблема не в dlopen/dlsym. Они работают. Проблема в том, что я непраильно написал кое-что. Спасибо всем за помощь.

wieker ★★
() автор топика
Ответ на: комментарий от wieker
typedef void (*ksfree_t)(void* ptr);
typedef void* (*ksmalloc_t)(size_t size, char* type);
typedef void (*neuro_unref_t)(neuro_t* neuro);
ksfree_t ksfree;
ksmalloc_t ksmalloc;
neuro_unref_t neuro_unref;

void init()
{
	void* handle = dlopen(NULL, RTLD_NOW);
	ksfree = dlsym(handle, "ksfree");
	ksmalloc = dlsym(handle, "ksmalloc");
	neuro_unref = dlsym(handle, "neuro_unref");
}

Не работает вот такой участок - запись в ksfree вызывает SegFault. Что я делаю не так?

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

Это не минимальный код, так как его нельзя откомпилировать и запустить. <telepat> Прозреваю, что делаешь ты это 1.c:

#include <sys/types.h>
#include <stdlib.h>
#include <dlfcn.h>

typedef void (*ksfree_t)(void* ptr);
ksfree_t ksfree;

void init()
{
   void* handle = dlopen(NULL, RTLD_NOW);
   ksfree = dlsym(handle, "ksfree");
}

void main() {
        init();
}
2.c:
void * ksfree(void*ptr){
        return 0;
};

И ессесно получаешь херню. На такое мой линкер пишет ворнинги. Переименую переменную ksfree или вытащи её из global-scope. </telepat>

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

А что они изменят? Этот пример из файла shared-object.c, который компилируется в shared-object.so

init вызывается из основной программы. shared-object.so должен использовать функции основной программы, допустим я передам ему указатели на функции в качестве параметров init(), а где он их сохранит, если присваивание глобальных указателей на функции вызывает SegFault? На dlopen я же не настаиваю.

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

1.c

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

void ksfree(void * );

void init()
{
   printf("init\n");
}

void do_all()
{
        ksfree(0);
}
2.c:
#include <stdio.h>

void * ksfree(void*ptr){
        printf("picez\n");
        return 0;
};

void init();

int main()
{
        init();
        do_all();
}
$gcc -shared 1.c -fPIC -o lib1.so
$gcc 2.c -l1 -L.
$$ ./a.out
init
picez

Подозреваю, что dlsym у тебя пытается перезаписать адрес функции ksfree из основной программы и обламывается.

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