一 PDB文件
PDB:Program Debug Database(程序調試數據庫)文件,是用來幫助軟件的調試的。
PDB(程序調試數據庫)文件保持着調試和項目狀態信息,從而可以對程序的調試配置進行增量鏈接。當用 /ZI 或 /Zi 編譯 C/C++ 程序時或用 /debug 編譯 Visual Basic/C# 程序時將創建 PDB 文件。
在 Visual C++ 中,/Fd 選項用於命名由編譯器創建的 PDB 文件。當在 Visual Studio 中使用向導創建項目時,/Fd 選項將被設置以創建名為 project.PDB 的 PDB。 如果使用生成文件創建 C/C++ 應用程序,並指定 /ZI 或 /Zi 而不指定 /Fd 時,則最終將生成兩個 PDB 文件:
VC70.PDB(更籠統地說就是 VCx0.PDB,其中 x 表示 Visual C++ 的版本。)該文件存儲各個 OBJ 文件的所有調試信息並與項目生成文件駐留在同一個目錄中。
project.PDB 該文件存儲 .exe 文件的所有調試信息。對於本機代碼,它駐留在 \debug 子目錄中。對於托管代碼,它駐留在 \WINDEBUG 子目錄中。
在開始前,我們先定義2個術語:private build, 用來表示在開發人員自己機器上生成的build;public build,表示在公用的build機器上生成的build。private build相對來說比較簡單,因為PDB和binay在相同的地方,通常地我們遇到的問題都是關於public build。
所有的的開發人員需要知道的最重要的事情是”PDB文件跟源代碼同樣的重要“, 沒有PDB文件,你甚至不能debugging。對於public build,需要symbol server存儲所有的PDB,然后當用戶報告錯誤的時候,debugger才可以自動地找到binay相應的PDB文件
二 PDB文件的內容
PDB不是公開的文件格式,但是Microsoft提供了API來幫助從PDB中獲取數據。
Native C++ PDB包含了如下的信息:
* public,private 和static函數地址;
* 全局變量的名字和地址;
* 參數和局部變量的名字和在堆棧的偏移量;
* class,structure 和數據的類型定義;
* Frame Pointer Omission 數據,用來在x86上的native堆棧的遍歷;
* 源代碼文件的名字和行數;
三 PDB如何工作
當你加載一個模塊到進程的地址空間的時候,debugger找到相應的PDB文件。第一個毫無疑問就是文件的名字,如果加載 zzz.dll,debugger則查找zzz.pdb文件。在文件名字相同的情況下debugger還通過嵌入到PDB和binay的GUID來確保 PDB和binay的真正的匹配。 即使沒有任何的代碼修改,昨天的binay和今天的PDB是不能匹配的。
在VisualStudio中的modules窗口的symbol file列可以查看PDB的load順序。第一個搜索的路徑是binary所在的路徑,如果不在binary所在的路徑,則查找binary中hardcode記錄的build目錄,例如obj\debug\*.pdb, 如果以上兩個路徑都沒有找到PDB,則根據symbol server的設置,在本地的symbol server的cache中查找,如果在本地的symbol server的cache中沒有對應的PDB,則最后才到遠程的symbol server中查找。通過上面的查找順序我們可以看出為什么public build和private build的PDB查找不會沖突。
對於private build有時我們需要在別人的機器上debug的情況,需要將相應的PDB與binary一起拷貝,對於加入GAC的.NET的binary,需要將PDB文件拷貝到C:\Windows\assembly\GAC_MSIL\Example\1.0.0.0__682bc775ff82796a類似的binary所在的目錄。另一個變通的方法是定義環境變量DEVPATH,從而代替使用命令GACUTIL將binary放入GAC中。在定義DEVPATH后,只需要將binary和PDB放到DEVPATH的路徑,在DEVPATH下的binary相當於在GAC下。使用DEVPATH,首先需要創建目錄且對當前build用戶有寫權限,然后創建環境變量DEVPATH且值為剛才創建的目錄,然后在web.config,app.config或machine.config中開啟development模式,啟動對DEVPATH的使用
<configuration>
<runtime>
<developmentMode developerInstallation="true"/>
</runtime>
</configuration>
在你打開了development模式后,如果DEVPATH沒有定義或路徑不存在的話會導致程序啟動時異常"Invalid value for registry"。而且如果在machine.config中開啟DEVPATH的使用會影響其他的所有的程序,所以要慎重使用machine.config。
最后開發人員需要知道的是源代碼信息是如何存儲在PDB文件中的。對於public builds,在運行source indexing tool后,版本控制工具將代碼存儲到你設置的代碼cache中。對於private builds,只是存儲了PDB文件的全路徑,
例如在c:\foo下的源文件mycode.cpp,
在pdb文件中存儲的路徑為c:\foo\mycode.cpp。
對於private builds可以使用虛擬盤來增加PDB對絕對路徑的依賴