如何偵錯平面 Thunk

文章翻譯 文章翻譯
文章編號: 133722 - 檢視此文章適用的產品。
全部展開 | 全部摺疊

在此頁中

結論

偵錯平面 Thunk 編譯器所產生的 Thunk 可能會很困難,因為 Thunk 機制是複雜且難以使用能夠透過 Thunk 追蹤的偵錯工具。本文提供偵錯平面 Thunk、 幾個特定的偵錯技術,以及說明如何修正許多 thunking 常見問題的疑難排解指南的整體的策略。

其他相關資訊

目標 DLL 可以做什麼的限制

您開始偵錯 Thunk 之前請記住有一些 DLL 可以執行一個 Thunk 內部的哪些目標上的限制。這是因為一個 Win16 架構的應用程式呼叫 Win32 架構的 DLL 不是 Win32 架構的程序 ; 同樣地,一個 Win32 架構的應用程式呼叫 Win16 架構的 DLL 不 Win16 架構的程序。常見的特定限制包括:

  • 您無法從 Win32 DLL Win16 架構的應用程式建立一個 Thunk 內的執行緒。
  • 內部 Win32 架構的 DLL Thunk 由呼叫程式碼應該需要少許的堆疊空間,因為呼叫的 Win16 架構處理程序擁有比未 Win32 架構的應用程式的小很多堆疊。
  • 處理插斷時,Win16 DLL 包含插斷服務常式 (ISR 以) 不必須 thunk 至 Win32 DLL。
  • Win32 架構的應用程式必須不將指標傳遞到 Thunk 或呼叫切換堆疊的 Win16 架構 DLL 的參數為位於堆疊上的資料。

偵錯平面 Thunk 為什麼很難

偵錯平面 Thunk 是困難,部分是因為平面 Thunk 機制是 Windows 核心複雜的一部份。16 位元的程式碼,反之亦然,從事實,它必須轉換成 32 位元已編譯的程式碼中的函式呼叫其複雜性樹幹呼叫相容。因為 32 位元程式碼會使用不同的資料型別,而 CPU 註冊從 16 位元的程式碼集平面 Thunk 機制必須轉譯函式參數、 切換堆疊,並轉譯傳回值。它針對速度,最佳化,還必須允許先佔式 Win32 程式碼呼叫未先佔式 Win16 程式碼。Thunk 編譯器進行建立平面 Thunk 比以手動方式建立它們,更容易,但它不是萬無一失。

偵錯平面 Thunk 不困難,只因為本身的機制是複雜,但也因為必要的偵錯工具會更難掌握。例如 Microsoft Visual C++ 偵錯工具和 WinDBG 無法追蹤透過 Thunk 因為 32 位元和 16 位元程式碼所組成,而且會導致系統聲稱或放開 [Win16Mutex,偵錯工具應用程式層級。若要追蹤透過一個 Thunk,您需要使用系統層級偵錯工具,例如 WDEB386.EXE。若要使用 WDEB386.EXE 主要的缺點是您需要知道 Intel x86 組件語言知道 Intel x86 微處理器的運作方式,並記住許多偵錯工具命令。

若要使用最佳的策略

最佳的策略偵錯 Thunk 是為分配和征服因為相當簡單,並排除大部分的問題之前您必須透過系統層級偵錯工具中的組件語言程式碼的追蹤。平面 Thunk 是由組成 Win32 架構的 DLL 和 Win16 架構 DLL 的所以若要測試每一種隔離一起測試之前。 建立 Win16 架構應用程式,以測試 Win16 架構] DLL,並建立一個 Win32 架構應用程式來測試 Win32 架構的 DLL。這樣做可以讓您可以使用各種不同的偵錯工具,請確認每一邊可以正確運作。

初步的檢查清單-使用 Thunk 編譯器編譯之前

