web-dev-qa-db-ja.com

Linux、GNU GCC、ld、バージョンスクリプトおよびELFバイナリ形式-どのように機能しますか?

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

-同じインターフェイスのセットを公開するダイナミックライブラリの2つのバージョン、たとえばlibsome1.solibsome2.soがあります。

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

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

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

-次に、libmagic.soで定義され、それによってエクスポートされる3つを除くすべてのシンボルを非表示にするリンカースクリプトを使用して、libmagic.soをコンパイルおよびリンクしようとします。これは機能します...または、少なくともlibVersion()LIB_VERSIONの値が一致します(バージョン1ではなくバージョン2が報告されます)。

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

これは、ランタイムリンカーのシンボルの解決における競合が原因である可能性があると思わざるを得ません。すべてのシンボルがlibsome2.soに関連付けられるようにsymbol@@VER_2をリ​​ンクしようとするなど、多くのことを試しました(コマンドnm -CD libsome2.soはまだシンボルをsymbol@@VER_2ではなくsymbolとしてリストしているため、まだ混乱しています)...何も思われません働くために!!!助けて!!!!!!

13

これはあなたの質問に正確に答えるものではありませんが...

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

共有ライブラリに名前を付けるには、通常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に移動すると、同じメジャーバージョンを使用するすべてのソフトウェアに、新しいマイナーアップデートが表示されます。

13
penguin359