Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

syscall wrapper asm C

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;                                     \
})
like image 201
RajSanpui Avatar asked Sep 20 '25 04:09

RajSanpui


1 Answers

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.

like image 152
DevSolar Avatar answered Sep 22 '25 09:09

DevSolar