CodeView シンボルレコード

はじめに

このドキュメントでは、LLVMが理解するさまざまな CodeView シンボルレコードの使用法とシリアル化形式について説明します。 CodeView タイプレコードと同様に、最新の C++ ツールチェーンによって生成される重要なタイプのみを説明します。

レコードのカテゴリ

シンボルレコードは、タイプレコードと1つの大きな類似点を共有しています。これらは同じレコードプレフィックスで始まり、これについては再説明しません (説明については前のリンクを参照してください)。この結果、シンボルレコードのシーケンスは、タイプレコードを処理するコードとほぼ同じコードで処理できます。シンボルレコードとタイプレコードの間には、いくつかの重要な違いがあります。

  • シンボルレコードは、PDB 公開シンボルストリームPDB グローバルシンボルストリーム、およびモジュール情報ストリームにのみ出現します。

  • タイプレコードは、TPI & IPI ストリームにのみ出現します。

  • タイプはタイプインデックスを介して他のCodeViewレコードから参照されますが、シンボルレコードは、それが含まれるストリーム内のレコードのバイトオフセットによって参照されます。

  • タイプはタイプ (タイプインデックス経由) を参照でき、シンボルはタイプ (タイプインデックス経由) とシンボル (オフセット経由) の両方を参照できますが、タイプがシンボルを参照することは決してありません。

  • タイプにあるようなリーフレコードメンバーレコードという概念はありません。すべてのシンボルレコードは、それ自身の長さを記述します。

  • 特定の特別なシンボルレコードは「スコープ」を開始します。これらのレコードでは、次のS_ENDレコードまでのすべての後続のレコードが、このシンボルレコードの「子」になります。たとえば、特定の関数を記述するシンボルレコードが与えられた場合、この関数のすべてのローカル変数は、対応するS_ENDレコードまで、その関数の後に現れます。

最後に、シンボルレコードには、PDBファイル内で出現することが許可されている場所によってグループ化された、3つの一般的なカテゴリがあります。公開シンボル (公開ストリームにのみ出現)、グローバルシンボル (グローバルストリームにのみ出現)、およびモジュールシンボル (モジュール情報ストリームに出現) です。

公開シンボル

公開シンボルは、DWARFの.debug_pubnamesに相当する CodeView です。マングルされた名前を持つプログラム内のすべての関数または変数に対して、1つの公開シンボルレコードがあります。これらのレコードを含む公開ストリームには、マングルされた名前でレコードをすばやく見つけることができるハッシュテーブルが追加で含まれています。

S_PUB32 (0x110e)

公開シンボルには、マングルされた名前、それがどのような種類のシンボルであるか (例: 関数、変数) を示すフラグ、およびシンボルのアドレスを記述するS_PUB32という1つのタイプのみがあります。DBI ストリームセクションマップサブストリームを参照して、このアドレスがどのモジュールに対応するかを判断できます。そこから、そのモジュールのモジュールデバッグストリームを参照して、指定されたアドレスを持つシンボルの完全な情報を特定できます。

グローバルシンボル

プログラム内のすべての外部リンケージを持つシンボルに対して1つの公開シンボルがあるのに対し、プログラム内のすべてのリンケージ (内部リンケージを含む) を持つシンボルに対して1つのグローバルシンボルがあります。その結果、内部リンケージを持つシンボルはマングルを持つ必要がない場合があり、アドレスを持つ必要もない可能性があるため、グローバルシンボルはマングルされた名前またはアドレスを記述しません。したがって、すべてのグローバルシンボルは、モジュール/オフセットの組み合わせを介して完全なシンボルレコードを直接参照します。

公開シンボルと同様に、すべてのグローバルシンボルは単一のグローバルストリームに含まれており、完全修飾名をグローバルストリーム内の対応するレコードにマッピングするハッシュテーブルが含まれています (前述のように、これにより、対応するモジュールシンボルストリーム内の完全なレコードを見つけることができます)。

この設計の帰結および制限は、コンパイラがエミットすることにしたものの正確なテキスト一致の完全修飾名以外のものによるプログラム全体のルックアップが非実用的であるということです。これは、特定のスコープ (O(1) スコープを含む) 内のベース名による O(1) ルックアップが必ずしも必要ではない DWARF とは異なり、少なくとも特定のスコープ内では O(n) アクセスが可能です。

重要

正確なテキスト一致の完全修飾名以外の名前によるプログラム全体のルックアップは不可能です。

S_GDATA32

S_GTHREAD32 (0x1113)

S_PROCREF (0x1125)

S_LPROCREF (0x1127)

S_GMANDATA (0x111d)

モジュールシンボル

S_END (0x0006)

S_FRAMEPROC (0x1012)

S_OBJNAME (0x1101)

S_THUNK32 (0x1102)

S_BLOCK32 (0x1103)

S_LABEL32 (0x1105)

S_REGISTER (0x1106)

S_BPREL32 (0x110b)

S_LPROC32 (0x110f)

S_GPROC32 (0x1110)

S_REGREL32 (0x1111)

S_COMPILE2 (0x1116)

S_UNAMESPACE (0x1124)

S_TRAMPOLINE (0x112c)

S_SECTION (0x1136)

S_COFFGROUP (0x1137)

S_EXPORT (0x1138)

S_CALLSITEINFO (0x1139)

S_FRAMECOOKIE (0x113a)

S_COMPILE3 (0x113c)

S_ENVBLOCK (0x113d)

S_LOCAL (0x113e)

S_DEFRANGE (0x113f)

S_DEFRANGE_SUBFIELD (0x1140)

S_DEFRANGE_REGISTER (0x1141)

S_DEFRANGE_FRAMEPOINTER_REL (0x1142)

S_DEFRANGE_SUBFIELD_REGISTER (0x1143)

S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE (0x1144)

S_DEFRANGE_REGISTER_REL (0x1145)

S_LPROC32_ID (0x1146)

S_GPROC32_ID (0x1147)

S_BUILDINFO (0x114c)

S_INLINESITE (0x114d)

S_INLINESITE_END (0x114e)

S_PROC_ID_END (0x114f)

S_FILESTATIC (0x1153)

S_LPROC32_DPC (0x1155)

S_LPROC32_DPC_ID (0x1156)

S_CALLEES (0x115a)

S_CALLERS (0x115b)

S_HEAPALLOCSITE (0x115e)

S_INLINEES (0x1168)

モジュール情報ストリームまたはグローバルストリームのいずれか/両方に入れることができるシンボル

S_CONSTANT (0x1107)

S_UDT (0x1108)

S_LDATA32 (0x110c)

S_LTHREAD32 (0x1112)

S_LMANDATA (0x111c)

S_MANCONSTANT (0x112d)