2012-04-20 37 views
7

ldd是檢查給定的可執行文件是或將要使用的共享庫的一種很好的簡單方法。但它並不總是按預期工作。例如,請參見下面的外殼片段演示瞭如何「失敗」來發現libreadline「依賴」到Python二進制檢查非默認加載器的共享庫

我嘗試過許多其他的發行版,但我從Tikanga

$ lsb_release -a 
LSB Version: :core-4.0-amd64:core-4.0-ia32:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-ia32:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-ia32:printing-4.0-noarch 
Distributor ID: RedHatEnterpriseServer 
Description: Red Hat Enterprise Linux Server release 5.6 (Tikanga) 
Release:  5.6 
Codename:  Tikanga 
複製

查看ldd對默認安裝的python(來自官方存儲庫)有何作用。

$ which python 
/usr/bin/python 
$ ldd `which python` 
    libpython2.4.so.1.0 => /usr/lib64/libpython2.4.so.1.0 (0x00000030e6200000) 
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00000030e0e00000) 
    libdl.so.2 => /lib64/libdl.so.2 (0x00000030e0a00000) 
    libutil.so.1 => /lib64/libutil.so.1 (0x00000030ee800000) 
    libm.so.6 => /lib64/libm.so.6 (0x00000030e0600000) 
    libc.so.6 => /lib64/libc.so.6 (0x00000030e0200000) 
    /lib64/ld-linux-x86-64.so.2 (0x00000030dfe00000) 
$ ldd `which python` | grep readline 
$ 

沒有找到關於readline的內容。現在我從交互式用法知道這個二進制文件具有真正的功能,所以我們不要試圖看看它來自哪裏。

$ python & 
[1] 21003 
$ Python 2.4.3 (#1, Dec 10 2010, 17:24:35) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-50)] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 

[1]+ Stopped     python 

背景(PID 21003)

$ lsof -p 21003 
COMMAND PID USER FD TYPE DEVICE  SIZE NODE NAME 
python 21003 ddvento cwd DIR 0,33 16384 164304 /glade/home/ddvento/loader-test 
python 21003 ddvento rtd DIR 8,3  4096  2/
python 21003 ddvento txt REG 8,3  8304 6813419 /usr/bin/python 
python 21003 ddvento mem REG 8,3 143600 8699326 /lib64/ld-2.5.so 
python 21003 ddvento mem REG 8,3 1722304 8699327 /lib64/libc-2.5.so 
python 21003 ddvento mem REG 8,3 615136 8699490 /lib64/libm-2.5.so 
python 21003 ddvento mem REG 8,3 23360 8699458 /lib64/libdl-2.5.so 
python 21003 ddvento mem REG 8,3 145824 8699445 /lib64/libpthread-2.5.so 
python 21003 ddvento mem REG 8,3 247544 6821551 /usr/lib64/libreadline.so.5.1 
python 21003 ddvento mem REG 8,3 15840 8699446 /lib64/libtermcap.so.2.0.8 
python 21003 ddvento mem REG 8,3 1244792 6833317 /usr/lib64/libpython2.4.so.1.0 
python 21003 ddvento mem REG 8,3 18152 8699626 /lib64/libutil-2.5.so 
python 21003 ddvento mem REG 8,3 56446448 6832889 /usr/lib/locale/locale-archive 
python 21003 ddvento mem REG 8,3 21808 6965997 /usr/lib64/python2.4/lib-dynload/readline.so 
python 21003 ddvento mem REG 8,3 25464 6901074 /usr/lib64/gconv/gconv-modules.cache 
python 21003 ddvento 0u CHR 136,1    3 /dev/pts/1 
python 21003 ddvento 1u CHR 136,1    3 /dev/pts/1 
python 21003 ddvento 2u CHR 136,1    3 /dev/pts/1 
$ lsof -p 21003 | grep readline 
python 21003 ddvento mem REG 8,3 247544 6821551 /usr/lib64/libreadline.so.5.1 
python 21003 ddvento mem REG 8,3 21808 6965997 /usr/lib64/python2.4/lib-dynload/readline.so 

賓果啓動了一個交互式Python會話!這裏是readline!

然而,這種技術只有當庫有效地加載,因此,例如它沒有找到/usr/lib64/libtcl8.4.so直到蟒蛇過程中不運行像from Tkinter import *

所以我有兩個問題:

  1. 我相信ldd的問題在於它假定使用標準加載器,而很可能python使用它自己的特殊加載器(這樣,每次安裝新的python模塊時都不必重新鏈接可執行文件不是純Python,但有一些C/C++/Fortran代碼)。它是否正確?顯然,如果一個可執行文件使用自己的加載程序,對於「如何找到這個可執行文件可能加載的所有可能的庫」這個問題沒有明顯的答案:這取決於加載程序的功能。但有沒有辦法找出哪些庫可能被python加載?

PS:如果你登陸這個問題,你應該已經知道以下,但如果你不應該涉及到1:看看如何簡單就是要徹底搞砸ldd輸出(只搞亂起來部分地是有點困難):

$ cat hello.c 
#include <stdio.h> 

int main() { 
    printf("Hello world.\n"); 
    return 0; 
} 

$ gcc -static hello.c -o loader 
$ gcc -Wl,--dynamic-linker,./loader hello.c -o hello 
$ ./hello 
Hello world. 
$ ldd ./hello 
Hello world. 

回答

5

Python和Perl中,和其他解釋語言做動態使用dlopen()負載的東西。 (這是不一樣的東西取代了標準裝載,他們仍在使用,而事實上dlopen()是鉤到基於ELF系統標準裝載。)

沒有爲動態加載模塊是標準的註冊表。 Python使用自己的規則來確定可以從哪裏加載擴展模塊(查看sys.path),包括那些具有關聯共享對象的擴展模塊。 Perl使用不同的規則。 Apache仍然使用不同的規則等。

所以要的答案概括您的問題:

  1. 不完全

  2. 沒有

+0

好的,謝謝,我稍微編輯了你的答案並接受了它。 – Davide 2012-04-23 16:03:58

0

作爲一個方面說明,一個可行的辦法來完成我的問題想2將是:

  • 在那裏創建一個空的chroot環境

  • 重新編譯蟒蛇,手動添加任何缺失,一個接一個

根據您的目標,這可能是也可能不是一個很好的解決方案(實際上對於我的目標來說並不算太糟糕 - 聽起來很奇怪)