2009-11-26[木] 〔D言語〕Ddbgの再コンパイル

Ddbg(Descent,CB)を使って変数表示がおかしくなるのは、 どうも Ddbgコマンドの lsv が使われた時みたい... なので、そこそこ状況限定されるから、なんとなくバグとれそうな 気がしてしまったで、 ソースのsvnリポジトリr1094 をみると実は公開exe(v.0.11.3)よりも新しいv0.12(2008-3-26)のソースがコミットされているようなのでした。 (コミットログにはbasic hardware breakpoint support-minor changesと)

で、とりあえず Ddbg をコンパイルしてみたのですが... そこはD言語、やっぱり泥沼にはまったのでした。

Ddbg 自体はD1で作られていて、 最新のD1でコンパイルしても今まで見過ごされていたバグが 検出される程度(すぐ修正可能)だったのですが、 問題は、bud とパーサージェネレートに使われてる Apaged.

budはエラーがでるため、apagedは配布サイトにソースしかないため、 ツール自体の再コンパイルを行ったのですが、まさにドツボ。
dmdのバージョンやtangoのバージョン等罠にはまりまくりで、最終的には断念。

結局、budについては、ソース構成割り出してバッチで処理, apagedに関してはふと apaged.exe を検索したらこちらで見つかったので それを用いることでなんとか.

ただ apaged 自体の文法に変更があったり、 ジェネレートされたルーチンの関数引数が変わってるため Ddbg側もそれに合わせて必要だったり、と結構疲れました.

あと win32 bindingも、今のdmdだと依存関係でひっかかり、ちょっと嫌な修正. udis86-1.4部分もたいしたことないけど (こいつも perl でソースジェネレートとかあって、それをさけるため) makefile若干弄ったりとか.


で、肝心の Ddbg lsv のバグですが、
ddbgcli.d の evalScopeSymbols() 内

StackSymbol[] locals_args = scope_sym.symbols.stack_symbols;
auto psym = cast(ProcedureSymbol)scope_sym;
if  ( psym !is null )
    locals_args ~= psym.arguments.stack_symbols;
foreach ( sym; locals_args.sort )
{

の部分で、関数内ローカル変数一覧に関数引数変数を追加して ソートし出力してるのですが、locals_args がコピーでなく実体 を指しているため、追加&ソートにより scope_sym.symbols.stack_symbols が 破壊されてしまっていたようです.
(main(char[][] args) { int i=0; ... } て感じに引数が中のローカル変数より 若い名前だと、デバッガの変数一覧で args が複数表示され他の変数がなくなる、 という状態)

とりあえず .dup つけて

StackSymbol[] locals_args = scope_sym.symbols.stack_symbols.dup;

で直るよう.
(.dup抜けって D言語の落とし穴の代表例の一つだよなあ、って気も)

弄った Ddbg をさらしておきます.

[download]

※どうも元配布のDdbg.exeは実行ファイル圧縮されているぽくexe小さいのですが、これはそんなことしていないので、ちょっと太めです.


ついでにbudのバグもメモ.

文字列インポートとしての import("file.txt") に未対応のよう.

source.d の void doImport (in string pFileText, inout int pPos) 中の

bool	first = true;                             //@@@
while ((lSavedPos = pPos,
        lCurrentToken = GetNextToken (pFileText, pPos)) !is null
           && (lCurrentToken != ";"))
{
    if ( lCurrentToken == "(" && first) return;   //@@@
    first = false;                                //@@@
    if ( lCurrentToken == ",")

のwhile付近に //@@@ の処理を追加すればとりあえずなんとかなるぽい.
(あとbuild.d (1450) のreturnの戻り値不要)

(自分のコンパイルしたexeを使って出るエラーの原因が不明なんでexe無)


と書いててて思い出した.

dmd自体の仕様変更かバグかしらないけど、 ddbg の再コンパイルではまった件として、-Jsrc 状態で import("cli\ddbg_help.txt") が使われてもソース無いって起こられてた.
とりあえず -Jsrc\cli にして import("ddbg_help.txt") にすることで回避.