2017-09-08 17 views
1

これはこれまで発生していなかった問題です。私はそれがおそらく私のパッケージリポジトリ(私は最近、私のArchシステムを再インストールしたばかりで、これはたった今起こっている)に問題があると確信しています。GCCでアセンブルすると、.dataに関する奇妙な再配置エラーが発生する

.data 
str: .asciz "Test" 

.text 
.globl main 
main: 
    sub $8, %rsp 
    mov $str, %rdi 
    call puts 
    add $8, %rsp 
    ret 

をしてから、私はGCCを使用してアセンブリとリンクしようとすると - 私は、過去に何度も行っているように - と、単に:

私はx86_64版でハロー小さな世界を書いた

gcc test.s -o test

し、このエラーが出力されます。

/usr/bin/ld: /tmp/ccAKVV4D.o: relocation R_X86_64_32S against `.data' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: final link failed: Nonrepresentable section on output collect2: error: ld returned 1 exit status

このエラーは、これまで私のために発生したことはありません。私は同じエラーメッセージをグーグルで問題を解決しようとしましたが、これは一般的な問題であると考えていましたが、非常に具体的なものが出てきます。私はbase-develとGCCのツールチェーン全体を再インストールしようとしました。他に何ができるのか分からない(nasmを使用しないでください。異端)。

明らかに何かが分からないと思っていますが、私は長い間、アセンブリのニーズにGCCを使用しました。

+0

私はこれが重複していると確信していますが、後でそれを検索するつもりです。 Debianは64bモードでPIC/PIEバイナリに切り替わりました。(OS Xと同じように、他のディストリビューションも同様です)、toolchainのデフォルトが変更されました。あなたのケースではgccがあなたのオブジェクトをPICとしてリンクしようとしていますが、 'mov $ str、%rdi'に絶対アドレスがあります。だから、あなたはどこにいても相対的にripになるようにコードを書き直すべきでしょう。あるいは、実行可能ファイルの古いPIC以外のリンクを強制するためにgccリンクを設定する方法があります。 – Ped7g

+0

Insight @ Ped7gありがとうございました – oldjohn1994

+4

GCCがデフォルトで再配置可能な64ビットコードをビルドした、より新しい/異なるバージョンのArch Linuxを使用している可能性があります。これを処理する最良の方法は、RIP(命令ポインタ相対)アドレッシングを使用するようにコードを変更することです。 'mov 'を' lea str(%rip)、%rdi'に変更し、_C_ライブラリを呼び出すときに 'call puts'の代わりに' call puts @ plt'を使用してください。 –

答えて

3

このエラーを回避する方法はno-pie(非位置独立実行ファイル)実行可能ファイルを生成することです:

この現象の理由は次のように@ Ped7gによって説明される
gcc -no-pie test.s -o test 



DebianはPICに切り替え/ PIEバイナリを64ビットモードで使用&あなたのケースのGCCがオブジェクトをPICとしてリンクしようとしていますが、絶対アドレスがmov $str, %rdiになります。

+2

彼はこの場合にはArchを使用していますが、Debianにも同じことが言えます。文字列のアドレスだけが問題ではありません。 _C_ライブラリへの呼び出しも同様に変更する必要があります。 –

+0

@MichaelPetch: '-no-pie'はすべてを修正し、' call puts'を 'call puts @ plt'に変換します。 PIEで動作させたい場合は 'call'命令だけを変更する必要があります。具体的には、 'gcc -fno-plt'(書き込み可能+実行可能PLTを避け、余分な間接を避けるための非遅延動的リンク)や' call puts @ PLT'を使ってビルドした場合、 'call * puts @ GOTPCREL(%rip)デフォルトの方法です(あるいは 'call puts @ plt'も動作します。コンパイラはCをコンパイルするときに大文字のPLTを出力します) –

関連する問題