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 を使う