一旦您已驗證過每一側可以正確運作的時候放入這兩個一起,以測試 Thunk 本身。編譯與 Thunk 編譯器 Thunk 之前進行初步檢查下列項目:
  1. 您 Thunk 指令碼中請確定每個函式具有正確的數目和參數型別。同時確定 Thunk 編譯器所支援參數型別。如果它們不必須某種方式將參數變更為傳遞與支援的型別資料。
  2. 如果以參數形式傳遞任何結構,請確定您使用相同的結構封裝在 Win32 DLL、 Win16 架構的 DLL 和 Thunk 指令碼。在 C/C + + 編譯器的命令列和 Thunk 編譯器命令列中,您會設定結構封裝。請注意 Thunk 編譯器封裝參數針對 16 位元的邊小寫和大寫的 32 位元邊。
  3. 請確定正在 thunking 到函式正確匯出,而且使用呼叫慣例,如果它們是 16 位元或 _stdcall,如果它們是 32 位元 PASCAL。Thunk 編譯器不支援 _cdecl 和 __fastcall 呼叫慣例。
  4. 請確定您 Win32 架構的 DLL 呼叫 ThunkConnect32() 每次呼叫其 DllMain() 函式。同樣地,請確定 Win16 架構 DLL 匯出的 DllEntryPoint() 函式,分開其 LibMain() 呼叫 ThunkConnect16() 並傳回 TRUE ThunkConnect16() 會成功。

    注意: 您實際呼叫 XXX_ThunkConnect16() 和 XXX_ThunkConnect32() XXX 是符號的位置與 Thunk 編譯器-t 參數定義。由 Thunk 編譯器所產生的程式碼會使用這些符號產生呼叫 ThunkConnect16() 和 ThunkConnect32 的資料表。
  5. 請確定 Thunk 編譯器命令列-t 參數中指定的值是相同的 「 Win32 」 和 「 Win16 Thunk DLL。值也必須對應至 (請參閱附註在步驟 4 中的) 在 Win16 基礎和以 Win32 基礎 DLL ThunkConnect 呼叫的前置詞。
  6. 請確認 Win16 架構 DLL 具有 DLLEntryPoint 以 RESIDENTNAME 關鍵字在它的模組定義 (.DEF) 檔匯出。沒有 RESIDENTNAME] 關鍵字 ThunkConnect32/ThunkConnect16 呼叫會失敗,並不會載入 DLL。
  7. 請確認 16 位元 DLL 具有 XXX_ThunkData16 以 RESIDENTNAME 關鍵字在它的模組定義 (.DEF) 檔匯出。
  8. 請確認在 Win16 架構 DLL 的 Makefile 中,資源編譯器會將 DLL 標示為 4.0。如果它標示為小於 4.0,它不會載入,並將 Thunk 將會失敗。
  9. 如果您的 32 位元為 16 位元 Thunk 函式傳回的指標,請確定基底型別相同的大小在 16 位元和 32 位元的兩邊 Thunk。如果基底型別的大小不同,Thunk 編譯器發出錯誤訊息指出,"無法指標非相同的型別,返回"如果要解決這個問題的方法之一是將一個指標傳回至不同,但相容,資料型別。比方說一 Thunk 無法傳回指標為 int 因為 int 是 16 位元邊的但在 32 位元邊的四個位元組的兩個位元組。變更從一個指標的 Thunk 的傳回型別,長時間 Thunk 指令碼和 Win16 基礎和以 Win32 基礎 DLL 的原始程式碼中的指標為 int。

    如果您撰寫 16 位元到 32 位元 Thunk,傳回的指標、 Thunk 編譯器會發出錯誤訊息指出、 」 指標型別可能不會傳回"。Thunk 編譯器不允許 16 位元到 32 位元 Thunk,要傳回的指標型別,因為一旦將 Thunk 已由 32 位元函式傳回,指標不會指向正確的 Win32 程序位址空間中的資料。這是因為地址空間的所有 Win32 架構的處理序的使用相同的範圍位址,且都是 preemptively 內容切換。
  10. 如果連結器報告"無法解析外部 」 的錯誤,且該符號一致地拼寫整個所有的原始程式碼、 模組定義檔和 Thunk 指令碼的函式名稱,請確定所有的項目其原型一致。Win32 一邊 Thunk 函式必須用 __stdcall 型別宣告 ; Win16 一邊函式必須用 PASCAL 型別宣告。C + + 專案中務必要宣告和使用 extern"C"連結規範,除了 __stdcall 或 PASCAL 型別定義 Thunk 函式的兩面。

trouble-shooting 指南-後以 Thunk 編譯器編譯

檢查初稿後建置您 Thunk DLL,並嘗試執行它們。如果它們執行繼續進行進一步的測試,以確定他們正搖動實心。如果它們不執行使用下列疑難排解指南判斷並修正問題的原因。

在 Win16 或 ThunkConnect32() ThunkConnect16() Win32 端就會失敗:

  1. 執行偵錯版本的系統 DLL。KERNEL32.DLL 和 KRNL386.EXE 偵錯版本都含有許多診斷訊息,告訴您為什麼 Thunk 未初始化。若要執行偵錯版本的系統 DLL,使用 [在 Win32 SDK 工具] 下的 [開始] 功能表中的 [」 切換至偵錯 DLL 」 圖示]。使用 「 切換到非偵錯的 DLL 中 「 若要切換回零售版本。
  2. 請確認 Win16 架構 DLL 有 ThunkConnect16() 的呼叫 Win32 架構的 DLL 已經以 ThunkConnect32() 對應的呼叫。如果其中這些遺失,然後另將會失敗並 Thunk DLL 會載入失敗。
  3. 將中斷點放在您的 Win32 DLL DllMain() 並在您的 Win16 DLL DllEntryPoint() 和 LibMain() 函式,以查看哪些 DLL 不載入。
