系统调用包装器asm C.

时间:2011-02-01 10:49:22

标签: c assembly arm wrapper system-calls

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

2 个答案:

答案 0 :(得分:5)

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

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

但是,在任何情况下,您都不能像使用C函数调用那样简单地将许多参数传递给内核。但是,可以将参数值放入某些寄存器中。哪些注册,以及内核如何解释它们的内容,再次特定于所讨论的操作系统。

由于您既不能访问特定的寄存器,也不能调用上面提到的任何内核触发方法,所以在普通的C代码中, syscall包装器可用于调用与C函数类似,然后将参数放在寄存器中并使用ASM代码触发内核。

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

答案 1 :(得分:0)

系统调用无法直接设置errno,而是返回负值。 errno实际上应该是一个评估为左值的宏。

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