syscall wrapper asm C

人走茶凉 提交于 2021-02-04 16:31:37

问题


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;                                     \
})

回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/4861621/syscall-wrapper-asm-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!