Как сделать так, чтобы символы в общей библиотеке переопределяли существующие символы? - PullRequest
0 голосов
/ 23 сентября 2018

Я хочу загрузить разделяемую библиотеку с помощью dlopen и сделать так, чтобы символы в ней были доступны без необходимости индивидуального захвата указателей на функции с помощью dlsym.Страница man говорит, что флаг RTLD_DEEPBIND поместит поиск символов в библиотеке перед глобальной областью видимости, но, очевидно, это не означает, что он переопределяет существующие символы, потому что это не работает.Рассмотрим этот пример:

main.c:

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

int is_loaded(){return 0;}

int main(){
    void *h = dlopen("./libimplementation.so", RTLD_NOW | RTLD_DEEPBIND);
    if(!h){
        printf("Could not load implementation: %s\n", dlerror());
        return 1;
    }
    puts(is_loaded() ? "Implementation loaded" : "Implementation not loaded");
    dlclose(h);
}

creation.c:

int is_loaded(){return 1;}

Makefile:

all: main libimplementation.so

main: main.c
    gcc -Wall -std=c99 -o $@ $^ -ldl

lib%.so: %.c
    gcc -Wall -std=c99 -o $@ $^ -shared

clean:
    -rm main *.so

Когда я собираюи запустить с make и ./main, я ожидаю, что функция test() из libimplementation.so переопределит функцию test() с main, но это не так.Я знаю, что мог бы также переместить весь код в main() в другую общую библиотеку run, а затем иметь main() dlopen libimplementation.so с RTLD_GLOBAL и затем librun.so обращаться к символам из libimplementation.so без их определения, поэтому он загружает их:

измененный main.c:

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

int main(){
    void *impl_h = dlopen("./libimplementation.so", RTLD_LAZY | RTLD_GLOBAL);
    if(!impl_h){
        printf("Could not load implementation: %s\n", dlerror());
        return 1;
    }
    void *run_h = dlopen("./librun.so", RTLD_LAZY);
    if(!run_h){
        printf("Could not load run: %s\n", dlerror());
        dlclose(impl_h);
        return 1;
    }
    void (*run)(void);
    *(void**)&run = dlsym(run_h, "run");
    if(!*(void**)&run){
        printf("Could not find entry point in run: %s\n", dlerror());
        dlclose(impl_h);
        dlclose(run_h);
        return 1;
    }
    run();
    dlclose(impl_h);
    dlclose(run_h);
}

run.c:

#include <stdio.h>

int is_loaded(void);

void run(void){
    puts(is_loaded() ? "Implementation loaded" : "Implementation not loaded");
}

и Makefile получает librun.so добавлено в качестве предварительного условия для all.

Есть ли способ получить символы из общей библиотеки, доступные одновременно, без dlsym или поместить фактический код в другую общую библиотеку, например, с librun.so

1 Ответ

0 голосов
/ 23 сентября 2018

По сути, нет способа сделать то, что вы просите.Представьте, что основная программа имеет что-то вроде:

static char *myptr = array_in_lib1;

Позже, когда у вас dlopen, myptr есть какое-то другое значение.Программа только что изменила переменную, чтобы указать на другой объект?Или же он был увеличен, чтобы указывать на какой-либо элемент в массиве позже - в этом случае вы бы хотели, чтобы он был скорректирован с учетом переопределения array_in_lib1 с новым определением из вновь открытой библиотеки?Или это просто случайное целое число, приведенное к char *?Решить, как это лечить, невозможно без понимания намерения программиста и полной истории процесса того, как оно пришло в текущем состоянии.

ВышеЭто особенно вопиющий пример, который я построил, но идея изменения символов во время выполнения принципиально противоречива во всех отношениях.Даже RTLD_DEEPBIND в том, что он уже делает, возможно, неуместен и глючит.Что бы вы ни пытались сделать, вы должны найти другой способ сделать это.

...