パスワード:
//a.c I don't use header files as this is just for demo purpose.
extern void function_b(int num);
void function_a(int num) {
function_b(num)
}
//b.c
void function_b(int num) {
...
}
//dll.c
#include <dlfcn.h>
int main() {
void *handle_a;
void *handle_b;
void (*pfunc_a)(int);
...
handle_a = dlopen("./a.so", RTLD_LAZY);
...
pfunc_a = dlsym(handle_a, "function_a");
...
handle_b = dlopen("./b.so", RTLD_GLOBAL);
...
pfunc_a(2020);
...
return 0;
}
dll.c
実行時に共有ライブラリをロードしようとすると、モジュールには参照がa
あり、function_b
モジュールb
には定義がありますfunction_b
。共有ライブラリを作成してプログラムが実行される前にディスクに存在しますが、プログラムを実行するとシンボル検索エラーが発生すると仮定しa.so
ますb.so
。
./a.so:undefined symbol: function_b
handle_a = dlopen("./a.so", RTLD_LAZY);
ただし、ここで使用しているこのコード行を使用すると、RTLD_LAZY
ランタイムリンカーはシンボルを確認しようとせず、以前に呼び出すfunction_b
機会を得ます。このように、動的リンカーはb.soの定義を使用して参照を変更します。dlopen("b.so", RTLD_GLOBAL)
function_a
a.so
function_b
私の質問は次のとおりです
私の理解は正しいですか?動的リンカーは、セクション内のfunction_bのコマンドアドレスに接続/再配置できるようにするか、
.got
セクション.got.plt
を変更する必要があります。a.so
.text
b.so
function_b
私の理解が正しい場合、この場合、動的リンカーがまだ解決されないのはなぜですか?
ベストアンサー1
問題は、動的リンカーがを確認できないということではなく、function_b
2番目の呼び出しがdlopen
正しくないことです。あなた必要含めるRTLD_LAZY
かRTLD_NOW
、他のフラグはこれら2つのフラグを補完します。
次の 2 つの値のいずれかを含める必要があります。バナー:
b.so
負荷を次に変更してください。
handle_b = dlopen("./b.so", RTLD_NOW | RTLD_GLOBAL);
作業プログラムを生成します。
各呼び出しはロードされた最後のライブラリであるため。の間で選択するdlopen
必要があります。上記で指定しましたが(遅延ローディングでは何も得られません)、この場合もうまく動作します。これに加えて、他のフラグを追加することもできます。実行時に見つけるためにシンボルをグローバルに使用できる必要があるためです。RTLD_LAZY
RTLD_NOW
b.so
NOW
LAZY
RTLD_GLOBAL
b.so
function_a
function_b
バラよりの例dlopen(3)
実行する必要があるエラー処理dlopen
などの詳細で問題を明らかにします。