スポンサーリンク

DLOPEN(3) FreeBSD ライブラリ関数マニュアル DLOPEN(3)

名称

dlopen, dlsym, dlerror, dlclose − 動的リンカへのプログラムのインタフェー ス

ライブラリ

標準 C ライブラリ (libc, −lc)

書式

#include <dlfcn.h>

void *

dlopen(const char *path, int mode);

void *

dlsym(void *handle, const char *symbol);

const char *

dlerror(void);

int

dlclose(void *handle);

解説

これらの関数は、動的リンカサービスに対する単純なプログラムのインタフェー スを提供します。プログラムのアドレス空間に新しい共有オブジェクトを追加す る操作、共有オブジェクトが定義するシンボルのアドレス結合を取得する操作、 および共有オブジェクトを使用する必要がなくなったときにそれを除去する操作 が提供されています。

dlopen() は、 path 内の共有オブジェクトへのアクセスを提供し、 dlsym() と dlclose() の呼び出しにおいて、オブジェクトを後で参照するために使用可能な 記述子を返します。 dlopen() を呼び出す前に path がアドレス空間内になかっ た場合はアドレス空間に配置されます。この方法で、オブジェクトが初めてアド レス空間にロードされるとき、関数 _init() が存在すればそれが動的リンカに よって呼び出されます。先の dlopen() 呼び出しでアドレス空間内に path が既 に配置されている場合、2 度目は追加されません。しかし、 path 上での dlopen() 操作の参照カウント値は管理されます。 path に指定されたものが NULL ポインタであれば、プロセスのメイン実行可能モジュールへの参照として解 釈されます。 mode は、ロードされたオブジェクトからの外部関数への参照が、 どのようにその参照先と結合するか、その方法を制御します。これには次の値の うちの 1 つが含まれていなくてはなりません。おそらくは、後で述べる追加フラ グとの OR をとった値になるでしょう。

       RTLD_LAZY

外部関数への参照はそれぞれ関数が最初に呼び出されるときに解決 されます。

RTLD_NOW
外部関数への参照はすべて dlopen() によってただちに結合されま す。

RTLD_LAZY は、効率を良くするという理由で一般的に好ましいです。しかし、 dlopen() を呼び出している間に未定義シンボルを確実に発見するためには RTLD_NOW が便利です。

次のフラグの 1 つを OR をとって mode 引数の中に含めることができます。

RTLD_GLOBAL
この共有オブジェクトから得られるシンボルおよび必要とされる オブジェクトの有向非巡回グラフ (DAG) が、その他すべての共有 オブジェクトからの未解決の参照を解決するために利用可能にな ります。

RTLD_LOCAL
この共有オブジェクトから得られるシンボルおよび必要とされる オブジェクトの有向非巡回グラフ (DAG) が、同一の共有オブジェ クトからの未解決の参照を解決するために利用可能になります。 こちらがデフォルトの動作ですが、このフラグを用いて明示的に 指定することができます。

dlopen() は、処理が失敗すると NULL ポインタを返し、 dlerror() で問い合わ せできるエラー状態を設定します。

dlsym() は、 symbolhandle で識別される共有オブジェクト内で発生したと きと同様に、ヌル文字で終了する文字列 symbol で記述されたシンボルのアドレ ス結合を返します。 dlopen() によってアドレス空間に追加されたオブジェクト によってエクスポートされるシンボルは、 dlsym() 呼び出しを通してのみアクセ ス可能です。このようなシンボルは、オブジェクトがロードされる際に、すでに アドレス空間に存在しているシンボルの定義に置き換わるものではありません し、通常の動的リンク参照を満たすために利用可能なものでもありません。

dlsym() が特別な handle NULL を使用して呼び出された場合は、そのハンドルは 呼び出しがされている実行ファイルあるいは共有オブジェクトへの参照として解 釈されます。このため、共有オブジェクトは自分自身の持つシンボルを参照でき るのです。

