2016-02-14

UNIX V6でcdbを使う

UNIX V6にはcdbというデバッガがついています。今日のデバッガからみると、かなりプリミティブです。マニュアルcdb(I)は2ページしかありませんし、あまり機能が充実しているとは言えませんが、使い慣れればデバッグに活躍するでしょう。

以下のプログラムを対象にしてcdbの使い方を紹介してみます。
char msg[]  "Hello world";

func(p)
char *p;
{
    printf("%s\n", p);
}

main()
{
    int i;

    for (i = 0; i < 10; i++)
        func(msg);
}
今日ではデバッグする時にはccに「-g」オプションをつけますが、当時のccには特別なオプションは要りません。実行ファイルがa.outであれば、cdbはデフォルトで読み込みます。まずmain()にブレークポイントをかけて、実行してみます。
# cdb
main%b
%r
Breakpoint: main+4
さらにfunc()にもブレークポイントをかけて、一時停止している実行を再開します。
func%b
%c
Breakpoint: func+4
func()で実行が一時停止していますので、スタックトレースを見てみます。
$
Trace/BTP
 0: func(01232)
 1: main()
func()の引数pはスタック上に割り当てられています。その内容はmsg[]の先頭アドレスです。
func:p=
0177744
func:p/
01232
func:p"
Hello world
 func()の先頭から逆アセンブルしてみます。またレジスタの値も見てみます。
func,5?
func:   jsr     r5,csv
        mov     04(r5),(sp)
        mov     $msg+12,-(sp)
        jsr     pc,*$printf
        tst     (sp)+
$r
Trace/BTP
ps      0170004
pc      036     func+06
sp      0177730
r5      0177740
r4      0
r3      0
r2      0
r1      0
r0      034     func+04
ブレークポイントは関数の先頭にかけることが多いかもしれませんが、任意の位置にかけることもできます。ただし今日のデバッガのように親切ではないので、かけ間違えても何のメッセージも出ませんし、うまくブレークポイントにかからないかもしれません。
 func+12%b
cdbのコマンド体系は、UNIX V6にもうひとつあるデバッガdbに似ています。しかしdbにはデバッガを抜けるためのコマンドが用意されているのに、cdbにはありません。しかたないので^Dでcdbを抜けるしかありません。

cdb(I)には以下のような記述があります。当時のマシン環境の常識が分からないので、意味がよく理解できないのですが、「no advance planning is necessary to use it」とわざわざ断っているのは、当時のデバッグでは何か特別な「planning」が必要だったということなのでしょうか。
An important feature of cdb is that even in the interactive case no advance planning is necessary to use it; in particular it is not necessary to compile or load the program in any special way nor to include any special routines in the object file.

0 件のコメント:

コメントを投稿