2017-12-02 244 views
1

我想使用一个古老的软件(从1999年开始的虚幻竞技场“经典”,也被称为UT99)。隐式加载动态库libtxc_dxtn.so,探测可选的S3纹理压缩(S3TC)支持。不幸的是,在加载库时,主应用程序崩溃并出现分段错误(崩溃还描述了here)。解决方法似乎是通过删除或移动libtxc_dxtn.so来移除Mesa的纹理压缩库。应用程序运行得非常好,没有纹理压缩,但当然其他需要纹理压缩支持的应用程序现在已经被破坏。当然,我不想为一个特定的应用程序修改我的系统。如何防止加载特定的动态库

所以我的问题是:
我可以防止特定的应用程序加载特定的动态库(如在“掩码”或“禁用”)?我希望能找到类似LD_PRELOAD的相反情况。

更新libtxc_dxtn.so是含蓄和间接加载。修改应用程序二进制文件不可行。

initialize program: ut-bin 
file=libSDL-1.1.so.0 [0]; needed by ut-bin [0] 
file=libGL.so.1 [0]; dynamically loaded by libSDL-1.1.so.0 [0] 
file=i965_dri.so [0]; dynamically loaded by libGL.so.1 [0] 
file=libtxc_dxtn.so [0]; dynamically loaded by i965_dri.so [0] 
+0

你是什么意思_indirectly loaded_? 'dlopen的()'?如果是的话,也许你可以'LD_PRELOAD'一个'dlopen()'覆盖,不会让'libtxc_dxtn.so'通过。 – PSkocik

+0

是的,使用'dlopen()'。尽管通过“间接加载”,我的意思是“库不是由应用程序本身加载的,而是由共享库加载的,而该库又由应用程序加载”。在我的情况下,它是'应用程序→→libSDL-1.1.so.0'→'libGL.so.1'→'i965_dri.so'→'libtxc_dxtn.so'。只有第一个库被加载为一个依赖项,其他的则被加载了'dlopen()'。 – Hermann

+0

'dlopen'覆盖方法的'LD_PRELOAD'应该可以工作(只要依赖库不使用'RTLD_LOCAL',但这是一个不应使用的不推荐使用的非标准标志)。我已经更新了我的答案。 – PSkocik

回答

2

有一个叫工具,它应该让你从可执行文件中删除DSO依赖。

下面是一个例子,从一个虚拟的可执行文件删除一个libpthread依赖性:

echo 'int main(){}' | 
    gcc -x c - -Wl,--no-as-needed -lpthread && 
    ldd a.out && 
    patchelf --remove-needed libpthread.so.0 a.out && 
    echo ====== && 
    ldd a.out 

我的输出:

linux-vdso.so.1 => (0x00007ffeced67000) 
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f21560f1000) 
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2155d28000) 
    /lib64/ld-linux-x86-64.so.2 (0x00007f215630f000) 
====== 
    linux-vdso.so.1 => (0x00007fffac536000) 
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6235c0d000) 
    /lib64/ld-linux-x86-64.so.2 (0x00007f6235fd6000) 

更新:

如果libtxc_dxtn.so装有dlopen,你可以预先加载(LD_PRELOAD)提供0123的小型库覆盖将返回NULL如果 其文件名参数是例如"libtxc_dxtn.so"ltrace应该帮助您找到需要防范的实际文件名参数)。例如:

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

void *dlopen(char const *Fnm, int Flg) 
{ 
    void *(*real_dlopen)(char const *, int); 
    *(void**)(&real_dlopen) = dlsym(RTLD_NEXT, "dlopen"); 
    if(0==strcmp("libtxc_dxtn.so", Fnm)){ 
     return NULL; 
    }else{ 
     return real_dlopen(Fnm, Flg); 
    } 

} 
+1

我添加了一个'Fnm'为NULL的检查,并将调用转发给'real_dlopen'。现在这个效果很好。我非常感谢你的详细解答。 – Hermann

+0

为了记录,https://stackoverflow.com/questions/6083337/overriding-malloc-using-the-ld-preload-mechanism在这方面也很有帮助。 – Hermann