1

私のメインアプリケーションは、関数 ABC を持つ静的ライブラリ A に静的にリンクし、動的ライブラリ xyz.dylib も同じ関数 ABC を持つ同じ静的ライブラリ A に静的にリンクします。関数 ABC は、グローバルに定義された変数を使用します。

メインアプリケーションが実行時に dlopen を使用して xyz.dylib をロードするとき。初期化子は、ABC 関数を呼び出した場所で呼び出されます。この関数 ABC は、メイン アプリケーションのアドレス空間からグローバル変数を使用します。

4

1 に答える 1

0

Osx では、dylib リンカのインライン関数は、最初に使用された関数を使用します。したがって、たとえば、インライン関数が最初にメインの実行可能ファイルで使用され、次にロードされた dylib で使用される場合、メインの実行可能ファイルのインライン関数が使用されます。

これは、インラインがグローバル シンボルを参照しない限り、通常は問題ありません。

繰り返しますが、同じバージョンが一貫して使用されるため、通常はこれで問題ありません。

この問題は、実行可能ファイルと dylib の両方にあるグローバルを参照する 2 つのインライン関数があり、1 つの関数が実行可能ファイルで最初に使用され、別の関数が dylib で最初に使用される場合に発生します。次に、ミスマッチのペアがあります。例えば:

class MagicAlloc
{
    void* Alloc()         { return gAlloc.get(); } 
    void  Free( void* v ) { gAlloc.free( v ); } 

    static RealAllocator gAlloc;
};

実行可能ファイルで MagicAlloc::Alloc を呼び出し、それを dylib で呼び出すとします。両方のすべての割り当てに対して、実行可能ファイルで gAlloc を使用します。次に、MagicAlloc::Free への最初の呼び出しが dylib で発生します。次に、グローバルのバイナリに割り当てられた何かを dylib から解放しようとします。

次の 2 つの解決策があります。

  1. グローバル/静的を参照するためにインラインを使用しないでください。グローバル構造と関数定義を同じ翻訳単位 (オブジェクト ファイル) に移動します。グローバルを「静的」とマークして、TLU の外部からは見えないようにします。これで、関数はリンク ステップで静的に解決され、適切なグローバルにバインドされます。

  2. プラグイン API を除く、実行可能ファイル内のすべてのシンボルを非表示にします。通常どおりリンクしますが、バイナリ自体をリンクする場合は、次をリンカーに渡します。

    -Wl,-exported_symbols_list,export_file

export file は、エクスポートする必要があるリンク シンボルのリストです。たとえば、そのファイルには少なくとも「_main」が必要です。これで、dylib を実行すると、間違ったインラインに動的にリンクできなくなります。これは、動的シンボル テーブルにないためです。2 番目のソリューションは、悪意のあるプラグインがグローバルに簡単にアクセスできないため、より安全です。

于 2013-12-09T23:40:48.483 に答える