Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
系统调用包装器ASMC_C_Assembly_Arm_Wrapper_System Calls - Fatal编程技术网

系统调用包装器ASMC

系统调用包装器ASMC,c,assembly,arm,wrapper,system-calls,C,Assembly,Arm,Wrapper,System Calls,有人能给我解释一下这段代码吗? 另外,请给我一些链接/网址,我可以知道更多关于这个? 此代码用作覆盖库中“extern int errno”的包装器。有人能给我解释一下这个函数,并告诉我为什么在一些系统调用中需要包装器吗?哪些也被称为弱点 #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

有人能给我解释一下这段代码吗? 另外,请给我一些链接/网址,我可以知道更多关于这个? 此代码用作覆盖库中“extern int errno”的包装器。有人能给我解释一下这个函数,并告诉我为什么在一些系统调用中需要包装器吗?哪些也被称为弱点

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

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

此代码更新您的errno副本,而不是C库的。执行“syscall”意味着触发内核执行特殊活动。由于内核在不同的地址空间中运行,因此不能通过简单的函数调用来实现

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

但是,在任何情况下,都不能像C函数调用那样简单地向内核传递大量参数。但是,您可以将参数值放入某些寄存器中。这些寄存器是什么,以及内核如何解释它们的内容,同样是特定于所讨论的操作系统的

由于您既不能访问特定的寄存器,也不能调用上面提到的任何内核触发方法,因此在普通C代码中,可以使用系统调用包装器,这些包装器被称为C函数,然后将参数放在寄存器中,并使用ASM代码触发内核


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

他的代码中没有errno声明,因此您可能无法确定实际更新了哪个errno。注意,这不是内核中的系统调用实现,而是C库中的某种包装器几乎总是错误的,因为规范要求
errno
是一个宏,如果您已经在某个地方有了另一个定义,则错误更大。GNU C库使用
(*(\uu errno\u location())
或类似的表达式来查找
errno
的线程本地实现,因此不会与另一个
errno
发生符号冲突,因此错误不会被检测到。正确,SWI是软件中断。