C の API、メモリ配置、gdb と lldb

Menu


ls -la に相当するプログラムを書く

opendir と fstat に相当するAPI を用いて、(C / C++ / Rust / Go ) で ls -la に相当するプログラム書く。

           dirp = opendir(".");
           if (dirp == NULL)
                   return (ERROR);
           len = strlen(name);
           while ((dp = readdir(dirp)) != NULL) {
                   if (dp->d_namlen == len && strcmp(dp->d_name, name) == 0) {
                           (void)closedir(dirp);
                           return (FOUND);
                   }
           }
           (void)closedir(dirp);
           return (NOT_FOUND);

プログラムを作成する cmake 用の CMakeLists.txt を作成する

作成時の command sequence を示せ

実行結果を示せ。


ls -laR に相当するプログラムを書く

再帰的に directory をたどるプログラムを書く。

どこまで深くたどったかを DIR * stack に取る。stack の深さは最初10とする。必要に応じて stack を realloc で拡張するコードを入れる。

    cf . telldir を使う方が使用するメモリは少なくなるはずだが…


DIR と struct stat はどこで定義されている?

clang -E を使って、その構造体の定義を探しだそう。

    ファイル名と、その場所を探しだす


FILE 構造体

    file descriptor はどのに格納されているか。
    file buffer はどこにあるか。

cf. lldb on OS X

 p *((FILE*)__stdoutp)    


debugger の操作

以下を gdb ( on Linux) と lldb ( on Mac OS X) について、それぞれ調べよ。


基本的な動作

    break point を設定して readdir しているところで 止める
    step 実行する
    continue する
    break point を解除する


ポインタの復習

stack の深さ3で止まるようにデバッガを設定する。(条件 break point )

自分で作ったstackのアドレスを表示する。

自分で作ったstackの中にあるDIRへのポインタを表示する。

自分で作ったstackの中にあるDIRの構造体を表示する。


ポインタの演算

stack に積まれているDIRをすべて表示してみる。

    配列を使って表示する       p stack[0]
    ポインタを使って表示する   p stack-1

の両方がある。

lldb/gdb で、演算している部分の命令を示せ。(演算が省略される場合もある) dissas などのコマンドを使う。


dirp

dirp は再帰的な表示の間で複数作られて、様々な値を取る。これを調べて表とグラフにせよ。

    表は LaTeX のコマンドを生成することにより作成する
    グラフは gnuplot を使う

どうして、このようなことになるのかを考察せよ。


debugger の使い方

lldb と gdb どちからで以下の操作を行い、log を示せ

(1) 作成したプログラム 引数 を指定して、lldb/gdb を起動する。プログラムは -O0 -g で compile すること。

(2) 関数 f のwriteを呼び出しているところ break point を設定し、そこで止める。

(3) frame up を使って main 関数で、write に正しい値が格納されていることを示せ

(4) break point を回数だけ通過してから、break point で止まるようにせよ

     lldb     brea modiy -i xx
     gdb      ingore xx yy ?

(5) m の値が指定した値で停まるようにせよ

(6) write する直前停めた時に disass して assembler を見る。stepi を繰り返して、sycall の直前までいく


option

(7) 実際に write system call が呼ばれる直前の register の値を示せ
      lldb    regisgter read
      gdb     info register

(8) break point を解除し、 f が終了するように finish コマンドを使う

変数が clang/gcc の最適化によって、どのような assembler になるかを調べよ。

最適化されたコードを assembler level で trace してみよう。


C / C++ では cmake を使うこと

nm.c を作る

CMakeList.txt を作る

    project( nm )
    add_definitions("-Wall")
    add_executable( nm  nm.c )

この段階で hg init ; hg add ; hg commit する

    % cmake -DCMAKE_BUILD_TYPE=Debug .

で debug build する

    % make
    % lldb -- ./nm 10 20


Go では go で作った module と debugger を使う


Rust では cargo と lldb を使う


Shinji KONO / Fri Nov 24 13:19:14 2023