Z.OOL.ネット信託統治領 はてな諸島

こちらは "Z.OOL.ネット信託統治領 はてな諸島" です。

Z.OOL.ネット信託統治領はてな諸島は、はてなダイアリーからはてなブログに運用を移行致しました。
どうか御了承下さい。

動的ライブラリ内の関数へのポインタの有効性を確認する一手法 (再掲)

この投稿は、技術的事項についての速報的で簡易な短信についての投稿であり、
以前の投稿の再掲です。どうか宜しくお願い致します。

本稿について

この投稿は、以下に投稿された過去の Qiitadon.com のセルフモーメントの投稿を再編した上で、再掲したものです。

z80oolong.hatenadiary.jp

また、この投稿は、技術的事項についての速報的で簡易な短信についての投稿として、Z.OOL.ネット信託統治領 Qrunch 諸島の以下の投稿にクロス投稿しています。

z80oolong.qrunch.io

はじめに

標準 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) 関数に関数のポインタを示す引数 addrDlinfo 構造体へのポインタ info を渡して呼び出した結果、値 0 が返却されるか、 info.dli_sname に関数名の文字列以外が格納されていれば、関数のポインタは正しくない物であることが判ります。

結論

即ち、 glibc を使用する場合において動的ライブラリ内の関数のポインタが正しいがどうかを確認するには、 dlerror(3) 関数の返り値を判定する手法と上記で述べた、標準ライブラリ関数の dladdr(3) を用いて関数のポインタから関数名の逆引きを試みる手法が必要であることが判ります。