1

別のプログラムでプラグインとしてロードできる共有ライブラリ (.so) を開発しています。そのプログラムは、他のライブラリのセットから構成されています。そのライブラリの 1 つである libA.so は、独自の実装 ::operator new() および ::operator delete() をエクスポートします。しかし、私はこの new と delete の実装を使用したくなく、独自の実装 (私のライブラリに静的にリンクされています) を使用したくありません。すべて正常に動作しますが、libA.so には割り当てられたメモリへのポインタを返す関数があり、libA.so から operator delete を呼び出して解放する必要があります。そのため、libA.so から _ZdlPv シンボルのアドレスが必要です。

_ZdlPv のアドレスを取得するために関数 dlsym を使用しています: dlsym(RTLD_DEFAULT, "_ZdlPv")。演算子削除 (_ZdlPv シンボル) の私自身の実装は、共有ライブラリの動的シンボル テーブルに存在しないため、libA.so で定義された演算子 delete() のアドレスを取得することを期待しています。

しかし、dlsym 関数から完全に間違った結果が得られました。別のライブラリ libB.so 内に存在するアドレスを返します。また、libB.so には _ZdlPv シンボルの定義が含まれていませんが、このシンボルが必要です (そのライブラリでは未定義です)。また、dlsym() によって返されるアドレスは、libB.so の .MIPS.stubs セクションを指します。これは PLT のようなものです (ただし、MIPS アーキテクチャでは -- はい、MIPS 向けに開発しています)。そして、dlsym によって返されたアドレスで関数を呼び出すと、スレッドが終了します。デバッグが難しい...

それはここで間違っていますか?dlsym() が機能しないのはなぜですか? 私が知っているように、$gp レジスターは「グローバル・リンケージ・テーブル」へのポインターを保持します。すべての共有ライブラリには独自のリンケージ テーブルがありますか? スタブ セクションから関数を呼び出すと、gp には正しい値が必要です。また、他のライブラリ (libB.so) のスタブ セクションからコードを呼び出している場合、このスレッドがクラッシュするため、間違った $gp 値で​​コードを呼び出していますか?

しかし、なぜ dlsym() は他の (libB.so) ライブラリのスタブ セクションのコードへのポインタを返すのでしょうか? これは、ライブラリのスタブ セクションに _ZdlPv シンボルが含まれていないためです。これは、ライブラリの動的シンボル テーブルに存在しないためですか?

私の仮定が正しければ、理解できませんでしたが、MIPS プラットフォームで dlsym() を使用して他のライブラリから任意関数を呼び出すにはどうすればよいですか?

4

0 に答える 0