問題タブ [dlopen]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票する
1 に答える
2954 参照

c - 共有ライブラリでdlcloseが呼び出されると、共有ライブラリのグローバル変数はどうなりますか?

共有ライブラリ(またはDLL)がdlopenおよびdlcloseメカニズムを介して使用されており、作成された共有ライブラリに、メモリがヒープから取得されるグローバル変数がいくつかある場合、dlcloseが呼び出されると、それらの変数とメモリはどうなりますか?

同じプロセスでdlopenが再度呼び出された場合、どのように動作しますか?

0 投票する
1 に答える
244 参照

c - dlopen() オブジェクトを操作する際の呼び出し元オブジェクトの決定

dlopen() を介してプラグイン システムを利用する (C) プログラムを作成しています。私が直面している障害は、メインプログラムが、それらを呼び出したプラグインを本当に知る必要があるいくつかの関数をエクスポートすることです (ほとんどの場合、記録を保持するため、メインプログラムに関数ポインターのようなものを追加するため、プラグインを適切にアンロードできます)。プログラム)。

これを行うためのきれいな方法が見つからないようです。これまでに思いついたオプション:

  1. プラグインがその名前を提供することを要求するか、ロード時に関数への引数として与えるいくつかのデータを提供します。
    • すべての関数が誰から呼び出されたかを気にするわけではないため、このオプションは好きではありません。さらに、プラグインが誰であるかについて嘘をつくのをできるだけ難しくしたいと思います
  2. backtrace() を使用して、前の関数のオブジェクト名を判別します。
    • これはかなり醜く、移植性がないようです。
  3. プラグインがその名前を含むファイルレベルの構造体 (または他の変数) を配置することを要求します (議論のために「plugin_info」と呼びましょう)。次に、プラグインをロードするときに dlsym() を使用して変数を検索し、その名前で (ハッシュのように) インデックスを付けます。次に、プラグインが関数を呼び出すために使用する #define マクロを挿入し、マクロを&plugin_info引数として追加します。
    • これは私が今使っているものですが、ハックのようです。1 つには、マクロに「&plugin_info」を渡す必要があります。「plugin_info」だけを渡すと、プラグインではなく、メイン プログラムから「plugin_info」がプルされます。アドレスで参照すると、正しいものでコンパイルされ、再配置されないようになります。このオプションは未定義の動作のように見えるので嫌いですが、機能します。また、マクロは、プラグイン開発者が関数呼び出しに問題がある場合 (間違った引数の型を渡すなど)、少し混乱させる可能性があります。

他のアイデアやテクニックがあれば、ぜひ知りたいです。

0 投票する
2 に答える
2416 参照

c - 動的シンボル検索のためのMinGWを使用したC(C ++ではない)での名前マングリングを防止します

関数名で「動的に」関数ポインターを取得するCプログラムがあります(つまり、関数名を文字列として渡し、関数へのポインターを取得します)。私はすでにdlopenとdlsymを使用してLinuxでこれを行っており、dlfcnを使用した他のUnixライクでも機能すると思います。

MinGWを使用してこのプログラムをWindowsに移植しようとしたときに、問題が発生しました。「GetProcAddress(handle、symbol_name)」を使用して名前を検索しようとすると、「symbol_name」はコールバック関数の名前であり、「handle」は「GetModuleHandle(NULL)」によって返される現在の実行可能ファイルへのハンドルです。何も取得されません。 MinGWの名前マングリングは、シンボル名に「_」を追加するためです。

明らかな解決策(必要な記号の前に「_」を付ける)は、移植性にとって少し「危険」に思えます(コンパイラーがそれらのいくつかに2つのアンダースコアを追加する可能性がありますか?わかりません)。

  • コンパイラが私のシンボルに名前を付けないようにするためのより良い方法はありますか?(またはそれらのサブセット、動的に検索する必要があるコールバックのみ);

  • または、GetProcAddressに、マングルされた場合でもそれらを検出させる方法はありますか?

オプション-fno-leading-underscoreも試しましたが、すべての外部シンボルのマングリングも削除され、プログラムをstdlibなどとリンクできなくなりました(また、ドキュメントの警告は少し怖いです)。

また、純粋なCを使用していることに注意してください(コードのどの部分にもC ++はありません)。また、すべてのコードは単一の「.exe」に含まれています。

TIA

0 投票する
1 に答える
5323 参照

linker - シンボルのバージョン管理を実現する方法

私は以下のようなものを達成したい:

ライブラリの複数のバージョンがあります。dlopen() を使用してライブラリの最新バージョンを動的に読み込みます。次に、特定の関数 (同様の戻り値の型と引数リストと共に) がそのバージョンに存在するかどうかを確認したいと思います。開いている場合は、以前のバージョンにフォールバックして同じことを確認します。

「バージョン スクリプト」に関する投稿を見たことがありますが、使用できません。また、関数名のみをチェックするため、シンボルテーブルを検索しても解決策にはならないと思います。

0 投票する
2 に答える
6347 参照

ios - iOSでdlsymを使用して名前で関数を呼び出す

