Linux、GNU GCC、ld、バージョンスクリプト、ELFバイナリ形式—仕組み


13

Linuxでのライブラリのバージョン管理と、それをすべて機能させる方法について詳しく学習しようとしています。コンテキストは次のとおりです。

-動的ライブラリの2つのバージョンがあり、同じインターフェイスセットを公開します(例:libsome1.soと)libsome2.so

-アプリケーションはに対してリンクされていlibsome1.soます。

-このアプリケーションはlibdl.so、たとえば、別のモジュールを動的にロードするために使用しますlibmagic.so

-今libmagic.soに対してリンクされていlibsome2.soます。明らかに、リンカスクリプトを使用してシンボルを非表示にせずにlibmagic.so、実行時のすべてのインターフェイスの呼び出しlibsome2.soはに解決されlibsome1.soます。これlibVersion()は、マクロの値に対して返される値をチェックすることで確認できますLIB_VERSION

-だから、次にlibmagic.so、リンカスクリプトでコンパイルおよびリンクを試みます。リンカスクリプトは、3を除くすべてのシンボルを定義しlibmagic.so、それによってエクスポートされます。この作品...または少なくともlibVersion()LIB_VERSION値が一致する(そしてそれは、バージョン2ではない1を報告します)。

-ただし、一部のデータ構造がディスクにシリアル化されると、破損が発生しました。アプリケーションのディレクトリlibsome1.soで、を指すようlibsome2.soにソフトリンクを削除して作成すると、すべてが期待どおりに機能し、同じ破損は発生しません。

私は仕方がありませんが、これは、実行時リンカーのシンボルの解決におけるいくつかの競合が原因であると考えられます。私は多くのことを試しましたlibsome2.so、すべてのシンボルが安定するようにリンクしようとしましたsymbol@@VER_2(コマンドがnm -CD libsome2.soまだシンボルをリストしているので、まだリストしsymbolていないので混乱していますsymbol@@VER_2)...何もうまくいかないようです!!! 助けて!!!!!!


あなたの最後のアプローチは、私が始めたものです。そして、私はおそらく腐敗が何らかのシンボルの混乱であることに同意します。悲しいことに、私はあなたに答えがありません。
RobotHumans

これはSOでうまくいくかもしれませんが、確かに言うほど十分には理解できません。移動したい場合はフラグを立ててください。
xenoterracide

1
試してみてくださいRTLD_LOCALRTLD_DEEPBINDあなたがアプリでのdlopenのフラグを。これをテストする時間はありませんが、マンページに基づいて動作するはずです。
stribika

回答:


13

これはあなたの質問に正確には答えませんが、...

まず第一に、ELFはLinuxが実行可能ファイル(プログラム)、共有ライブラリ、およびソフトウェアのコンパイル時に見つかった中間ファイルであるオブジェクトファイルに使用する仕様です。オブジェクトファイルは.oで終わり、共有ライブラリは.soで終わり、その後にピリオドで区切られたゼロ個以上の数字が続き、実行可能ファイルは通常拡張子を持ちません。

通常、共有ライブラリに名前を付けるには3つの形式があり、最初の形式は単に.soで終わります。たとえば、readlineというライブラリはlibreadline.soというファイルに保存され、通常は/ lib、/ usr / lib、または/ usr / local / libのいずれかの下にあります。そのファイルは、-lreadlineなどのオプションを使用してソフトウェアをコンパイルするときに配置されます。-lは、次のライブラリとリンクするようコンパイラーに指示します。ライブラリは時々変更されるため、廃止される可能性があるため、ライブラリはSONAMEと呼ばれるものを埋め込みます。readlineのSONAMEは、libreadlineの2番目のバージョンのメジャーバージョンのlibreadline.so.2のようになります。互換性があり、ソフトウェアの再コンパイルを必要としないreadlineのマイナーバージョンも多数存在する場合があります。readlineのマイナーバージョンは、libreadline.so.2.14という名前になります。通常、libreadline。soは、readlineの最新のメジャーバージョン(この場合はlibreadline.so.2)への単なるシンボリックリンクです。libreadline.so.2は、実際に使用されているファイルであるlibreadline.so.2.14へのシンボリックリンクでもあります。

ライブラリのSONAMEは、ライブラリファイル自体に埋め込まれています。ファイルlibreadline.so.2.14内のどこかに、文字列libreadline.so.2があります。プログラムがコンパイルされ、readlineでリンクされると、libreadline.soファイルが検索され、それに埋め込まれたSONAMEが読み取られます。後で、プログラムが実際に実行されると、libreadline.soだけでなくlibreadline.so.2がロードされます。これは、それが最初にリンクされたときに読み取られたSONAMEであったためです。これにより、システムに複数の互換性のないバージョンのreadlineがインストールされ、各プログラムはリンクされた適切なメジャーバージョンをロードします。また、readlineを2.17にアップグレードする場合、既存のライブラリとともにlibreadline.so.2.17をインストールするだけで、シンボリックリンクlibreadline.so.2をlibreadline.so.2.13からlibreadline.so.2.17に移動すると、

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.