我无法在Debian 9上使用GCC链接依赖于位置的程序集。以下是程序集中的hello.s
文件:
.section .rodata
hello_str:
.string "Hello world"
.text
.globl main
main:
xor %rdi, %rdi
mov $hello_str, %rdi
call puts # puts("Hello world");
xor %rax, %rax # return 0;
ret
运行gcc hello.s
后,收到以下错误:
$ gcc hello.s
/usr/bin/ld: /tmp/ccDvqMUc.o: relocation R_X86_64_32S against `.rodata' 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
而clang hello.s
生成可执行文件:
$ clang hello.s
$ file ./a.out
./a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=ca2f0204d60b5fc197b95c5ccb626a9dfb355a9b, not stripped
$ ./a.out
Hello world
当我将hello.s
转换为与位置无关的代码并将其存储到hello-pic.s
文件中时:
.section .rodata
hello_str:
.string "Hello world"
.text
.globl main
main:
xor %rdi, %rdi
leaq hello_str(%rip), %rdi
call puts@PLT # puts("Hello world");
xor %rax, %rax # return 0;
ret
然后gcc hello-pic.s
生成一个可执行文件(file
命令的输出和生成的a.out
可执行文件的输出与clang
的{{1}}相同
我不能在其他Linux机箱(Ubuntu,CentOS)上重现这个问题,这让我相信Debian上的GCC是用一些非标准标志构建的。如果是,那么基本原理是什么?如何强制GCC链接与位置相关的代码?随附的是我目前安装的CPU架构和相关软件包:
hello.s
答案 0 :(得分:0)
与其他发行版一样,Debian 9似乎默认启用了PIE(出于安全原因):
For the stretch release, the Debian version of the GNU GCC 6 compiler now defaults
to compiling "position independent executables" (PIE).
要恢复旧行为,您需要将-no-pie
添加到CFLAGS
。