iOS で関数を名前で呼び出すことはできませんか? というC関数がありgetstringます。私は次のように呼んでいます。

これが実行されると、responseFiled.textに設定されdlsym(...): symbol not foundます。これは、機能するdlopenが機能しないことを意味しdlsymます。バイナリを使用してシンボルをダンプし、存在するnmことを確認しました_getstringのマニュアルを確認したdlsymところ、名前にアンダースコアを追加してはいけないと書かれています。とにかく追加しても問題は解決しません。私は何を間違っていますか?

ここで、Objective-C で関数を名前で呼び出すことについて同様の質問をし、回答に従って Mac で正常に実行したため、この問題は iOS に固有のようです。

0 投票する
3 に答える
5409 参照

c++ - RTLD_GLOBAL を使用しない typeinfo、共有ライブラリ、および dlopen()

dlopenを使用してロードしたときに、共有ライブラリ全体で例外が正しく機能しないという問題があります (または、少なくとも、期待どおりです。これには問題があることはわかっています) 。ここにいくつかの単純化されたサンプル コードを含めます。実際の状況はmyapp =Matlab, myext1 =mexglx matlab 拡張機能です。mylibは 2 つの拡張機能 ( myext1myext2 )間の私のコードの共有ライブラリです。

mylib.h

mylib.cpp

myext1.cpp

myext2.cpp myext1.cppと同じ

myapp.cpp

このコードのコンパイル:

Aでの entrypoint( )の呼び出しは期待どおりに機能し、throwFoo()が例外をスローし、 entrypoint( )が例外をキャッチします。ただし、 Bでの呼び出しは例外をキャッチできません。さらに診断コードを追加すると、 Fooクラスの typeinfo が2 つの拡張機能で異なることがわかります。2 つのdlopen呼び出しの順序を変更しても違いはなく、2 番目にロードされた拡張機能は失敗します。

RTLD_GLOBALをdlopenの追加フラグとして使用することでこれを修正できることはわかっていますが、 dlopen を使用するアプリケーション (Matlab) は制御できません。この問題を解決するためにmylibまたはmyext1myext2でできることはありますか?

実行時に LD フラグを使用しないようにする必要があります (Matlab バイナリを実行しているユーザーを制御できないため)。他の提案はありますか?

0 投票する
5 に答える
13478 参照

c - メモリからdlopen?

生成されたオブジェクト コードをメモリから直接読み込む方法を探しています。

ファイルに書き込むと、dlopen を呼び出してそのシンボルを動的にロードしてリンクできることを理解しています。ただし、メモリ内で開始し、ディスクに書き込まれ、dlopen によってメモリに再ロードされることを考えると、これは少し回り道のように思えます。メモリ内に存在するオブジェクト コードを動的にリンクする方法があるかどうか疑問に思っています。私が言えることから、これを行うにはいくつかの異なる方法があるかもしれません:

  1. dlopen をだまして、メモリから離れることはないにもかかわらず、メモリの場所がファイルであると考えさせます。

  2. 私が探していることを行う他のシステムコールを見つけてください (これは存在しないと思います)。

  3. コードをメモリ内で直接リンクできる動的リンク ライブラリを見つけます。明らかに、これはグーグルで検索するのが少し難しいです.「動的リンクライブラリ」は、動的リンクのタスクを実行するライブラリではなく、ライブラリを動的にリンクする方法に関する情報を表示するためです.

  4. リンカーから一部の API を抽象化し、そのコードベースから新しいライブラリを作成します。(明らかに、これは私にとって最も望ましくないオプションです)。

それで、これらのうちどれが可能ですか?実現可能ですか?私が仮説を立てたもののどれかを教えていただけますか? 私が考えもしなかった別の方法はありますか?

0 投票する
1 に答える
858 参照

c++ - この動的ライブラリ読み込みコードが gcc で動作するのはなぜですか?

バックグラウンド:

私は、C++ GNU/Linux アプリケーションを Windows に移植するという、うらやましい仕事をしていることに気づきました。このアプリケーションが行うことの 1 つは、特定のパスで共有ライブラリを検索し、posix dlopen() および dlsym() 呼び出しを使用してそれらからクラスを動的にロードすることです。このようにロードするのには十分な理由がありますが、ここでは触れません。

問題:

dlsym() または GetProcAddress() を使用して C++ コンパイラによって生成されたシンボルを動的に検出するには、extern "C" リンケージ ブロックを使用してシンボルをアンマングルする必要があります。例えば:

このコードは完全に有効な C++ であり、Linux と Windows の両方の多数のコンパイラでコンパイルおよび実行されます。ただし、「戻り値の型が有効な C ではない」ため、MSVC ではコンパイルされません。私たちが思いついた回避策は、リスト オブジェクトの代わりにリストへのポインターを返すように関数を変更することです。

