SymGetLineFromAddrが示す行数

久しぶりにWin32API関連の覚書です。

Cで呼び出し履歴(コールスタック)の取得サンプルを漁ると、こんなのをよく見かけました。
※これ以降のコードは超概略記述なので、このままコピペしても動作しません。

		IMAGEHLP_LINE64 line = { sizeof(IMAGEHLP_LINE64) };
		SymFromAddr(hProcess, address, &disp, symbol);
		SymGetLineFromAddr64(hProcess, symbol->Address, &dispLine, &line64);
		
		printf("filename=%s, line=%d\n", line64.FileName, line64.LineNumber);

最初、コピペで実行してみたのですが、どうも呼び出し元の行の位置がずれているのです。例えば、

void GetCallStack()
{
		IMAGEHLP_LINE64 line = { sizeof(IMAGEHLP_LINE64) };
		SymFromAddr(hProcess, address, &disp, symbol);
		SymGetLineFromAddr64(hProcess, symbol->Address, &dispLine, &line64);
		
		printf("filename=%s, line=%d\n", line64.FileName, line64.LineNumber);
}

int main()
{
    Statement1;
    Statement2;
    Statement3;
    GetCallStack();
}

と組んでみたときに、呼び出し元は15行目なので「line=15」と出力してほしいのですが、「line=11」と出力されます。

結論は、SymFromAddr()で取得したDisplacement(変位)をSymGetLineFromAddr64()のアドレスに加えないといけないのです。

		SymFromAddr(hProcess, address, &disp, symbol);
		SymGetLineFromAddr64(hProcess, symbol->Address + disp, &dispLine, &line64);

あと、Release版のときは、コンパイルオプションに「/Od」(最適化を無効にする)を指定しないとDebug版と同様な綺麗な呼び出し履歴が取得できないので注意です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください