1

dlopenを使用して実行時にロードされるプラグインを利用できるアプリケーションがあります。各プラグインは、共通の構造を使用して定義されたプラグイン情報を取得する関数を定義します。そんな感じ:

struct plugin {
    char *name;
    char *app_version;
    int app_verion_id;
    char *plugin_version;
    int plugin_version_id;
    /* ... */
 };

 struct plugin p = { "sample plugin",APP_VERION,APP_VERSION_ID,"1.2.3",10203 };

 struct plugin *get_plugin() {
     return &p;
 }

これはうまく機能し、プラグインをロードできます。ここで、アプリケーション全体をリンクせずにこれらのプロパティを読み取るための小さなツールを作成したいと思います。それを行うために、私はこのようないくつかのコードを持っています:

void *handle;
struct plugin *plugin;
struct plugin *(get_plugin*)();

handle = dlopen(filename, RTLD_LAZY);
if (!handle) { /*...return; ...*/ }

get_plugin = dlym(handle, "get_plugin");
if (!get_plugin) { /*...return; ...*/ }

plugin = get_plugin();
printf("Plugin: %s\n", plugin->name);

これは、単純なプラグインに適しています。問題は、多くのプラグインがアプリケーションからさらにシンボルを参照していることです。これらのシンボルは、RTLD_LAZYが設定されていても解決されます。(プラグイングローバルのものを初期化するために使用されるアプリケーションからのグローバル変数のように)したがって、dlopen()呼び出しは。のようなエラーで失敗しますfatal: relocation error: file sample_plugin.so: symbol application_some_symbol: referenced symbol not found。単一の単純な構造にアクセスしたいだけなので、リンカーが彼の作業の多くを実行するのをどのように防ぐことができるのか疑問に思いました。

4

3 に答える 3

1

によるとman dlopen(強調は私のものです)

RTLD_LAZY

遅延結合を実行します。
シンボルを参照するコードが実行されるときにのみ、シンボルを解決します。シンボルが参照されない場合、それは解決されません。 (遅延バインドは関数参照に対してのみ実行されます。変数への参照は、ライブラリが読み込まれると常にすぐにバインドされます。)

したがって、プラグインが使用する可能性のあるすべてのグローバル変数をツールに追加する必要があります。

于 2010-04-10T18:22:10.487 に答える
1

elfバイナリを使用している場合は、プラットフォームでlibelfが使用可能かどうかを確認することをお勧めします。詳細をお試しくださいman elf。これにより、実際にリンクしなくても必要なものが得られる場合があります。使ったことがないのでわかりません。

于 2010-04-12T20:27:09.477 に答える
0

で汚いハックはどうですかobjdump

〜$ objdump -s -j .rodata plugin.so  

plugin.so:ファイル形式elf32-i386

セクション.rodataの内容:
 20000000 73616d70 6c6520706c7567696e00332eサンプルプラグイン3。
 20000010 322e3100 312e322e33002.1.1.2.3。      

于 2010-04-10T18:19:22.073 に答える