32位系统调用表入口点如何映射到x86_64中的SYSCALL_DEFINE

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了32位系统调用表入口点如何映射到x86_64中的SYSCALL_DEFINE相关的知识,希望对你有一定的参考价值。

我正在深入研究系统调用,

[将系统调用添加到syscall_32.tbl和syscall_64.tbl中

syscall_32.tbl

434     i386    hello           sys_hello           __ia32_sys_hello

syscall_64.tbl

434 common  hello           __x64_sys_hello

定义:

SYSCALL_DEFINE0(hello) {
    pr_info("%s
", __func__);
    pr_info("Hello, world!
");
    return 0;
 }

用户空间代码:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/syscall.h>
#include <string.h>
int main(void)
{
    long return_value = syscall(434);

    printf("return value from syscall: %ld, erron:%d
", return_value, errno);
    return 0;
}

当我在x86_64上运行此用户空间代码时,我在dmesg中得到以下输出

$ gcc userspace.c -o userspace

[  800.837360] __x64_sys_hello
[  800.837361] Hello, world!

但是当我将其编译为32位时,我得到了

$ gcc userspace.c -o userspace -m32

[  838.979286] __x64_sys_hello
[  838.979286] Hello, world!

怎么会出现在syscall_32.tbl(__ia32_sys_hello)中的入口点映射到__x64_sys_hello?

答案

在64位内核上,SYSCALL_DEFINE0将compat(32位)和其他ABI(例如x86_64上的x32)定义为真正的64位函数。它没有定义(也没有办法定义;这不是预处理器的工作方式)由宏评估)之后出现的单个主体构建的多个函数。因此,__func__扩展为写入了__func__的包装函数的名称,而不是包装器的名称。对于x> 0的SYSCALL_DEFINEx,由于必须转换参数,因此更为复杂。

您可以在arch/x86/include/asm/syscall_wrapper.h中找到所有魔术(在顶级内核树下)。

如果您真的希望/需要单独的功能,我相信有一种方法可以跳过魔术而做到。但这会使您的代码难以维护,因为当魔术背后的机制中断时,它可能会中断。可能更希望调查调用(当前)用户空间进程是32位还是64位,并据此采取不同的操作。

以上是关于32位系统调用表入口点如何映射到x86_64中的SYSCALL_DEFINE的主要内容,如果未能解决你的问题,请参考以下文章

查看系统版本32位与64位生产场景中的使用及对比

X86 X64 X86_64 AMD64 区别

ld:入口点(_main)未定义。对于架构 x86_64:Xcode 9

入口点 (_main) 未定义。对于架构 x86_64 - 仅 XCode UITesting

x86_64 调用约定和堆栈帧

windows7内核分析之x86&x64第二章系统调用