プログラミング

【C言語】デバッグのテクニック(標準関数のスタブ作成、動的ライブラリのデバッグ方法)

C言語のデバッグテクニックとして「標準関数のスタブ作成」「動的ライブラリのデバッグ方法」をご紹介します。

この記事で解決できること

  • 【C言語】標準関数のスタブ作成方法がわかる。
  • 【C言語】動的ライブラリのデバッグがわかる。

標準関数のスタブ作成方法がわかる

インターポジショニング(関数の上書き)

やり直しC言語:インターポジショニングによるtime(3)のスタブ化を参考にしました。

time関数(実行する度に結果が変わる関数)を題材にしています。まずこういうコードを単体試験しようとすると、時間が毎回変わるので一定の結果は得られません。

コンパイルして実行。現在のUNIX時間(数値)が表示されます。

 command
$ gcc -g -o main main.c
$
$ ./main
$ 1555888123

常に0を返すtime関数のスタブを作ってみました。

コンパイルして実行。常に0が返ります。

 command
$ gcc -g -o main2 main2.c
$
$ ./main2
$ 0

main.cとstub.cを分離します。

stub.cを共有ライブラリとしてビルドして、main.cと動的リンクさせます。しかしこのまま実行すると共有ライブラリが見つからないというエラーが出ます。

 command
$ gcc -shared -fPIC -o libstub.so stub.c
$ gcc -I./ -L./ -g -o main main.c -lstub
$ ./main
$ ./main: error while loading shared libraries: libstub.so: cannot open shared object file: No such file or directory

LD_LIBRARY‗PATHに、libstub.soのあるパスを指定することで、無事スタブ共有ライブラリを見つけることが出来ました。

 command
$ export LD_LIBRARY_PATH=<libstub.soがあるディレクトリ>
$ ./main
$ 0

標準関数をローカル関数で再定義することをインターポジショニングと呼ぶそうです。単体試験に使えそうですね。

余談ですがUNIX時間(数値)を年月日時分秒に変換できるUNIX時間変換ツールが便利です。

動的ライブラリ(*.so)のデバッグ手法

デバッグ対象の動的ライブラリ(*.so)を構築

まずプログラムはこんな感じ。

コンパイルはこう。(-sharedで共有ライブラリ指定。-fPICでPosition Independent Codeを指定)

 command
$ gcc -shared -fPIC -o libdltest.so dltest.c

デバッグ用ドライバー(呼び出しプログラム)の作成

こんな感じです。Man page of DLOPENなどを見ると色々オプションがありますが今日は深く考えない。ポイントはシンボル名を指定してdlsymを呼ぶと関数ポインタが得られるということ。

コンパイルはこう。(-ldlでlibdl.soをリンクします)

 command
$ gcc -g -o main main.c -ldl

実行する。

 command
$ ./main
$ func1
$ func2(123)
$ func3(abcde)

関数ポインタ

久々に関数ポインタを使いました。忘れないように覚え書きしておきます。

関数プロトタイプのようにも見えますがあくまでも関数ポインタ変数の定義です。はfunc1、戻り値と引数を定義します。

int( *func1 )( void );

dlsymの戻り値(関数ポインタ)をfunc1に代入するときは、このようにキャストします。

func1 = ( int (*)( void ) )dlsym( handle, "func1" );

呼び出しはこんな感じ。func1();でも呼べるけど、関数ポインタであることを明示しておいた方がいいです。

( *func1 )();

応用編ですが関数ポインタは配列にできます。

コンパイルして実行するとこんな感じ。

 command
$ gcc -g -o func_ptr_array func_ptr_array.c
$ ./func_ptr_array
$ test1
$ test2
$ test3

まとめ

C言語のデバッグテクニックとして「標準関数のスタブ作成」「動的ライブラリのデバッグ方法」をご紹介しました。

最近プログラムをたくさん書いてなかったので、デバッグの効率化のテクニックを忘れ始めてました。ちょこちょこ自分で手を動かして、カンを鈍らせないようにしたいと思います。

 

  • この記事を書いた人
  • 最新記事

ペイヴメント

ペイヴメントのエンジニア塾(当ブログ)では20年以上の経験から得られたプログラミング系ノウハウについてベテランにも満足して頂けるような内容の濃いコンテンツを初心者にも分かりやすい形で日々発信しています。【経歴】ベンチャーのソフトハウスで4年勤務後、精密機器メーカーのソフト開発部門に勤務し今に至ります。

-プログラミング

Copyright© ペイヴメントのエンジニア塾 , 2020 All Rights Reserved.