如何让共享库中的符号覆盖现有符号?

问题描述 投票:0回答:1

我想用dlopen加载一个共享库,并在其中提供符号,而无需使用dlsym单独获取它们的函数指针。 man pageRTLD_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);
}

implementation.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.soRTLD_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

c shared-libraries dlopen
1个回答
2
投票

从根本上没有办法做你想要的。想象一下主程序有:

static char *myptr = array_in_lib1;

后来,在你dlopen时,myptr还有其他价值。程序刚刚将变量更改为指向不同的对象吗?或者它是否已经增加以指向数组中的某个元素 - 在这种情况下,您是否希望将其调整为使用新打开的库中的新定义来重新定义array_in_lib1?或者它只是一个随机整数投射到char *?如果不了解程序员的意图以及它如何到达当前状态的完整过程历史,决定如何对待它是不可能的。

以上是我构建的一个特别令人震惊的例子,但是符号在运行时改变定义的想法在各种方面都是根本不一致的。甚至RTLD_DEEPBIND,它已经做了,可以说是不和谐和错误。无论你想做什么,你都应该找到另一种方法。

© www.soinside.com 2019 - 2024. All rights reserved.