D言語でスタックトレースを取ろうというものです。
shinichiro.hさんが作ったreflection.dに dmd の -g オプションを付けてコンパイルした際にexeファイルに格納されるデバッグ情報を元に、シンボル名、アドレス、ライン情報を取得する機能を追加し、さらにスタック情報を元にスタックトレースを取れるようにしたものです。
デバッグ情報を元にシンボル名などを取得しているため、mapファイル読み込みよりも高速な起動が実現できます。
デバッグ情報を読み込むには、PEヘッダ、.debugディレクトリ、codeviewフォーマットの解析が必要です。
現在デバッガを作ってちゃんとした行データを取得できるようにしています。
クラスのメソッドが呼ばれたときのスタック情報を見て、スタックトレースを実現しているため、メソッドのライン情報しか取れていません。戻りのアドレスも取れるのですが、表示していません。
クラスのメソッドが呼ばれたときのスタックのアドレスを見て、スタックトレース用のスタックの情報を消しています。そのため、ローカル変数の数によりスタックのアドレスが変ってしまうため、消すのに失敗することがあります。
dmd -g test.d reflection.d
コンパイル
gオプションをつけてコンパイルします。
dmd -g test.d reflection.d
実行
test
結果
error at test.C.go4(62) error at test.C.go6(68) at test.C.go5(65) error at test.C.go7(71) at test.C.go5(65) error at test.C.go8(77) error at test.C.go9(80) g3 ArrayBoundsError test.d(60) at test.C.go3(56) at test.C.go2(53) at test.C.go(50)
コンパイル
dmd -L/map test.d reflection.d
L/mapオプションをつけてコンパイルします。
実行
マップファイルを指定して実行します。若干起動に時間がかかりますが、linux等でも動きます。
test test.map
結果
error at test.C.go4 error at test.C.go6 at test.C.go5 error at test.C.go7 at test.C.go5 error at test.C.go8 error at test.C.go9 g3 ArrayBoundsError test.d at test.C.go3 at test.C.go2 at test.C.go
コンパイル
dmd test.d reflection.d
オプションをつけずコンパイルします。
実行
test
結果
error error error error error g3 ArrayBoundsError test.d
開発中
デバッガを作ってしまって、行番号とか完全に取ってしまおう作戦!!