5

常に実行可能ファイルに直接リンクされているいくつかのオブジェクト ファイルに、スレッド ローカル変数を追加しています。これらのオブジェクトは、共有ライブラリ内に含まれることはありません (これは近い将来にも当てはまると考えて間違いありません)。これは、これらのオブジェクトに -fPIC フラグが必要ないことを意味しますよね?

私たちのコードベースには、デフォルトですべてのオブジェクトの -fPIC フラグがあります。これらの多くは共有ライブラリに含まれているため、-fPIC の使用は理にかなっています。ただし、このフラグを使用すると、新しいスレッド ローカル変数のデバッグで問題が発生します。これは、 -fPIC を使用してスレッド ローカル変数をステップ オーバーしているときに GDB がクラッシュするためです。新しいスレッド ローカル変数を使用してこれらのいくつかのオブジェクト ファイルから -fPIC を削除すると、適切にデバッグできます。

非 PIC オブジェクトと PIC オブジェクトを実行可能ファイルに混在させても問題ないという正式な声明は見つかりません。これまでの私のテストでは問題ないことが示されていますが、コーシャとは感じられず、共有ライブラリのケースにより、オンラインでの議論は一般的に「PIC と非 PIC を混在させないでください」です。

この場合、非 PIC オブジェクトを PIC オブジェクトとライブラリで構築された実行可能ファイルにリンクしても安全ですか? これが安全であるというGCCドキュメントからの正式な声明があるかもしれませんが、私はそれを見つけることができません.

編集: このバグを回避するために gcc にバイナリ パッチを適用することは、短期的な解決策ではありません。Linux でコンパイラを切り替えることは、可能な解決策ではありません。

4

2 に答える 2

4

上記のようなバグ以外は問題ないはずです。これを説明する決定的なドキュメントへの参照を提供することはできませんが、経験からのみ話します. -fPIC を指定すると、gcc (またはアセンブラー) は別のコードを生成しますが、結果のコードは標準化された再配置シンボルを使用します。断片を一緒にリンクする場合、これは最初は問題ではありません。リンカーは頑固にすべてをつなぎ合わせ、コードが非 PIC コードの PIC を示しているかどうかを知りません。共有ライブラリをサポートしていないシステムを使用しているため、これを知っており、独自のローダーをラップする必要がありました。

難しい最後のポイントは、結果のオブジェクトが共有ライブラリであるかどうかをリンカに伝えることができるということです。そうして初めて、リンカーはインポート/エクスポートを示すいくつかの (OS 固有の) 構造体とシンボルを生成します。そうしないと、リンカは作業を終了するだけです。主な違いは、シンボルが見つからないとエラーが発生することです。

コンパイラとリンカーを明確に分離することで、フラグが問題にならないことが保証されます (パフォーマンスの違い以外では)。LTO タフには注意が必要です。これには、過去にさまざまなコンパイラ設定でいくつかの問題がありました。

前述のように、私はこれを調査し、ELF と動的ローダーに関するいくつかのドキュメントを赤くしました。PIC/非 PIC のリンクに関する明示的な言及はどこにもありませんが、リンク プロセスは入力のコンパイラ設定を実際には気にしません。有効なコードは有効なコードのままです。

PIC 以外のコードを共有ライブラリ (PIC) にリンクしたい場合、絶対再配置が発生すると (可能性が高い) リンカは終了します。コードをプログラムにリンクしたい場合、最終的なプログラムが処理できるものにのみ制限されます。PIC をサポートする OS では、何でも使用できます。そうしないと、リンカがシンボルの欠落やサポートされていないセクション/再配置タイプについて文句を言う可能性があります。

于 2016-06-10T10:31:12.233 に答える