unity3D:IL2CPP 內部構建 – 生成程式碼的除錯技巧
轉自:http://www.manew.com/thread-40379-1-1.html
在本文中,我們將探究一些程式碼除錯技巧,一些可以使IL2CPP生成的C++程式碼除錯更加容易的技巧。我們將瞭解如何設定斷點、檢視字串和使用者定義型別的內容、以及如何確定出現異常的位置。
當我們接觸到這些內容時,應該正在除錯由.NET IL程式碼建立的生成C++程式碼,因此除錯過程有可能不那麼令人滿意。但是通過一些除錯技巧,便有可能透徹的理解unity專案程式碼如何在實際目標裝置上執行(我們會在文章的末尾討論一些有關除錯託管程式碼的內容)。
同時,在專案中為生成程式碼做準備,以便其區別於該程式碼。通過Unity各個新版本,我們正在尋找一個方法使生成程式碼更好、更快、更小短。
設定
在本文中,我在OSX系統上使用unity 5.0.1p3。使用和有關生成程式碼的文章中相同的示例專案,但是此次使用IL2CPP指令碼後端為iOS目標建立示例專案。如上篇文章所述,在選擇“Development Player”的情況下建立專案,這樣il2cpp.exe便會生成C++程式碼,且生成的型別名稱和方法名稱以IL程式碼中的名稱為基礎。
Unity生成Xcode專案完成後,在Xcode中將其開啟(我的版本為6.3.1,任何更新版本都可使用),選擇目標裝置(iPad Mini 3,任何iOS裝置都可使用)並在Xcode中建立專案。
設定斷點
執行專案之前,首先在HelloWorld中Start的頂部設定斷點。正如前一篇文章中所見,在生成的C++程式碼中該方法名稱為HelloWorld_Start_m3。我們可以使用Cmd+Shift+O並鍵入該方法名稱,以便在Xcode中查詢,然後在此處設定斷點。
我們也可在Xcode中選擇Debug > Breakpoints > Create Symbolic Breakpoint,然後,用此方法設定斷點。
現在當我執行Xcode專案時,可以立刻看到在該方法開始的時候中斷。
如果我們知道方法名稱,則可在此類生成程式碼中用其他方法設定斷點。在Xcode中,也可在生成程式碼的某個檔案的具體行設定斷點。實際上所有的生成檔案都是Xcode專案的一部分。你可以在Classes/Native資料夾的Project Navigator中看到這些檔案。
檢視字串
在Xcode中有兩種方法可檢視IL2CPP字串的表示法。我們可以直接檢視字串儲存器,或者呼叫libil2cpp中某個字串的處理程式,將字串轉化成Xcode可以顯示的std::string。檢視名為 _stringLiteral1字串的值(劇透:內容為“Hello, IL2CPP!”)。
在帶內嵌Ctags的生成程式碼(或在Xcode中使用Cmd+Ctrl+J)中,我們可以跳轉至_stringLiteral1的定義並發現其型別為Il2CppString_14:
[AppleScript] 純文字檢視 複製程式碼 ?
01 02 03 04 05 06 07 08 09 10 |
struct
Il 2 CppString_ 14
{
Il 2 CppDataSegmentString
header;
int 32 _t
length;
uint 16 _t
chars[ 15 ];
} ;
|
實際上,IL2CPP中所有字串都如此顯示。我們可以在object-internals.h標頭檔案中找到Il2CppString的定義。在IL2CPP中,這些字串包括任何託管型別的標頭部分,Il2CppObject(通過Il2CppDataSegmentString定義型別訪問)後是4位元組長度,然後是雙位元組字元陣列。編譯時定義的字串,如 _stringLiteral1,以定長chars陣列結束,但是執行時產生的字串具有分配的陣列。字串中的字元編碼為UTF-16。
如果我們新增 _stringLiteral1到Xcode的監視視窗,我們可選擇View Memory of “_stringLiteral1”選項,以便檢視儲存器中字串的佈局。
然後在儲存器檢視器中,我們可以看到以下內容:
字串的頭成員為16位元組,因此將其跳過後,我們會發現四位元組的值為0x000E (14)。該範圍後的下一個位元組為字串0x0048 (‘H’) 的首位字元。因為每個字元為兩位元組寬度,但是該字串中所有字元僅匹配一個位元組寬度,所以在Xcode右側顯示這些字元且各字元中間以圓點隔開。字串內容仍清晰可見。該字串檢視方法確實有效,但難於檢視更加複雜的字串。
在Xcode中我們也可通過lldb命令提示符檢視字串內容。在使用libil2cpp時,utils/StringUtils.h資料頭會提供介面處理一些字串程式。特別是通過lldb命令提示符呼叫Utf16ToUtf8的方法。其介面如下所示:
[AppleScript] 純文字檢視 複製程式碼 ?
static
std : : string
Utf 16 ToUtf 8
( const
uint 16 _t *
utf 16 String ) ;
|
我們可以把C++裡的字串內容轉變成這種方式,將返回一個UTF-8編碼的std::string。然後,如果在lldb命令提示符中使用p命令,則可以列印字串內容。
[AppleScript] 純文字檢視 複製程式碼 ?
1 2 |
( lldb )
p il
|