dlsym() が特別な handle RTLD_DEFAULT を使用して呼び出された場合は、オブ ジェクトがロードされる際に未定義のシンボルを解決するために使用されるアル ゴリズムに従ってシンボルを探索します。探索されるオブジェクトは次のように 書かれた順番になります。

1. 参照しているオブジェクト自身 (あるいは dlsym() への呼び出しがされて いるオブジェクト)。ただし、オブジェクトが ld(1) に対して −Wsymbolic オプションを使用してリンクされた場合。

2. プログラムの起動時にロードされていた全オブジェクト

3. dlopen() 経由でロードされた全オブジェクト。これらのオブジェクトは、 参照を行っているオブジェクトも含んだ、必要とされるオブジェクトの有向 非巡回グラフに存在します。

4. RTLD_GLOBAL フラグを mode 引数で設定して呼び出した dlopen() 経由で ロードされた全オブジェクト

dlsym() が特別な handle RTLD_NEXT を使用して呼び出された場合、シンボルの 検索は、 dlsym() 呼び出しを発行した後でロードされた共有オブジェクトに制限 されます。そのため、メインプログラムからこの関数が呼び出された場合、すべ ての共有ライブラリが検索されます。この関数が共有ライブラリから呼び出され た場合、その共有ライブラリより後でロードされる共有ライブラリすべてが検索 されます。 RTLD_NEXT はライブラリ関数を包み込むラッパを実装するのに便利で す。例えば、ラッパ関数 getpid() がある場合、関数内で dlsym(RTLD_NEXT, "getpid") を使用すれば ‘‘本物の’’ getpid() にアクセスできるでしょう。

シンボルが見つけられなかった場合、 dlsym() は null ポインタを返し、エラー 状態を設定します。エラー状態は dlerror() を使用して問い合わせることができ ます。

dlerror() は、 dlopen(), dlsym(), または dlclose() 呼び出しの間に発生した 最後のエラーを記述するヌル文字で終了する文字列を返します。このようなエ ラーが発生していない場合、 dlerror() は NULL ポインタを返します。 dlerror() を呼び出すたびに、エラー指示がリセットされます。そのため、後の 呼び出しが先の呼び出しの直後にくるような dlerror() 呼び出しを行った場合、 後の呼び出しでは必ず NULL ポインタが返ってきます。

dlclose() は handle が参照する共有オブジェクトへの参照を削除します。参照 カウント値が減らされ 0 になると、そのオブジェクトはアドレス空間から削除さ れ handle は無効になります。この方法で共有オブジェクトを除去する直前に、 _fini() 関数がこのオブジェクトで定義されている場合にはそれを呼び出しま す。 dlclose() は、処理が成功すると値 0 を返します。そうでない場合は -1 を返し、エラー状態を設定します。エラー状態は dlerror() で問い合わせできま す。

オブジェクトに固有の関数 _init() と _fini() は、引数なしに呼び出され、戻 り値は期待されていません。

ELF 実行可能ファイルの場合、ファイル中で定義されているシンボルを dlsym() で見えるようにするには ld(1) に対して −export-dynamic オプションを使用し てリンクを行う必要があります。

以前の実装では、C 言語からコンパイルしたオブジェクトコードとシンボルの互 換性を持たせることができるように、外部シンボルにはすべてアンダスコアを先 頭につける必要がありました。現在でも、 C 言語のコンパイラに対して (非推奨 ですが) −aout オプションを使用した場合には当てはまります。

エラー

dlopen() と dlsym() は、エラーが発生した場合には NULL ポインタを返しま す。 dlclose() は処理が成功すると 0 を返し、エラーが発生した場合は -1 を 返します。エラーが検出されるたびに、エラーの詳細を説明するメッセージが dlerror() 呼び出しによって取り出せます。

関連項目

ld(1), rtld(1), dladdr(3), link(5)

FreeBSD 10.0 September 24, 1989 FreeBSD 10.0

スポンサーリンク