c - 创建共享对象时不能使用针对 `.data' 的重定位 R_X86_64_32;

标签 c assembly ld

我编写了下面的汇编代码,它可以直接通过as和ld构建。

as cpuid.s -o cpuid.o
ld cpuid.o -o cpuid

但是当我使用 gcc 来完成整个过程时。我遇到以下错误。

$ gcc cpuid.s -o cpuid
/tmp/cctNMsIU.o: In function `_start':
(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o:(.text+0x0): first defined here
/usr/bin/ld: /tmp/cctNMsIU.o: relocation R_X86_64_32 against `.data' can not be used when making a shared object; recompile with -fPIC
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
/usr/bin/ld: final link failed: Invalid operation
collect2: error: ld returned 1 exit status

然后我将_start修改为main,并将-fPIC添加到gcc参数中。但这并不能解决我的 ld 错误。错误消息更改为以下。

$ gcc cpuid.s -o cpuid
/usr/bin/ld: /tmp/ccYCG80T.o: relocation R_X86_64_32 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

由于我没有创建共享对象,所以我不明白其含义。我只想制作一个可执行的二进制文件。

    .section .data
output:

    .ascii "The processor Vendor ID is 'xxxxxxxxxxxx'\n"

    .section .text

    .global _start

_start:

    movl $0, %eax

    cpuid

    movl $output, %edi
    movl %ebx, 28(%edi)
    movl %edx, 32(%edi)
    movl %ecx, 36(%edi)

    movl $4, %eax
    movl $1, %ebx
    movl $output, %ecx
    movl $42, %edx
    int $0x80

    movl $1, %eax
    movl $0, %ebx
    int $0x80

如果我将上面的代码修改为下面的内容,它是否正确或者对 64 位 asm 编程有一些副作用?

         .section .data
 output:
         .ascii "The processor Vendor ID is 'xxxxxxxxxxxx'\n"

         .section .text

         .global main
 main:
         movq $0, %rax
         cpuid

         lea output(%rip), %rdi
         movl %ebx, 28(%rdi)
         movl %edx, 32(%rdi)
         movl %ecx, 36(%rdi)
         movq %rdi, %r10

         movq $1, %rax
         movq $1, %rdi
         movq %r10, %rsi
         movq $42, %rdx
         syscall

最佳答案

正如评论所指出的,您可以通过将程序链接为非 PIE 来解决此问题,但最好将您的 asm 修复为与位置无关。如果是 32 位 x86 代码那就有点难看了。该指令:

    movl $output, %edi

会变成:

    call 1f
1:  pop %edi
    add $output-1b, %edi

对于 64 位来说,它更干净。而不是:

    movq $output, %rdi

你会写:

    lea output(%rip), %rdi

关于c - 创建共享对象时不能使用针对 `.data' 的重定位 R_X86_64_32;,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49434489/

相关文章:

c - 为什么 VISA (4111111111111111) 不返回任何内容?

assembly - 如何将两个字节转换为一个 16 位数字?

c - 将 .a 库链接到 .o 对象,因此在构建时只需要包含 .o

c++ - Solaris 5.10 x86 CC 链接器错误 : ld: fatal: library -lcryptoki: not found

c - 如何解码Linux中系统调用的输入标志?

c - Linux 内核链表 - 和排序

c - 逗号运算符 , 的作用是什么?

assembly - 关于 [base + index*scale + disp] 和 AT&T disp(base,index,scale) 的几个问题

c - 偏移量如何进入堆栈?

c++ - ld:osX 机器上的重复符号 [libpmk]