2009-07-07 64 views
1

我在網上閱讀了一些關於Vtable thunk的文章,並且我在某處讀到thunk可以用來鉤住/連鎖程序調用。使用v-table thunk連鎖程序調用

它可以實現嗎?

有沒有人知道這是如何工作,我也無法找到很好的資源解釋thunk。 對此有何建議?

+0

你能否澄清你的問題?目前,連同你的評論,它看起來像「告訴我涉及thunk的所有事情的一切」,這有點...廣泛。 – peterchen 2009-07-07 10:33:46

回答

3

以v-table thunk的方式實現原始thunk是最後的手段。無論你需要完成什麼,最有可能通過包裝函數來實現,而且它將不那麼痛苦。

通常,一個thunk執行以下操作:

  1. 固定起來的輸入參數(例如,轉換爲不同的格式)
  2. 呼叫真正實施
  3. 清理步驟1 /固定輸出參數

看到它是如何工作的例子,讓我們來談談我們的好朋友雷蒙德陳和他的調節器的thunk的討論:

http://blogs.msdn.com/oldnewthing/archive/2004/02/06/68695.aspx

他用形實轉換如下:

[thunk]:CSample::QueryInterface`adjustor{4}': 
    sub  DWORD PTR [esp+4], 4 ; this -= sizeof(lpVtbl) 
    jmp  CSample::QueryInterface 

他介紹,您可以實現多個接口相同的方法的類,所以它有多個V-表。 (如果你不知道COM,你只需要知道它是直接與v-tables一起工作的,所以指向特定接口的指針必須包含指向該接口的所有方法的函數指針,按照的順序。)

如果您在特定插槽中使用不同方法實現兩個接口,則需要多個v-表。但是,你只寫一次重疊的方法,所以這個方法需要能夠同時使用這個「this」指針。要做到這一點,編譯器會生成一個方法來完成必要的修復並調用原始實現。

所以,這確實的thunk以下步驟:

  1. 修復了輸入參數,即隱藏的「this」指針,在第一線。
  2. 在第二行中調用真正的實現。
  3. 清理:沒有要求(見下文)

這就是jmp指令出現在通常情況下,如果你要調用使用call功能,它將返回給你,你必須。 ret返回給您的來電者。由於沒有清理工作要做,編譯器會執行一個優化,將執行直接移動到真正的實現中,讓真正的實現返回語句返回到您的調用者。這只是一個優化,而不是thunking的基本部分。例如,16/32位thunk會根據需要將輸入/輸出參數在16和32位之間轉換,因此它不能跳過清除步驟;它必須call,而不是jmp。這個故事的寓意是:如果你需要做某些事情,如jmp優化,你不能直接用C++或其他高級語言編寫代碼,那麼繼續編寫一個彙編語言thunk 。否則,只需編寫一個包裝並完成它。老實說,這聽起來像你要求性能優化,而且大部分時間(1)編譯器在優化上比我們想象的要好,(2)它不會給你帶來很大的改進如你想象的。

0

嗯,你讀過thunk是一個解決方案,現在你正在尋找一個問題來解決?

Thunk通常是簡短的「轉發」功能,可以提供較小的(通常是硬編碼的)調整。

目前在wikipedia中已經很好地解釋了VTable塊。他們使用通用模式:生成一個小函數來避免運行時的計算/額外工作。

其它地方我見過/使用的thunk:

關聯的窗口句柄與一個窗口對象:用於被子類每個窗口,對與該對象調用窗口過程中動態生成一個小的thunk參考,然後使用thunk作爲窗口過程。

延遲加載DLL:thunk確保在第一次調用任何函數時加載DLL。

捕獲COM接口調用:thunks爲診斷提供了一個注入點,並跳轉到實際的方法。

+0

請問你能指出一些資源/鏈接,可以顯示一些例子,如果有任何與thunk的所有這些? – anand 2009-07-07 07:53:42