2011-12-18 113 views
1

我試圖用LD_PRELOAD攔截PyDict_New函數。我已經驗證了this recipe在python解釋器中使用了getpid,而我已經使用adapted it to use PyDict_New,但它並不像我期望的那樣工作。雖然我明確分配字典,並且必須使用此函數,但我的覆蓋不會被調用。不能攔截PyDict_New與LD_PRELOAD

我在做什麼錯?


背景:我試圖在一個非常大的系統中調試問題。我發現有一個引用計數不好的字典。我知道字典首先分配的位置,以及問題出現的位置,但我很確定在某個中間時間計數會變差,並且一個簡單的代碼跟蹤不會執行,因爲該字典被緩存並重新使用(通過PyDict_New)由gc系統。

回答

3

LD_PRELOAD只能重載本身自動加載的函數。如果您使用python二進制文件,PyDict_New不會動態加載,因此動態加載程序無法攔截該符號的分辨率。如果您通過編譯自己的二進制文件並使用libpython.so進行鏈接來創建自己的「python」,它應該可以工作。下面是你需要把你的程序(/tmp/foo.c)什麼:

#include "Python.h" 

int 
main(int argc, char **argv) 
{ 
    return Py_Main(argc, argv); 
} 

而且你可以簡單地構建它: 的gcc -o富-I/usr/include目錄/ python2.7 foo.c -lpython2.7

執行此操作後,./foo上的LD_PRELOAD應起作用。

+0

你是什麼意思「自己動態加載」。 LD_PRELOAD不會在不使用-Bsymbolic編譯的共享庫中重寫全局函數嗎? – 2011-12-26 06:23:03

+1

我指的是可執行文件中的符號不​​是由ld.so動態加載的。由於它們沒有被ld.so加載,LD_PRELOAD根本就沒有被使用。在這種情況下,OP想要覆蓋的函數被編譯到python可執行文件中,而不是由ld.so從任何共享庫加載。在提供的解決方案中,所有的python都是從libpython2.7.so動態加載的,所以LD_PRELOAD可以工作。至於-Bsymbolic,我的理解是唯一的影響是讓一個庫首先選擇自己的符號,而不是首先查看可執行文件。 – 2011-12-28 15:58:29

+0

我需要嘗試一下。 – bukzor 2011-12-29 20:14:11

1

我認爲只要下載Python的源代碼分發版(對於與您相關的版本),在調試模式下構建它並使用它運行應用程序會容易得多。

這種方法將爲您提供更多的調試問題的靈活性。例如,您可以在PyDict_New中設置條件斷點,或者將其替換爲您自己的版本。

+0

雖然這不能解決問題,但我會將它投票。我沒有想到這一點。我想我只是不習慣在這麼低的水平上工作。 – bukzor 2011-12-18 04:56:40

+0

@bukzor:你的問題實際上並沒有提供足夠的細節來直接解決(顯示你的代碼,你的編譯/鏈接/執行路徑,你期望的輸出,你看到的輸出等等。*否則它現在太抽象了* )。儘管如此,我提議的方法應該讓你更快地調試你的問題,恕我直言 – 2011-12-18 05:53:17

+0

如果你點擊我的文章中的鏈接,你會發現所有的信息。也許我應該讓他們更加突出/明確。明天會做。 – bukzor 2011-12-18 07:37:09