60

64 ビット FreeBSD で C アプリケーションをコンパイルしようとすると、次のエラーが発生しました。

再配置 R_X86_64_32S は、共有オブジェクトを作成するときに使用できません。-fPIC で再コンパイル

R_X86_64_32S移転とはR_X86_64_64

エラーについてグーグルで検索しましたが、考えられる原因です-R_X86_64_32Sが実際に何を意味するのか誰かが教えてくれれば幸いです。

4

6 に答える 6

40

R_X86_64_32SおよびR_X86_64_64は、amd64アーキテクチャ用にコンパイルされたコードの再配置タイプの名前です。それらすべてをamd64ABIで調べることができます。それによると、R_X86_64_64に分解されます:

  • R_X86_64-すべての名前の前にこれが付けられます
  • 64-直接64ビット再配置

R_X86_64_32S

  • R_X86_64-プレフィックス
  • 32S-値を32ビットに切り捨て、符号拡張

これは基本的に、どちらの場合も「この再配置によって示されるシンボルの値と加数」を意味します。次に、リンカはR_X86_64_32S、生成された値が元の64ビット値に符号拡張されていることを確認します。

これで、実行可能ファイルで、コードセグメントとデータセグメントに指定された仮想ベースアドレスが与えられます。実行可能コードは共有されず、各実行可能ファイルは独自の新しいアドレス空間を取得します。これは、コンパイラがデータセクションがどこにあるかを正確に認識し、それを直接参照できることを意味します。一方、ライブラリは、データセクションがベースアドレスから指定されたオフセットにあることだけを知ることができます。そのベースアドレスの値は、実行時にのみ知ることができます。したがって、すべてのライブラリは、位置に依存しないコード(または略してPIC)と呼ばれる、メモリ内のどこに配置されても実行できるコードで作成する必要があります。

今、あなたの問題を解決することになると、エラーメッセージはそれ自体を物語っています。

于 2011-05-23T07:03:54.303 に答える
31

これを理解するには、まず次のことを行う必要があります。

基準

R_X86_64_64R_X86_64_32およびR_X86_64_32Sこれらはすべて、ELF ファイル形式の AMD64 仕様を含むSystem V AMD ABIによって定義されています。

これらはすべて、ELF 形式のアーキテクチャに依存しない部分を指定するSystem V ABI 4.1 (1997)ELF32_R_TYPEで指定されている、再配置エントリのフィールドの可能な値です。その標準はフィールドのみを指定しますが、アーキテクチャに依存する値は指定しません。

4.4.1「再配置タイプ」の下に、要約表が表示されます。

Name          Field   Calculation
------------  ------  -----------
R_X86_64_64   word64  A + S
R_X86_64_32   word32  A + S
R_X86_64_32S  word32  A + S

このテーブルについては後で説明します。

そしてメモ:

R_X86_64_32および再配置はR_X86_64_32S、計算された値を 32 ビットに切り捨てます。リンカは、R_X86_64_32 (R_X86_64_32S) 再配置用に生成された値が元の 64 ビット値にゼロ拡張 (符号拡張) されていることを確認する必要があります。

R_X86_64_64 と R_X86_64_32 の例

R_X86_64_64最初にand を見てみましょうR_X86_64_32:

.section .text
    /* Both a and b contain the address of s. */
    a: .long s
    b: .quad s
    s:

それで:

as --64 -o main.o main.S
objdump -dzr main.o

内容:

0000000000000000 <a>:
   0:   00 00                   add    %al,(%rax)
                        0: R_X86_64_32  .text+0xc
   2:   00 00                   add    %al,(%rax)

0000000000000004 <b>:
   4:   00 00                   add    %al,(%rax)
                        4: R_X86_64_64  .text+0xc
   6:   00 00                   add    %al,(%rax)
   8:   00 00                   add    %al,(%rax)
   a:   00 00                   add    %al,(%rax)

Ubuntu 14.04、Binutils 2.24 でテスト済み。

ここでは逆アセンブルを無視し (これはデータであるため意味がありません)、ラベル、バイト、および再配置のみを調べます。

最初の移転:

0: R_X86_64_32  .text+0xc

つまり:

  • 0a: バイト 0 (ラベル)に作用する
  • R_X86_64_: AMD64 システム V ABI のすべての再配置タイプで使用されるプレフィックス
  • 32: (4 バイト)のみを指定したため、ラベルの 64 ビット アドレスはs32 ビット アドレスに切り捨てられます。.long
  • .text:私たちは.textセクションにいます
  • 0xc: これは、再配置エントリのフィールドである加数です。

