C 如何防止加载特定的动态库

C 如何防止加载特定的动态库,c,linux,shared-libraries,ld,dlopen,C,Linux,Shared Libraries,Ld,Dlopen,我想使用一个古老的软件(1999年的“经典”虚幻锦标赛,也称为UT99)。动态库libtxc\u dxtn.so隐式加载,探测可选的S3纹理压缩(S3TC)支持。不幸的是,在加载库时,主应用程序因分段错误而崩溃(也描述了崩溃)。一种解决方法似乎是通过删除或移动libtxc\u dxtn.so来删除Mesa的纹理压缩库。该应用程序在没有纹理压缩的情况下运行得非常好,但当然,其他需要纹理压缩支持的应用程序现在已经崩溃了。当然,我不想为一个特定的应用程序修改我的系统 所以我的问题是: 我是否可以阻止(

我想使用一个古老的软件(1999年的“经典”虚幻锦标赛,也称为UT99)。动态库
libtxc\u dxtn.so
隐式加载,探测可选的S3纹理压缩(S3TC)支持。不幸的是,在加载库时,主应用程序因分段错误而崩溃(也描述了崩溃)。一种解决方法似乎是通过删除或移动
libtxc\u dxtn.so
来删除Mesa的纹理压缩库。该应用程序在没有纹理压缩的情况下运行得非常好,但当然,其他需要纹理压缩支持的应用程序现在已经崩溃了。当然,我不想为一个特定的应用程序修改我的系统

所以我的问题是:
我是否可以阻止(如“掩码”或“禁用”)特定应用程序加载特定的动态库?我希望找到类似于
LD\u PRELOAD
的相反内容

更新
libtxc\u dxtn。因此
是隐式和间接加载的。修改应用程序二进制文件是不可行的

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]
有一个名为的实用程序,它应该允许您从可执行文件中删除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\u dxtn.so
加载了
dlopen
,您可以预加载(
LD\u preload
)一个小型库,该库提供了
dlopen
覆盖,如果 它的文件名参数是,例如,
“libtxc\u 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);   
    }

}
定义GNU源
#包括
#包括
void*dlopen(字符常量*Fnm,内部Flg)
{
void*(*实开)(字符常量*,int);
*(void**)(&real_dlopen)=dlsym(RTLD_NEXT,“dlopen”);
如果(0==strcmp(“libtxc_dxtn.so”,Fnm)){
返回NULL;
}否则{
返回实际打开(Fnm、Flg);
}
}

间接加载是什么意思<代码>dlopen()?如果是,也许您可以
LD\u PRELOAD
a
dlopen()
覆盖它,它不会让
libtxc\u dxtn。因此
通过。是的,使用
dlopen()
。虽然“间接加载”是指“库不是由应用程序本身加载的,而是由共享库加载的,而共享库又是由应用程序加载的”。在我的例子中,它是
应用程序
→ <代码>libSDL-1.1.so.0
→ <代码>libGL.so.1
→ <代码>i965_dri.so→
libtxc_dxtn.so
。只有第一个库作为依赖项加载,其他库使用
dlopen()
加载。
dlopen
覆盖方法的
LD\u PRELOAD
应该可以工作(只要依赖库不使用
RTLD\u LOCAL
,但这是一个不推荐使用的非标准标志,无论如何都不应该使用)。我已经更新了我的答案。我添加了一个检查
Fnm
是否为空,并将调用转发到
real\u dlopen
。现在这个效果很好。我感谢你非常详细的回答。作为记录,我们在这方面也很有帮助。