動的ライブラリ(*.so)のデバッグ手法をまとめておきます。

  • デバッグ対象の動的ライブラリ(*.so)を構築
まずプログラムはこんな感じ。
(dltest.c)

#include <stdio.h>

int func1( void )
{
    printf( "func1\n" );
    return 0;
}

void func2( int i )
{
    printf( "func2(%d)\n", i );
}

int func3( char* str )
{
    printf( "func3(%s)\n", str );
    return 0;
}
コンパイルはこう。(-sharedで共有ライブラリ指定。-fPICでPosition Independent Codeを指定)
$ gcc -shared -fPIC -o libdltest.so dltest.c
これでlibdltest.soができあがります。
  • デバッグ用ドライバー(呼び出しプログラム)の作成
こんな感じです。Man page of DLOPENなどを見ると色々オプションがありますが今日は深く考えない。ポイントはシンボル名を指定してdlsymを呼ぶと関数ポインタが得られるということ。
#include <stdio.h>
#include <dlfcn.h>

void* handle;
int ( *func1 )( void );
void ( *func2 )( int );
int ( *func3 )( char* );

int main( void )
{
    handle = dlopen( "./libdltest.so", RTLD_LAZY );
    if( handle != NULL ){
        func1 = ( int (*)( void ) )dlsym( handle, "func1" );
        if( func1 != NULL) {
            ( *func1 )();
        }
        func2 = ( void (*)( int ) )dlsym( handle, "func2" );
        if( func2 != NULL) {
            ( *func2 )( 123 );
        }
        func3 = ( int (*)( char* ) )dlsym( handle, "func3" );
        if( func3 != NULL) {
            ( *func3 )( "abcde" );
        }
        dlclose( handle );
    }
    return 0;
}
コンパイルはこう。(-ldlでlibdl.soをリンクします)
$ gcc -g -o main main.c -ldl
実行する。
$ ./main
$ func1
$ func2(123)
$ func3(abcde)
  • 関数ポインタ
久々に関数ポインタを使いました。忘れないように覚え書きしておきます。

関数プロトタイプのようにも見えますがあくまでも関数ポインタ変数の定義です。はfunc1、戻り値と引数を定義します。
int( *func1 )( void );
dlsymの戻り値(関数ポインタ)をfunc1に代入するときは、このようにキャストします。
func1 = ( int (*)( void ) )dlsym( handle, "func1" );
呼び出しはこんな感じ。func1();でも呼べるけど、関数ポインタであることを明示しておいた方がいいです。
( *func1 )();
応用編ですが関数ポインタは配列にできます。
(func_ptr_array.c)

#include <stdio.h>
void test1( void )
{
    printf( "test1\n");
}
void test2( void )
{
    printf( "test2\n");
}
void test3( void )
{
    printf( "test3\n");
}

int main( void )
{
    int( *func[] )( void ) = { test1, test2, test3 };
    ( *func[0] )();
    ( *func[1] )();
    ( *func[2] )();
    return 0;
}

コンパイルして実行するとこんな感じ。
$ gcc -g -o func_ptr_array func_ptr_array.c
$ ./func_ptr_array
$ test1
$ test2
$ test3
  • ひとりごと
最近プログラムをたくさん書いてなかったので、デバッグの効率化のテクニックを忘れ始めてました。ちょこちょこ自分で手を動かして、カンを鈍らせないようにしたいと思います。

続く

IMG_20190422_065637



スポンサードリンク