移転先の住所は次のように計算されます。

A + S

どこ:

  • A: ここに加数0xC
  • S: ここでは再配置前のシンボルの値00 00 00 00 == 0

したがって、再配置後、新しいアドレスはセクションの 0xC == 12 バイトになり.textます。

(4 バイト) と(8 バイト)のs後に来るので、これはまさに私たちが期待するものです。.long.quad

R_X86_64_64は類似していますが、ここでは のアドレスを切り詰める必要がないため、より単純ですs。これは、カラムではword64なく標準スルーで示されます。word32Field

R_X86_64_32S 対 R_X86_64_32

R_X86_64_32Svsの違いR_X86_64_32は、リンカーが「収まるように再配置が切り捨てられた」と文句を言うときです。

  • 32: 再配置後に切り捨てられた値が古い値をゼロ拡張しない場合、つまり、切り捨てられたバイトはゼロでなければならない場合に文句を言います:

    例:がゼロではないため、苦情FF FF FF FF 80 00 00 00を生成します。80 00 00 00FF FF FF FF

  • 32S: 再配置後の切り捨てられた値が古い値を拡張しない場合に文句を言います。

    例:の最後のビットと切り捨てられたビットはすべて 1であるため、 FF FF FF FF 80 00 00 00toは問題ありません。80 00 00 0080 00 00 00

参照:この GCC エラー "... relocation truncated to fit..." とはどういう意味ですか?

R_X86_64_32S次の方法で生成できます。

.section .text
.global _start
_start:
    mov s, %eax
    s:

それで:

as --64 -o main.o main.S
objdump -dzr main.o

与えます:

0000000000000000 <_start>:
   0:   8b 04 25 00 00 00 00    mov    0x0,%eax
                        3: R_X86_64_32S .text+0x7

32Sこれで、リンカー スクリプトに合わせて切り捨てられた「再配置」を確認できます。

SECTIONS
{
    . = 0xFFFFFFFF80000000;
    .text :
    {
        *(*)
    }
}

今:

ld -Tlink.ld a.o

次の理由で問題ありません:は符号拡張である0xFFFFFFFF80000000に切り捨てられます。80000000

しかし、リンカー スクリプトを次のように変更すると:

. = 0xFFFF0FFF80000000;

エラーが生成さ0れるようになりました。これは、符号拡張ではなくなったためです。

32Sメモリ アクセスに使用するがイミディエイト32に使用する理由:アセンブラーが R_X86_64_32 のようなゼロ拡張ではなく、R_X86_64_32S のような符号拡張再配置を使用する方が良いのはいつですか?

R_X86_64_32S および PIE (位置に依存しない実行可能ファイル)

R_X86_64_32S は位置に依存しない実行可能ファイルでは使用できませんgcc -pie

relocation R_X86_64_32S against `.text' can not be used when making a PIE object; recompile with -fPIC

l

私はそれを説明する最小限の例を提供しました: What is the -fPIE option for position-independent executables in gcc and ld?

于 2015-10-22T20:07:27.150 に答える
5

つまり、必要に応じて-fPICフラグを使用せずに共有オブジェクトをコンパイルしたことを意味します。

 gcc -shared foo.c -o libfoo.so # Wrong

電話する必要があります

 gcc -shared -fPIC foo.c -o libfoo.so # Right

ELF プラットフォーム (Linux) では、共有オブジェクトは位置に依存しないコード (メモリ内の任意の場所から実行できるコード) でコンパイルされます。このフラグが指定されていない場合、生成されるコードは位置に依存するため、この共有オブジェクトを使用することはできません。物体。

于 2011-05-23T06:28:13.753 に答える
3

この問題に遭遇し、この回答が役に立たないことがわかりました。静的ライブラリを共有ライブラリとリンクしようとしていました。-fPIC スイッチをコマンドラインの前に置くことも調査しました(他の回答でアドバイスされているように)。私にとって、問題を解決した唯一のことは、静的ライブラリを共有に変更することでした。-fPIC に関するエラー メッセージは、さまざまな原因で発生する可能性があると思いますが、基本的には、ライブラリがどのように構築されているかを確認し、さまざまな方法で構築されているライブラリを疑ってください。

于 2015-08-04T20:53:03.477 に答える