先不管什麼是符號文件,先看看在沒有符號文件支持時的情況,下面是VC8.0在沒有符號文件支撐時的一個調用堆棧
> DllTwo.dll!003d1cde() [下面的框架可能不正確和/或缺失,沒有爲 DllTwo.dll 加載符號] MapTest.exe!004017f5() MapTest.exe!00401169() kernel32.dll!_BaseProcessStart@4() + 0x23 字節 |
下面是加載了PDB文件後的堆棧情況:
> DllTwo.dll!CrashFun() 行42 + 0x3 字節 C++ MapTest.exe!wmain(int argc=1, wchar_t * * argv=0x00414c38) 行17 C++ MapTest.exe!__tmainCRTStartup() 行594 + 0x17 字節 C kernel32.dll!_BaseProcessStart@4() + 0x23 字節 |
有沒有發現最開始的稀奇古怪的十六進制符號都變成了函數名?這就是符號文件的魔力。
這裏所說的“符號”就是“調試符號”,從軟件調試的角度來講,調試符號是將被調試的二進制程序和源程序聯繫起來的橋樑,很多重要的調試功能,例如源代碼調試、棧回溯(如上表中的示例棧)、按名稱顯示函數或者變量名稱等,都需要調試符號的支撐才能實現。
從編譯器的角度來看,調試符號是編譯器把源代碼編譯成二進制代碼的過程中,爲支持調試而摘錄的調試信息,這些信息描述的目標對象主要包括:變量、變量類型、函數、標號(Label)、源代碼行等。編譯器或者其他專門的工具把這些信息收集提煉後輸出到專門的文件中存儲,這樣的文件就是符號文件。
微軟的編譯器默認把這些符號信息保存在PDB文件中。PDB文件,是Program Database的縮寫,從名字就知道,它專門用以描述(源)程序的數據庫。其中的主要內容包括:
(1)代碼所定義Class的類名,類成員的名字和類型;
(2) 變量的名字和類型;
(3) 函數的名字,函數的所有參數的名字和類型以及返回值。
PDB文件是微軟定義的一種格式,微軟並沒有公開此文件的格式,但是提供了一組接口來訪問此文件,即DIA(Microsoft Debug Interface Acess)。下面是有人開發一個用來查看PDB文件內容的一個工具的截圖:
有了此PDB文件,當在調試器中試圖讀取某個內存地址的時候,調試器會嘗試在對應的PDB文件中搜索,看這個內存地址是否有對應的符號。如果能夠找到,調試器就會把這個符號顯示出來,從而大大方便開發人員的調試。因此,在軟件調試過程中,PDB文件是最爲重要的信息,它比上面所說的map文件要重要的多。不過要使用PDB文件,需要專門的調試器的支持纔行,例如VC、Windbg。