web-dev-qa-db-ja.com

GCC / LDでRPATHとRUNPATHを設定する方法は?

最近、システムのアップグレード後にこの問題が発生しました。GCC-Wl,-rpath=オプションを使用すると、以前とは動作が異なります。

これを使用して、プロジェクトのサブモジュールに組み込まれたいくつかの共有ライブラリへの検索パスを設定しました。当時は、システム全体にLD_LIBRARY_PATHを設定するよりも良いと考えていました(コンピュータの電源を入れるたびに設定したくありませんでした)。すべてが正常に機能し、これら2つのアプローチは同等に見えました。

-rpathの動作が変更されたようです。直接依存するライブラリでは引き続き機能しますが、-rpath=を介して設定された同じディレクトリから他のライブラリをリンクするライブラリでは機能しません。 LD_LIBRARY_PATHのエクスポートは以前と同様に機能します。

readelfを使用してコンパイルの出力を検査しましたが、違いがあります。アップグレード前(Linux Mint 18.2とGCC 5.4)のDynamicセクションには次の行がありました:

0x000000000000000f (RPATH)            Library rpath: [submod/lib]

アップグレード(Linux Mint 19 with GCC 7.3)の後、行は次のように変更されました。

0x000000000000001d (RUNPATH)            Library runpath: [submod/lib]

RUNPATHではなくRPATHを使用しますか? では、RPATHをRUNPATHに置き換えることをお勧めします(または、少なくとも優先度が低いため、別の目的に使用することをお勧めします)。なぜこれが間接リンクに影響するのか。ライブラリ自体のreadelf出力には、RPATHもRUNPATHもありません。

だから私の質問はこれです:なぜリンカが-rpath=オプションを異なって解釈し始めたのですか、そして古い動作を強制する方法はありますか?(または同等の結果が得られる別の方法を実行します。)

別の質問は次のようになります:古いバージョンのリンカに新しい出力を生成するように指示することは可能ですか(つまり、RPATHではなくRUNPATH)?


[〜#〜]編集[〜#〜]

これは バイナリのRunPathを設定する方法? の複製ではありません。私の質問は反対です。RPATHの動作が必要です。私はそれを理解しました(コメントの先端のおかげで)、ここで私の質問に答えます。

6
Machta

古い動作を強制する方法はありますか?

はい。このオプションを使用できます-Wl,--disable-new-dtagsnewリンカーにold動作を使用するように指示します。 RPATH。

古いバージョンのリンカーに新しい出力(RPATHではなくRUNPATH)を生成するように指示することは可能ですか?

はい。使用する -Wl,--enable-new-dtagsoldリンカーにnew動作を使用するように指示します。 RUNPATH。

readelfを使用して実行可能ファイルを確認しました。これらの2つのオプションは、ELF動的セクションに書き込まれる内容を制御しているようです。問題は、新しいバージョンのデフォルトの変更が原因で発生したと思いますが、興味深いことに、ldのマニュアルページでは、同じであることが示唆されています。

--enable-new-dtags
-disable-new-dtags
このリンカーは、ELFで新しいダイナミックタグを作成できます。しかし、古いELFシステムはそれらを理解しない場合があります。 --enable-new-dtagsを指定すると、新しいダイナミックタグが必要に応じて作成され、古いダイナミックタグは省略されます。 --disable-new-dtagsを指定すると、新しいダイナミックタグは作成されません。 デフォルトでは、新しいダイナミックタグは作成されません。これらのオプションはELFシステムでのみ使用できることに注意してください。

6
Machta

プロジェクトGNU Binutils(含むGNUリンカー(ld))は、この動作の変更の起源ではありませんが、Debian(2016) 1 、およびGentoo(2013!) 2

2013年1月のMike Frysingerによるgentooのコミットメントによると、

「「新しい」dtagsオプションは14年以上前から存在しているため、LinuxおよびGNUターゲットの場合、デフォルトで有効にします。 "

RUNPATHとRPATHには「文書化されていない動作の違い」があるため、この変更はあまり受け入れられていません、 45 ...驚くことに、この変更は現在Debian安定版に適用されています。

問題は、RUNPATHを使用すると、予測できない問題が発生することです...しかし、主に機能するだけです。ウィキペディアから:

Ldダイナミックリンカーは、DT_RPATHとは異なり、DT_RUNPATHの場所で推移的依存関係を検索しません。

2
Javier