【问题标题】:syscall wrapper asm C系统调用包装 asm C
【发布时间】:2011-02-01 10:49:21
【问题描述】:

有人可以向我解释这段代码 sn-p 吗? 另外请给我一些链接/ 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;                                     \
})

【问题讨论】:

    标签: c assembly arm wrapper system-calls


    【解决方案1】:

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

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

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

    由于您既不能访问特定的寄存器,也不能调用上述任何内核触发方法,所以在纯 C 代码中,您可以使用 调用的系统调用包装器 em> 类似于 C 函数,然后将参数放在寄存器中,并使用 ASM 代码触发内核。

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

    【讨论】:

    • 正确,SWI 是软件中断。
    【解决方案2】:

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

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

    【讨论】:

    • 他的代码中没有errno的声明,所以你可能不确定到底更新了哪个errno。请注意,这不是内核中的系统调用实现,而是 C 库中的某种包装器。
    • 我的意思是extern int errno; 几乎总是错误的,因为规范要求errno 是一个宏,如果你在某个地方已经有另一个定义,那就更错误了。 GNU C 库使用(*(__errno_location())) 或类似的表达式来查找errnothread-local 实现,因此不会与其他errno 发生符号冲突,因此未检测到错误.
    猜你喜欢
    • 1970-01-01
    • 2021-04-29
    • 2016-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-01
    相关资源
    最近更新 更多