62

私がやること

Linux 用の共有ライブラリを作成するときは、再配置、シンボルの可視性、GOT/PLT などに注意を払う傾向があります。

該当する場合は、同じライブラリの関数が相互に呼び出すときに PLT スタブを呼び出さないようにしています。たとえば、共有オブジェクトが 2 つのパブリック関数を提供するfoo()bar()します。(どちらもユーザーが呼び出すことができます)。bar()ただし、この関数は も呼び出しますfoo()。したがって、この場合に私が行うことは次のとおりです。

  1. プライベートな可視性を持つ関数を定義_foo()します。_bar()
  2. foo()と のbar()弱いエイリアスを_foo()それぞれ定義し_bar()ます。

そうすれば、共有オブジェクトのコードで弱いシンボルが使用されることはありません。ローカル関数のみを直接呼び出します。たとえば、_bar()が呼び出されると、_foo()直接呼び出します。

しかし、ユーザーは_*関数を認識しておらず、対応する弱いエイリアスを常に使用しています。

やり方

Linux では、これは次の構成を使用して実現されます。

extern __typeof (_NAME) NAME __attribute__(weak, alias("_NAME"));

問題

残念ながら、これは OS X では機能しません。私は OS X やそのバイナリ形式について深い知識を持っていないので、少し調べてみると、弱い関数の例がいくつか見つかりました (このようなもの)。ウィーク シンボルを使用できるのと同じですが、DSO のローカル関数のエイリアスであるウィーク シンボルは使用できません。

可能な解決策...

今のところ、すべてのシンボルがグローバルでデフォルトの可視性を持つように、この機能 (マクロを使用して実装) を無効にしました。今のところ同じことを達成するために私が考えることができる唯一の方法は、すべての_foo関数をプライベートな可視性で持ち、対応するfoo関数をデフォルトの可視性で持ち、対応する「非表示」を呼び出すことです。

より良い方法は?

ただし、そのためにはかなりの量のコードを変更する必要があります。したがって、他に方法がない限り、そこには行かないほうがいいと思います。

では、OS X の代替手段、または同じセマンティクス/動作を取得する最も簡単な方法は何ですか?

4

1 に答える 1

2

OS X では、ライブラリ内で行われる呼び出しは自動的に直接呼び出しとなり、dyld スタブを経由しません。事実の証拠は、代替関数を注入して呼び出しを処理できるようにしたい場合は、インターポーザブルを使用してシンボルへの間接アクセスを強制し、dyld スタブを介して呼び出しの実行を強制する必要があることです。それ以外の場合、デフォルトでは、ローカル呼び出しは直接になり、dyld を実行するオーバーヘッドは発生しません。

したがって、Linux での最適化は既にデフォルトの動作であり、エイリアスは必要ありません。

それでも、プラットフォームと互換性のあるコードを単純にするためだけにこれを行いたい場合は、エイリアスを作成できます。属性名として「weak_import」または「weak」(結合したい場合) を使用するだけです。

extern typeof (_NAME) NAME __attribute (weak_import, alias("_NAME"));

Weak Linking に関する Appleリファレンス: Marking Symbols for Weak Linking

于 2014-06-13T23:13:57.650 に答える