4

我想在 Linux 上编译以下程序:

    .global _start
    .text
_start:
    mov $1,   %rax
    mov $1,   %rdi
    mov $msg, %rsi
    mov $13,  %rdx
    syscall
    mov $60,  %rax
    xor %rdi, %rdi
    syscall
msg:
    .ascii "Hello World!\n"

但是,它给了我以下链接器错误:

$ gcc -nostdlib hello.s
/usr/bin/ld: /tmp/ccMNQrOF.o: relocation R_X86_64_32S against `.text' 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-pie默认使用生成共享对象。因此,使用-no-pie修复它:

$ gcc -no-pie -nostdlib hello.s
$ ./a.out
Hello World!

如何将 gcc 配置为-no-pie默认使用?我正在使用 Arch Linux。

4

2 回答 2

4

我想只是不要用--enable-default-pie.

请参阅此博客文章:http ://nanxiao.me/en/gccs-enable-enable-default-pie-option-make-you-stuck-at-relocation-r_x86_64_32s-against-error/和启用 pie 的 Arch 补丁默认情况下:https ://git.archlinux.org/svntogit/packages.git/commit/trunk?h=packages/gcc&id=5936710c764016ce306f9cb975056e5b7605a65b 。

于 2018-03-05T18:21:53.897 回答
0

为此,您必须重新编译 gcc 以禁用默认 PIE。或者您-no-pie每次要编译位置相关的汇编代码时都需要。

但是,仅对于您提供的示例,更好的方法是使用相对寻址,例如label_name(%rip).

相对寻址允许 PIE 正常工作。

我把你的修改成这样:(见leaq行)

.global _start
.text
_start:
    movq $1,        %rax
    movq $1,        %rdi
    leaq msg(%rip), %rsi
    movq $13,       %rdx
    syscall
    movq $60,       %rax
    xorq %rdi,      %rdi
    syscall
.section .rodata
msg:
    .ascii "Hello World!\n"

(我添加.section .rodata只是因为通常这应该放入rodata部分。您的版本工作正常,但输出包含来自标签的objdump -d无意义指令。)msg

于 2020-07-25T03:31:20.170 回答