リンカーによってフルサイズの .pdb または .dbg シンボル ファイルがビルドされると、 プライベート シンボル データ と パブリック シンボル テーブルという 2 つの異なる情報コレクションが含まれます。 これらのコレクションは、含まれる項目の一覧と、各項目に関する情報が異なります。
プライベート シンボル データには、次の項目が含まれます。
Functions
グローバル変数
ローカル変数
ユーザー定義の構造体、クラス、およびデータ型に関する情報
ソース ファイルの名前と、各バイナリ命令に対応するそのファイル内の行番号
パブリック シンボル テーブルに含まれる項目の数が少なくなります。
関数 ( static として宣言された関数を除く)
extern として指定されたグローバル変数 (および複数のオブジェクト ファイルに表示されるその他のグローバル変数)
一般に、パブリック シンボル テーブルには、ソース ファイル間でアクセスできる項目が正確に含まれています。 静的関数、1 つのソース ファイル内でのみグローバルな変数、ローカル変数など、1 つのオブジェクト ファイルにのみ表示される項目は、パブリック シンボル テーブルには含まれません。
これら 2 つのデータコレクションは、各項目に含まれる情報も異なります。 通常、 プライベート シンボル データに含まれる項目ごとに、次の情報が含まれます。
アイテムの名前
仮想メモリ内の項目のアドレス
各変数、構造体、および関数のデータ型
各関数のパラメーターの型と名前
各ローカル変数のスコープ
各ソース ファイルの各行に関連付けられているシンボル
スタックへのアクセスに使用される各関数のフレーム ポインター省略 (FPO) レコード
一方、 パブリック シンボル テーブルには、それに含まれる各項目に関する次の情報のみが格納されます。
項目の名前。
モジュールの仮想メモリ空間内の項目のアドレス。 関数の場合、これはエントリ ポイントのアドレスです。
各関数のフレーム ポインター省略 (FPO) レコード。
装飾と呼ばれる記号プレフィックス/サフィックスを含めることができます。
パブリック シンボル データは、2 つの方法でプライベート シンボル データのサブセットと考えることができます。これには、項目の短いリストが含まれます。また、各項目に関する情報も少なくなります。 たとえば、パブリック シンボル データにはローカル変数がまったく含まれていません。
各ローカル変数は、アドレス、データ型、およびスコープを持つプライベート シンボル データにのみ含まれます。 一方、関数はプライベート シンボル データとパブリック シンボル テーブルの両方に含まれますが、プライベート シンボル データには関数名、アドレス、FPO レコード、入力パラメーター名と型、出力型が含まれますが、パブリック シンボル テーブルには関数名、アドレス、および FPO レコードだけが含まれます。
プライベート シンボル データとパブリック シンボル テーブルには、もう 1 つの違いがあります。 パブリック シンボル テーブル内の項目の多くは、プレフィックス、サフィックス、またはその両方で 修飾された 名前を持ちます。 これらの装飾は、C コンパイラ、C++ コンパイラ、および MASM アセンブラーによって追加されます。 一般的なプレフィックスには、一連のアンダースコアまたは 文字列__imp_ (インポートされた関数を指定する) が含まれます。 一般的なサフィックスには、1 つ以上のアット サイン ( @ ) の後にアドレスまたはその他の識別文字列が含まれます。 これらの装飾は、関数名またはグローバル変数名が異なるモジュール間で繰り返される可能性があるため、シンボルのあいまいさを解消するためにリンカーによって使用されます。 これらの装飾は、パブリック シンボル テーブルがプライベート シンボル データのサブセットであるという一般的な規則の例外です。
完全なシンボル ファイルと削除されたシンボル ファイル
完全なシンボル ファイルには、プライベート シンボル データとパブリック シンボル テーブルの両方が含まれています。 この種のファイルは プライベート シンボル ファイルと呼ばれることもありますが、このようなファイルにはプライベートシンボルとパブリックシンボルの両方が含まれているため、この名前は誤解を招くものです。
削除されたシンボル ファイルは、パブリック シンボル テーブルのみを含む小さなファイルです。場合によっては、パブリック シンボル テーブルのサブセットのみを含みます。 このファイルは、 パブリック シンボル ファイルと呼ばれることもあります。
完全なシンボルファイルと縮小されたシンボルファイルの作成
Visual Studio を使用してバイナリをビルドする場合は、完全または削除されたシンボル ファイルを作成できます。 削除されたシンボルの構築の詳細については、「 /PDBSTRIPPED (プライベート シンボルの削除)」を参照してください。
BinPlace ツールを使用すると、完全なシンボル ファイルから削除されたシンボル ファイルを作成できます。 最も一般的な BinPlace オプション (-a -x -s -n) を使用すると、削除されたシンボル ファイルは -s スイッチの後に一覧表示されるディレクトリに配置され、完全なシンボル ファイルは -n スイッチの後に一覧表示されるディレクトリに配置されます。 BinPlace がシンボル ファイルを削除すると、削除された完全なバージョンのファイルには、同一の署名とその他の識別情報が提供されます。 これにより、デバッグにいずれかのバージョンを使用できます。 BinPlace の詳細については、「 BinPlace」を参照してください。
PDBCopy ツールを使用すると、プライベート シンボル データを削除することで、完全なシンボル ファイルから削除されたシンボル ファイルを作成できます。 PDBCopy では、パブリック シンボル テーブルの指定されたサブセットを削除することもできます。 詳細については、「 PDBCopy」を参照してください。
SymChk ツールを使用すると、シンボル ファイルにプライベート シンボルが含まれているかどうかを判断できます。 詳細については、 SymChk を参照してください。
デバッガーでのパブリック シンボルとプライベート シンボルの表示
WinDbg、KD、または CDB を使用してシンボルを表示できます。 これらのデバッガーのいずれかが完全なシンボル ファイルにアクセスできる場合、プライベート シンボル データに一覧表示されている情報と、パブリック シンボル テーブルに一覧表示されている情報の両方が含まれます。 パブリック シンボル データには、シンボル装飾が含まれています。
プライベート シンボルにアクセスする場合、これらのシンボルはパブリック シンボル テーブルに含まれていないため、プライベート シンボル データが常に使用されます。 これらの記号は装飾されません。
.symopt (シンボル オプションの設定) コマンドを使用すると、デバッガーでパブリック シンボルとプライベート シンボルを使用する方法を決定するシンボル オプションを制御できます。 たとえば、このコマンドはシンボルデバッグ情報をオンにします。
.symopt+ 0x80000000
次のオプションは、デバッガーでのパブリック シンボルとプライベート シンボルの使用方法を変更します。
SYMOPT_UNDNAME オプションがオンの場合、パブリック シンボルの名前が表示されるときに装飾は含まれません。 さらに、シンボルを検索する場合、装飾は無視されます。 このオプションをオフにすると、パブリック シンボルを表示するときに装飾が表示され、装飾が検索で使用されます。 プライベート シンボルは、どのような状況でも装飾されることはありません。 このオプションは、すべてのデバッガーで既定でオンになっています。
SYMOPT_PUBLICS_ONLY オプションがオンの場合、プライベート シンボル データは無視され、パブリック シンボル テーブルのみが使用されます。 このオプションは、すべてのデバッガーで既定でオフになっています。
SYMOPT_NO_PUBLICS オプションがオンの場合、パブリック シンボル テーブルは無視され、検索とシンボル情報はプライベート シンボル データのみを使用します。 このオプションは、すべてのデバッガーで既定でオフになっています。
SYMOPT_AUTO_PUBLICS オプションがオン (および SYMOPT_PUBLICS_ONLY と SYMOPT_NO_PUBLICS の両方がオフ) の場合、プライベート シンボル データで最初のシンボル検索が実行されます。 目的のシンボルが見つかった場合、検索は終了します。 そうでない場合は、パブリック シンボル テーブルが検索されます。 パブリック シンボル テーブルにはプライベート データ内のシンボルのサブセットが含まれるため、通常、この結果、パブリック シンボル テーブルは無視されます。
SYMOPT_PUBLICS_ONLY、SYMOPT_NO_PUBLICS、およびSYMOPT_AUTO_PUBLICSのオプションがすべてオフの場合、シンボルが必要されるたびにプライベート シンボル データとパブリック シンボル テーブルの両方が検索されます。 ただし、両方の場所で一致が見つかった場合は、プライベート シンボル データ内の一致が使用されます。 したがって、このインスタンスの動作は、SYMOPT_AUTO_PUBLICSがオンの場合と同じですが、SYMOPT_AUTO_PUBLICSを使用するとシンボル検索が若干高速になる可能性があります。
コマンド x (シンボルの検査) を 3 回使用する例を次に示します。 初回は既定のシンボル オプションが使用されるため、情報はプライベート シンボル データから取得されます。 これには、配列 typingString のアドレス、サイズ、およびデータ型に関する情報が含まれていることに注意してください。 次に、コマンド .symopt+ 4000 が使用され、デバッガーはプライベート シンボル データを無視します。 x コマンドを再度実行すると、パブリック シンボル テーブルが使用されます。今回は、typingString のサイズとデータ型の情報はありません。 最後に、コマンド .symopt- 2 を使用すると、デバッガーに装飾が追加されます。 この最後の時刻に x コマンドを実行すると、関数名の修飾バージョン (_typingString) が表示されます。
0:000> x /t /d *!*typingstring*
00434420 char [128] TimeTest!typingString = char [128] ""
0:000> .symopt+ 4000
0:000> x /t /d *!*typingstring*
00434420 <NoType> TimeTest!typingString = <no type information>
0:000> .symopt- 2
0:000> x /t /d *!*typingstring*
00434420 <NoType> TimeTest!_typingString = <no type information>
DBH ツールを使用したパブリック シンボルとプライベート シンボルの表示
シンボルを表示するもう 1 つの方法は、 DBH ツールを使用することです。
/?
オプションを使用してヘルプ オプションを表示します。
C:\Program Files (x86)\Windows Kits\10\Debuggers\x64>dbh /?
dbh dbghelp shell
usage: dbh [-n] [-c] [-d] [-?] [-??] [-p] [targetmodule] [command]
[-n] display noisy symbol spew
[-d] use decorated publics
[-p:XXXX] attaches to process ID XXXX
[-s:SSSS] set symbol path to SSSS
[-c] callbacks return false
[targetmodule] load symbols for specified module
[command] execute command and exit
[-?] display these usage instructions
[-??] display detailed usage instructions
Tlist などのツールを使用してプロセス ID を一覧表示し、-p オプションを使用して既存のプロセスにアタッチします。
C:\Program Files (x86)\Windows Kits\10\Debuggers\x64>dbh -p:4308
DBH では、デバッガーと同じシンボル オプションが使用されます。 デバッガーと同様に、DBH は既定で SYMOPT_PUBLICS_ONLY と SYMOPT_NO_PUBLICS をオフのままにし、既定で SYMOPT_UNDNAME と SYMOPT_AUTO_PUBLICS をオンにします。 これらの既定値は、コマンド ライン オプションまたは DBH コマンドによってオーバーライドできます。
DBH コマンド 加算子 414fe0 を 3 回使用する例を次に示します。 初回は既定のシンボル オプションが使用されるため、情報はプライベート シンボル データから取得されます。 これには、関数 fget のアドレス、サイズ、およびデータ型に関する情報が含まれていることに注意してください。 次に、コマンド symopt +4000 が使用され、DBH はプライベート シンボル データを無視します。 addr 414fe0 が再度実行されると、パブリック シンボル テーブルが使用されます。今回は、関数 fget のサイズとデータ型の情報はありません。 最後に、コマンド symopt -2 が使用され、DBH に装飾が含まれます。 この最終時刻に addr 414fe0 を実行すると、_fgets関数名の修飾バージョンが表示されます。
pid:4308 mod:TimeTest[400000]: addr 414fe0
fgets
name : fgets
addr : 414fe0
size : 113
flags : 0
type : 7e
modbase : 400000
value : 0
reg : 0
scope : SymTagNull (0)
tag : SymTagFunction (5)
index : 7d
pid:4308 mod:TimeTest[400000]: symopt +4000
Symbol Options: 0x10c13
Symbol Options: 0x14c13
pid:4308 mod:TimeTest[400000]: addr 414fe0
fgets
name : fgets
addr : 414fe0
size : 0
flags : 0
type : 0
modbase : 400000
value : 0
reg : 0
scope : SymTagNull (0)
tag : SymTagPublicSymbol (a)
index : 7f
pid:4308 mod:TimeTest[400000]: symopt -2
Symbol Options: 0x14c13
Symbol Options: 0x14c11
pid:4308 mod:TimeTest[400000]: addr 414fe0
_fgets
name : _fgets
addr : 414fe0
size : 0
flags : 0
type : 0
modbase : 400000
value : 0
reg : 0
scope : SymTagNull (0)
tag : SymTagPublicSymbol (a)
index : 7f
追加情報
シンボルの詳細については、「 シンボルの構文とシンボルの一致、 シンボル オプション、 シンボルの状態の省略形 と 遅延シンボルの読み込み」を参照してください。