c - 如何防止特定动态库被加载

标签 c linux shared-libraries ld dlopen

我想使用一款古老的软件(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]

最佳答案

有一个名为 patchelf 的实用程序这应该允许您从可执行文件中删除 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) 提供 dlopen 的迷你库 重写将返回 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);   
    }

}

关于c - 如何防止特定动态库被加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47611304/

相关文章:

检查三元运算符是否存在的 C 程序

linux - 如何使用带有 Perl -e 参数的 cat 读取文件?

c - 在同一进程中多次加载共享库的地址空间

linux - 为什么我需要在安装我的二进制文件后设置 LD_LIBRARY_PATH?

c - dlopen 无法为作为原型(prototype)的函数定义符号

c - 从C中的字符串中逐个字符地读取

c - 如何以与在终端中写入的方式完全相同的方式在文件中写入文本?(保留所有空格)

c - 在 C 中,如何写入特定的内存位置,例如视频内存 b800,在 DOS 中(真正的 DOS,MS DOS 6.22)

java - 在 CentOs 中将 java 应用程序作为服务运行时遇到错误 : nested exception is java. lang.UnsatisfiedLinkError

linux - Linux 中的选择性核心转储 - 如何选择转储部分?