私は、新しい関数と古いレガシー関数プロトタイプの両方で動作するか、少なくとも非推奨の関数が検出されたときに検出して警告を発する、GNU/Linux ローダーの最適なソリューションを見つけようとしています。古いライブラリを使用しようとしたときにコードがセグメンテーション違反を起こした場合、ユーザーにとって見苦しいものになります。私の最初のアイデアは、get_list の呼び出し中に SIGSEGV シグナル ハンドラーを設定することでした (これが厄介なのはわかっています。より良いアイデアを受け入れます)。したがって、古いライブラリをロードするとセグメンテーション違反が発生することを確認するために、古い関数プロトタイプ (リスト オブジェクトを返す) を使用して新しいロード コード (リストへのポインタを期待する) を使用してライブラリを実行し、驚いたことにそれを実行しました。ちょうど働いた。私が持っている質問は、なぜですか?

以下の読み込みコードは、上記の両方の関数プロトタイプで動作します。gcc バージョン 4.1.2 および 4.4.4 を使用して、Fedora 12、RedHat 5.5、および RedHawk 5.1 で動作することを確認しました。-shared および -fPIC を指定して g++ を使用してライブラリをコンパイルし、実行可能ファイルを dl (-ldl) に対してリンクする必要があります。

0 投票する
1 に答える
1920 参照

c++ - C++ では、動的ライブラリ内から外部で定義されたグローバル変数にアクセスできますか?

C++ では、動的ライブラリ内から外部で定義されたグローバル変数にアクセスできますか?

次のようにヘッダー ファイルで宣言されたグローバル変数があります。

ファイル名 : TestVariable.hpp

次に、ソース コード ファイルで次のように定義します。

ファイル名: TestVariable.cpp

私の動的ライブラリを構成するソース コードは次のとおりです。

ファイル名 : Plugin.cpp

私のメイン関数は次のように定義されます。

ファイル名 : main.cpp

GNU Autotools、g++、および ld を使用して、すべてのコードを正しく (警告なしで) コンパイルおよびリンクできますが、結果のバイナリ実行可能ファイルを実行すると、動的ライブラリ ファイルを dlopen できません。しかし、関数loadLibraryの本体を構成する唯一のコード行をコメントアウトし、再コンパイルしてリンクすると、プログラムは正しく動作します!

よくわからない場合は、ライブラリ (ライブラリ) で dlopen が呼び出されたときに、ライブラリがグローバル変数testVariableへの参照を解決できず、これが dlopen 操作の失敗の原因であると言えます。リンケージタイプや名前マングリングがこの問題と関係があるのでしょうか?

生成されたダイナミック ライブラリで Linux nm ユーティリティを実行すると、シンボルtestVariableが未定義、つまり "U" であることが通知されます。バイナリ実行可能ファイルで nm ユーティリティを実行すると、シンボルtestVariableが存在し、初期化されていないデータ セクション (つまり "B") 内に存在することが通知されます。では、動的ライブラリをロードするときに dlopen がこのシンボルを解決できないのはなぜでしょうか?

ソース ファイルPlugin.cppから動的ライブラリのみを生成します。バイナリ実行可能ファイルは、2 つのソース コード ファイルmain.cppおよびTestVariable.cppから生成されています。

誰か助けてください。答えは私の顔を見つめていると断言できますが、私はそれを見ていません。

前もって感謝します。

0 投票する
2 に答える
3925 参照

macos - dlopen() でロードされた DLL で @executable_path をオーバーライドする

オペレーティング システムは MacOS X、具体的には PowerPC G4 上の 10.5 (Leopard) ですが、10.6 を実行している x86 でも同じ問題があります。

DLL を動的にロードするアプリケーションを作成しています。DLL (これを と呼びましょうfoo.dylib) は別のアプリケーションの一部であり、ハードディスクの別の場所にあります。私のアプリケーションはプログラムで見つけfoo.dylibます(正確な配置は変更される可能性があり、おそらくユーザーは実行中のアプリケーション自体からGUIを介してDLLパスを指定します)。たとえば、アプリケーションがディレクトリ/Application/MyApp.app/Contents/MacOSにあり、foo.dylibたまたま にあるとし/Application/OtherApp.app/Contents/MacOSます。DLL の読み込みにはdlopen().

さて、それfoo.dylib自体が同じディレクトリにある他のDLLの束を必要としていることがわかりましたが、事前に何も知りません。このような追加の DLL はそれぞれ、.foo.dylibなどのパスで登録され@executable_path/bar.dylibます。のセマンティクスは@executable_path、現在のプロセス実行可能ファイルが見つかったディレクトリに置き換える必要があるということです。これは、私ではなく、OtherApp でうまく機能します。 を開くfoo.dylibと、 をロードしようとし、正しいディレクトリではないbar.dylibで検索します。/Application/MyApp.app/Contents/MacOS/bar.dylib

DYLD_FALLBACK_LIBRARY_PATH回避策は、環境変数をに設定することですが、これはアプリケーションを起動する前/Application/OtherApp.app/Contents/MacOSに行う必要があります (この環境変数はダイナミック リンカーによって 1 回だけ読み取られます。プログラムで値を変更しても効果はありません)。これは、ファイルの場所の動的検出と互換性がありません。setenv()putenv()foo.dylib

の効果をオーバーライドするプログラム的な方法はあります@executable_pathか?