CodeView 符號記錄¶
簡介¶
本文檔描述 LLVM 理解的各種 CodeView 符號記錄的使用方式和序列化格式。 就像CodeView 類型記錄一樣,我們僅描述現代 C++ 工具鏈產生的重要類型。
記錄類別¶
符號記錄與類型記錄有一個主要的相似之處:它們都以相同的記錄前綴開始,我們將不再重複描述(請參考先前的連結以取得描述)。 因此,處理符號記錄序列可以使用與處理類型記錄大致相同的程式碼。 符號記錄和類型記錄之間存在幾個重要的差異
類型記錄僅出現在TPI & IPI 流中。
雖然類型是從其他 CodeView 記錄透過類型索引引用的,但符號記錄是透過記錄在其中出現的流中的位元組偏移量引用的。
類型可以參考類型(透過類型索引),符號可以參考類型(透過類型索引)和符號(透過偏移量),但類型永遠不能參考符號。
某些特殊的符號記錄會開始一個「範圍」。 對於這些記錄,所有後續記錄直到下一個
S_END
記錄都是此符號記錄的「子項」。 例如,給定一個描述特定函式的符號記錄,則此函式的所有區域變數都將出現在函式之後,直到對應的S_END
記錄。
最後,符號記錄有三個一般類別,按它們在 PDB 檔案中合法出現的位置分組。 公開符號(僅出現在公開流中)、全域符號(僅出現在全域流中)和模組符號(出現在模組資訊流中)。
公開符號¶
公開符號是 CodeView 中 DWARF .debug_pubnames
的等效物。 程式中每個具有 mangled 名稱的函式或變數都有一個公開符號記錄。公開流(包含這些記錄)還包含一個雜湊表,可讓您透過 mangled 名稱快速找到記錄。
S_PUB32 (0x110e)¶
只有一種公開符號類型,即 S_PUB32
,它描述了一個 mangled 名稱、一個指示符號類型的標誌(例如函式、變數)以及符號的位址。 可以查詢 DBI 流的區段映射子流,以確定此位址對應於哪個模組,然後可以查詢該模組的模組偵錯流,以找到具有給定位址的符號的完整資訊。
全域符號¶
雖然每個具有外部連結的符號都有一個公開符號,但程式中每個具有連結(包括內部連結)的符號都有一個全域符號。 因此,全域符號不描述 mangled 名稱或位址,因為具有內部連結的符號不必進行任何名稱修飾,也可能沒有位址。 因此,所有全域符號都只是透過模組/偏移量組合直接參考完整的符號記錄。
與公開符號類似,所有全域符號都包含在單個全域流中,該流包含一個雜湊表,將完全限定名稱映射到全域流中的對應記錄(如前所述,然後包含允許您在對應的模組符號流中找到完整記錄的資訊)。
請注意,這種設計的一個後果和限制是,除了編譯器決定發出的任何內容的完全符合文本匹配的完全限定名稱之外,對名稱進行全程式查找是不切實際的。 這與 DWARF 不同,在 DWARF 中,即使我們不一定在給定範圍內(包括 O(1) 範圍)按基本名稱進行 O(1) 查找,但我們至少在給定範圍內具有 O(n) 存取權。
重要
除了完全符合文本匹配的完全限定名稱之外,不可能對名稱進行全程式查找。