如果 ThunkConnect16() 和 ThunkConnect32() 呼叫正常運作,但仍然不是 Thunk 就該來簡化您 Thunk。您實際上可以攻擊這兩種方式。第一次,請先從 Thunk 一一移除參數,並重新編譯它。或者,其次,建立簡單的 Thunk,運作方式,並建置向上直到它失敗請依照下列步驟執行:
  1. 建立簡單的 Thunk,以及執行只以確定您有 Thunk 機制已正確地設定。簡單的 Thunk 是很好的選擇是函式沒有傳回值和沒有參數。如果沒有作用更簡單的 Thunk,執行透過初步的檢查清單上面請確定您有設定正確的事。然後繼續步驟 2。
  2. 請檢查並確定目標 DLL 和它所依賴的任何 DLL 可找到並載入。如果其中一個遺失,或載入器無法找到,Thunk 不起作用。
  3. 請確定您的目標 DLL 不執行它不能將 Thunk 內容中的項目。
一旦您有簡化的 Thunk,運作方式,但真實 Thunk 仍然無法運作,請依照下列步驟執行:
  1. 如果要判斷如果參數會造成失敗一次加入簡單 Thunk 其中一個參數。如果其中一個是確定參數是正確類型函式宣告,然後以相同的數目和類型參數在這兩個 DLL 和 Thunk] 編譯器中定義,且該函式宣告為 PASCAL 或 _stdcall]。
  2. 如果您的目標 DLL 為 Win16 架構的 DLL,而且它不能存取其全域或靜態資料,請確定您已正確地匯出函式。如果您使用 Visual C++ 使用 /GD 參數,必須宣告和定義該函數與 __export 關鍵字 Win16 架構之 DLL 的原始程式碼中。只列出在 DLL 的模組定義 (.DEF) 檔中的函式的名稱不是足夠,因為編譯器不會處理該的.DEF 檔,以便它將不會產生初構和終解匯出函式的程式碼需要。
  3. 如果呼叫 LocalAlloc() 中您目標 Win16 DLL 原因] 一般保護 (GP) 錯誤,請確定您的函式會匯出,步驟 2 所述。
  4. 如果您收到 GP 容錯 KERNEL32 中只是 Win16 架構函式會傳回您的目標之後,確定目標函式宣告並定義為 PASCAL。無法使用 C 呼叫慣例。雖然在 C + + 程式碼,但更有可能在組件語言中不常見確定目標函式並未修改 DS、 SS、 BP、 SI 或 DI 暫存器。
  5. 如果您 Win32 架構目標函式傳回之後,立即在您的 32 位元 Thunk DLL 或 KERNEL32 得到 GP 容錯,請確定目標函式宣告為 _stdcall,且它並沒有修改 DS、 ES、 FS、 SS、 EBP、 EBX、 ESI 或 EDI 暫存器。C + + 程式碼應該不會造成暫存器來進行修改,但應該仔細檢查組件語言程式碼。
  6. 如果您 Win16 架構目標函式會傳回不正確的位置請確定它是宣告,並且定義為 FAR。這是特別重要的小型模型 DLL ; 在中型及大型模型 DLL 的函式都預設 FAR。
  7. 如果您遇到 Win16 架構函式存取時超過 64K 的指標,當做參數 (也就是 thunked 指標) 傳入的資料中的 GP 容錯,您需要配置一個陣列磚塊式並排的選取器的 「 Microsoft 知識庫 」 中下列文所述:
    132005不完整的 DOCERR: AllocSelector & FreeSelector 說明文件
    Win16 一邊 thunked 的指標永遠包含單一選取器中的這表示您不能做巨大的指標的 64 K 的限制。存取 Win16 架構目標 DLL-但是只有如果它建立的磚塊式並排的選取器來參考它,陣列,而且它會使用極大的指標變數來存取資料的指標位址的資料整個原始範圍。
  8. 請確定您只使用 thunked 的指標 Thunk 內容中。只要將 Thunk 傳回,會釋放由 Thunk 編譯器使用的配置由 Win16 目標選取器。
  9. 將中斷點放在目標函式,以確定您正在擷取到它們的開頭。如果您是和已偵錯獨立的 Thunk 目標側邊,錯誤造成目標內,機會是很好的目標是做不能在一個 Thunk 中完成的事,或參考不存在的記憶體。請參閱步驟 7 和 8。

屬性

文章編號: 133722 - 上次校閱: 2005年7月11日 - 版次: 2.3
這篇文章中的資訊適用於:
  • Microsoft Platform Software Development Kit-January 2000 Edition?應用於:
    • Microsoft Windows 95
    • Microsoft Windows 98 Standard Edition
    • Microsoft Windows Millennium Edition
關鍵字:?
kbmt kbhowto kbkernbase kbprogramming KB133722 KbMtzh
機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:133722
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。

提供意見

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com