はじめに
標準 C ライブラリ関数において dlsym(3)
関数で動的ライブラリ内の関数のポインタを取得する時、dlerror(3)
関数の返り値を判定すると、 0 が返却されるにも関わらず、まれに dlsym(3)
関数の値が誤ったポインタを返却してエラーを返さない現象が起きることがあります。
この場合、返却されたポインタを用いて関数を呼び出すと、当然にプロセスが Segmentation Fault を起こす不具合を起こします。
これを防ぐ手法として、 glibc のみに実装されている標準ライブラリ関数の dladdr(3)
を用いて関数のポインタから関数名の逆引きを試みる手法について述べます。
dladdr(3)
関数について
以下に、 dladdr(3)
の引数及び返り値を示します。
int dladdr(void *addr, Dl_info *info);
typedef struct {
const char *dli_fname;
void *dli_fbase;
const char *dli_sname;
void *dli_saddr;
} Dl_info;
ここに、 Dlinfo
構造体は、動的ライブラリ内の関数の逆引き情報を格納する構造体であり、 dli_sname
メンバに関数名が格納されます。詳細については、dlclose, dlerror, dlopen, dlsym のマニュアルページを御覧下さい。
そして、 dladdr(3)
関数に関数のポインタを示す引数 addr
と Dlinfo
構造体へのポインタ info
を渡して呼び出した結果、値 0 が返却されるか、 info.dli_sname
に関数名の文字列以外が格納されていれば、関数のポインタは正しくない物であることが判ります。
結論
即ち、 glibc を使用する場合において動的ライブラリ内の関数のポインタが正しいがどうかを確認するには、 dlerror(3)
関数の返り値を判定する手法と上記で述べた、標準ライブラリ関数の dladdr(3)
を用いて関数のポインタから関数名の逆引きを試みる手法が必要であることが判ります。
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
0件のコメント