我解析了最后一个libc中的系统调用调用:
git clone git://sourceware.org/git/glibc.git
我在sysdeps/unix/sysv/linux/i386/sysdep.h文件中发现了下面的代码:
# define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
LOADREGS_##nr(args) \
asm volatile ( \
"call *%%gs:%P2" \
: "=a" (resultvar) \
: "a" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo)) \
ASMARGS_##nr(args) : "memory", "cc")
如果我理解正确的话,LOADREGS_##nr(args) 宏将参数加载到 ebx、ecx、edx、esi、edx 和 ebp 寄存器中。
sysdeps/unix/sysv/linux/i386/sysdep.h
# define LOADREGS_0()
# define ASMARGS_0()
# define LOADREGS_1(arg1) \
LOADREGS_0 ()
# define ASMARGS_1(arg1) \
ASMARGS_0 (), "b" ((unsigned int) (arg1))
# define LOADREGS_2(arg1, arg2) \
LOADREGS_1 (arg1)
# define ASMARGS_2(arg1, arg2) \
ASMARGS_1 (arg1), "c" ((unsigned int) (arg2))
# define LOADREGS_3(arg1, arg2, arg3) \
LOADREGS_2 (arg1, arg2)
# define ASMARGS_3(arg1, arg2, arg3) \
ASMARGS_2 (arg1, arg2), "d" ((unsigned int) (arg3))
# define LOADREGS_4(arg1, arg2, arg3, arg4) \
LOADREGS_3 (arg1, arg2, arg3)
# define ASMARGS_4(arg1, arg2, arg3, arg4) \
ASMARGS_3 (arg1, arg2, arg3), "S" ((unsigned int) (arg4))
# define LOADREGS_5(arg1, arg2, arg3, arg4, arg5) \
LOADREGS_4 (arg1, arg2, arg3, arg4)
# define ASMARGS_5(arg1, arg2, arg3, arg4, arg5) \
ASMARGS_4 (arg1, arg2, arg3, arg4), "D" ((unsigned int) (arg5))
# define LOADREGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
register unsigned int _a6 asm ("ebp") = (unsigned int) (arg6); \
LOADREGS_5 (arg1, arg2, arg3, arg4, arg5)
# define ASMARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
ASMARGS_5 (arg1, arg2, arg3, arg4, arg5), "r" (_a6)
#endif /* GCC 5 */
enter code here
代码中在哪里将参数加载到寄存器 ebx、ecx、edx、esi、edx 和 ebp 中?是上面的代码吗?我不理解实现方式。 下面的代码将第六个参数加载到 ebx 寄存器中吗?
register unsigned int _a6 asm ("ebp") = (unsigned int) (arg6);
这段代码的含义是什么:
ASMARGS_0 (), "b" ((unsigned int) (arg1))
它将第一个参数加载到ebx寄存器中?
然后,“call *%%gs:%P2”跳转到VDSO代码?这段代码对应于“call *gs:0x10”吗?
所以,下面这个关于write系统调用的图示,正确吗?
write(1, "A", 1) -----> LIBC -----> VDSO -----> KERNEL
load reg ?
jump to vdso
|---------------------------------------------------|--------------|
user land kernel land
我不理解VDSO实用程序!vdso选择syscall方法(sysenter或int 0x80)。
非常感谢您的帮助。对不起,我的英语很糟糕。