系统调用包装器 asm C

发布于 2024-10-15 06:14:45 字数 1656 浏览 1 评论 0原文

有人可以向我解释一下这段代码吗? 另外请给我一些链接/URL,我可以在其中了解更多信息? 此代码用作包装器来覆盖我们库中的“extern int errno”。有人可以向我解释这个函数,并告诉我为什么在某些系统调用中需要包装器吗?哪些也称为WeakSYSCALLS?

#define ASM_ARGS_1      ASM_ARGS_0, "r" (_a1)
#define ASM_ARGS_2      ASM_ARGS_1, "r" (_a2)
#define ASM_ARGS_3      ASM_ARGS_2, "r" (_a3)
#define LOADREGS_5(a1, a2, a3, a4, a5)          \
register int _v1 asm ("v1") = (int) (a5);     \
LOADREGS_4 (a1, a2, a3, a4)

#define LOADREGS_6(a1, a2, a3, a4, a5, a6)      \

register int _v2 asm ("v2") = (int) (a6);     \

LOADREGS_5 (a1, a2, a3, a4, a5)

#define MYLIBC_SYSCALL(name, nargs, args...)               \
({                                                        \

    unsigned int retval;                              \

    {                                                 \

    register int _a1 asm ("r0"), _nargs asm ("r7");   \
    LOADREGS_##nargs(args)                            \
    _nargs = __NR_##name;                             \
    asm volatile (                                    \
            "swi    0x0"                              \
            :"=r"(_a1)                                \
            :"r"(_nargs) ASM_ARGS_##nargs             \
            : "memory" );                             \

      retval = _a1;                                     \
    }                                                 \

    if ( retval >= 0xfffff001 )     {                 \
            errno = -retval;                          \
            retval = (unsigned int)-1;                      \
    }                                                 \
    (int) retval;                                     \
})

Can someone explain this code snippet to me?
Also please give me some link/URL where i can know more about this?
This code is used as a wrapper to override the "extern int errno" in our library. Can someone explain me this function, and tell why is wrapper needed in some syscalls? Which are also called WeakSYSCALLS?

#define ASM_ARGS_1      ASM_ARGS_0, "r" (_a1)
#define ASM_ARGS_2      ASM_ARGS_1, "r" (_a2)
#define ASM_ARGS_3      ASM_ARGS_2, "r" (_a3)
#define LOADREGS_5(a1, a2, a3, a4, a5)          \
register int _v1 asm ("v1") = (int) (a5);     \
LOADREGS_4 (a1, a2, a3, a4)

#define LOADREGS_6(a1, a2, a3, a4, a5, a6)      \

register int _v2 asm ("v2") = (int) (a6);     \

LOADREGS_5 (a1, a2, a3, a4, a5)

#define MYLIBC_SYSCALL(name, nargs, args...)               \
({                                                        \

    unsigned int retval;                              \

    {                                                 \

    register int _a1 asm ("r0"), _nargs asm ("r7");   \
    LOADREGS_##nargs(args)                            \
    _nargs = __NR_##name;                             \
    asm volatile (                                    \
            "swi    0x0"                              \
            :"=r"(_a1)                                \
            :"r"(_nargs) ASM_ARGS_##nargs             \
            : "memory" );                             \

      retval = _a1;                                     \
    }                                                 \

    if ( retval >= 0xfffff001 )     {                 \
            errno = -retval;                          \
            retval = (unsigned int)-1;                      \
    }                                                 \
    (int) retval;                                     \
})

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

转身以后 2024-10-22 06:14:45

执行“系统调用”意味着触发内核执行特殊活动。由于内核运行在不同的地址空间中,因此这不能通过简单的函数调用来完成。

根据操作系统和硬件平台,系统调用可以通过触发中断、调用门、SYSENTER 或其他几种方法来调用。

但无论如何,您不能像 C 函数调用那样简单地将多个参数传递给内核。但是,您可以将参数值放入某些寄存器中。这些寄存器是什么,以及内核如何解释它们的内容,又是特定于所讨论的操作系统的。

由于您既不能访问特定寄存器,也不能调用上述任何内核触发方法,在纯 C 代码中,您可以使用系统调用包装器,它们称为,例如C函数,然后将参数放入寄存器并使用ASM代码触发内核。

您在上面看到的就是这样一个系统调用包装器。您会看到它将参数数量放入寄存器 r7 的部分,将参数本身放入适当的寄存器 (LOADREGS_*),然后执行触发器 (swi 0x0,其中我猜是一个软件中断——我对ARM平台了解不多),并从寄存器A1获取“返回值”。

Doing a "syscall" means triggering the kernel to execute a special activity. Since the kernel runs in a different address space, this cannot be done via a simple function call.

Depending on the operating system and hardware platform, a syscall can be invoked by, for example, triggering an interrupt, a call gate, SYSENTER, or several other methods.

In any case, though, you cannot simply pass a number of parameters to the kernel the way you would do with a C function call. You can, however, place parameter values into certain registers. Which registers those are, and how their contents are interpreted by the kernel, is again specific to the OS in question.

Since you can neither access specific registers, nor invoke any of the kernel-triggering methods mentioned above, in plain C code, there are syscall wrappers available to you that are called like C functions, and then place the parameters in registers and trigger the kernel using ASM code.

What you see above is such a syscall wrapper. You see the part where it places the number of arguments into register r7, the arguments themselves into the appropriate registers (LOADREGS_*), then does the trigger (swi 0x0, which I guess is a software interrupt - I don't know much about the ARM platform), and gets the "return value" from register A1.

携君以终年 2024-10-22 06:14:45

系统调用不能直接设置errno,而是返回负值。 errno 实际上应该是一个计算结果为左值的宏。

此代码更新您的 errno 副本,而不是 C 库的副本。

System calls cannot set errno directly, instead they return a negative value. errno is actually supposed to be a macro that evaluates to an lvalue.

This code updates your copy of errno rather than the C library's.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文