将汇编目标文件与GCC链接时,由于errno设置而发生重定位错误

问题描述 投票:0回答:1

作为一个学校项目,我被要求重写 x86-64 程序集中的 write 函数。这个项目有一些规则。例如,正如 write 在发生错误时设置 errno 一样,我的 write 函数也应该以相同的方式设置 errno。另外,禁止使用 gcc 的

-no-pie
选项进行编译和链接。在 Linux 中,我们必须使用 errno.h 库中的
__errno_location
函数设置 errno 变量。所以我在我的汇编源文件中调用这个函数,并根据所需的规则进行设置。然后我在我的
main.c
源文件中声明它以使用我的 write 函数并用它来测试它。然后我输入编译和链接操作命令进行链接过程,但链接时遇到问题;

/usr/bin/ld: my_write.o: warning: relocation against `__errno_location@@GLIBC_2.2.5' in read-only section `.text'
/usr/bin/ld: my_write.o: relocation R_X86_64_PC32 against symbol `__errno_location@@GLIBC_2.2.5' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status

编译器告诉我使用

-fPIE
选项重新编译。但是当我再次执行时,它会给出相同的错误消息。

如果我使用

-no-pie
选项编译,这次会编译,但这也违反规则

有什么想法吗?


下面我分享一下文件内容以及我的编译步骤;

my_write.s;

section .text
global my_write
extern __errno_location

my_write:
    mov rax, 1
    syscall
    cmp rax, -1
    je err
    ret

err:
    neg rax                 
    mov rdi, rax
    call __errno_location
    mov [rax], rdi
    mov rax, -1
    ret

main.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>

extern ssize_t my_write(int fd, const void *buf, size_t count);

int main(void)
{
    char *str = "Hello";
    my_write(1, str, 5);
}

编译和链接

1.

nasm -felf64 -o my_write.o my_write.s
gcc -o test main.c my_write.o
/usr/bin/ld: my_write.o: warning: relocation against `__errno_location@@GLIBC_2.2.5' in read-only section `.text'
/usr/bin/ld: my_write.o: relocation R_X86_64_PC32 against symbol `__errno_location@@GLIBC_2.2.5' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status

给我一个这个错误。

c linux assembly gcc errno
1个回答
0
投票

您需要在 asm 代码中使用 PIE 兼容的调用:

call __errno_location@PLT

一般来说,对于PIE,在不同的.so中调用符号时,需要

@PLT

© www.soinside.com 2019 - 2024. All rights reserved.