あなたのディストリビューションには--enable-default-pie
というgccが設定されているため、デフォルトでは位置に依存しない実行可能ファイルが作成されます(実行可能ファイルとライブラリのASLRが可能です)。その移転はPIC/PIEでは認められていません。
gcc -fno-pie -no-pie
を使用すると、以前の動作に戻すことができます。-no-pie
はリンカーオプション、-fno-pie
is the code-gen optionです。 -fno-pie
だけでは、gccはmov eax, offset .LC0
のようなコードを、まだ有効になっている-pie
とリンクしません。
:
(July 2017 patchは、gccでcompatのために、-nopie
ため-no-pie
エイリアスを作っclang -fno-pie -nopie
を、しかしclang4.0.1はそれを持っていません。打ち鳴らすはPIEは、あまりにも、デフォルトで有効になっていることができます。)のみ-no-pie
で
、(まだ-fpie
)コンパイラによって生成されたコードは必要以上に遅くなり、まだASLRから利益を得ないであろう位置に依存する実行可能ファイルにリンクされます。このペナルティは、主に(静的なストレージクラスを持つファイルスコープの変数static
の代わりに)グローバルにアクセスするときに発生します。 -fPIE
は、64ビットコードでは-fPIC
よりもはるかに悪くはないが、32ビットでは依然として悪いことに注意してください。 some examples on the Godbolt compiler explorerを参照し、The sorry state of dynamic libraries on Linuxを参照してください。
この方法でgccを設定した場合、gcc -v |& grep -o -e '[^ ]*pie'
は--enable-default-pie
を出力します。この設定オプションのサポートがgccのearly 2015に追加されました。 Ubuntuは16.10でそれを有効にし、Debianはgcc 6.2.0-7
(カーネルビルドエラー:https://lkml.org/lkml/2016/10/21/904)で同時刻に有効にしました。関連:Build compressed x86 kernels as PIE。
ld
自体はデフォルトを変更していないことに注意してください。それでも(少なくともbinutils 2.28のArch Linuxでは)正常に動作します。変更すると、または-no-pie
を明示的に使用しない限り、gcc
はデフォルトで-pie
をリンカーオプションとして渡します。
NASMソースファイルでは、絶対アドレスを取得するためにa32 mov eax, [abs buf]
を使用しました。関連
nasm -felf64 -Worphan-labels -g -Fdwarf testloop.asm &&
ld -o testloop testloop.o # works
gcc -v -nostdlib testloop.o # doesn't work
...
..../collect2 ... -pie ...
/usr/bin/ld: testloop.o: relocation R_X86_64_32 against `.bss' 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
gcc -v -no-pie -nostdlib testloop.o # works
gcc -v -static -nostdlib testloop.o # also works: -static implies -no-pie
:(67 a1 40 f1 60 00
インテルCPU上LCPストール)がいるIt doesを6バイトの方法は、小さな絶対アドレス(アドレスサイズ+のMOV EAX、moffsをコードする場合、私はテストしていた。):building static/dynamic executables with/without libc, defining _start
or main
を。
file
とreadelf
パイは、 "共有オブジェクト" ではなく、実行可能であることを言います。
$ gcc -fno-pie -no-pie -O3 hello.c
$ file a.out
a.out: ELF 64-bit LSB executable, ...
$ gcc -O3 hello.c
$ file a.out
a.out: ELF 64-bit LSB shared object, ...
半関連:別の最近のgccの特徴は、gcc -fno-plt
です。最後に共有ライブラリへの呼び出しは、call [rip + [email protected]]
(AT & T call *[email protected](%rip)
)となり、PLTトランポリンはありません。
ディストリビューションでは、書き込み可能な+実行可能メモリページが不要になるため、すぐに有効にすることを願っています。これは、多くの共有ライブラリ呼び出しを行うプログラムにとっては、大幅な高速化です。 x86-64 clang -O2 -g
tramp3dをコンパイルすると、どのハードウェアでも41.6秒から36.8秒になります。the patch author tested on。 (共有ライブラリ呼び出しの最悪のシナリオかもしれません)
遅延バインディングの代わりに早期バインディングが必要なので、すぐに終了する大きなプログラムの方が処理が遅くなります。 (例えば、clang --version
またはhello.c
をコンパイルする)。この減速は、明らかにプリリンクで減少する可能性があります。
これはPICコードの外部変数のGOTオーバーヘッドを削除しません。 (上記のゴッドボルトのリンクを参照してください)。
'-m32'では、PCを保持する貴重なレジスタを無駄にするので、これは本当に悪いことです。私の64ビットディストリビューションではフラグも有効になっているので、 '-m32 'もそれを使います。 –