2017-12-02 150 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