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