因为想跟踪下在新建进程时,如何处理新建进程的vruntime,所以跟踪了下fork。

以glic-2.17中ARM为例(unicore架构的没找到),实际上通过寄存器向系统调用传递的参数为:

r7: __NR_clone 120

r0: CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD

r1: NULL

r2: NULL

r3: NULL

r4: &THREAD_SELF->tid

fork()---->__fork()---->__libc_fork()

__libc_fork()---->INLINE_SYSCALL (clone, , \
CLONE_CHILD_SETTID | \
CLONE_CHILD_CLEARTID | \
SIGCHLD, \
NULL, NULL, NULL, &THREAD_SELF->tid)
#define INLINE_SYSCALL(name, nr, args...)  \
({ unsigned int _sys_result = \
                  INTERNAL_SYSCALL (name, , nr, args); \
if (__builtin_expect \
                (INTERNAL_SYSCALL_ERROR_P (_sys_result, ), )) \
{ \
__set_errno (INTERNAL_SYSCALL_ERRNO \
                            (_sys_result, )); \
_sys_result = (unsigned int) -; \
} \
(int) _sys_result; })
#define INTERNAL_SYSCALL(name, err, nr, args...)   \
INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args) //#define __NR_clone 120
#define SYS_ify(syscall_name) (__NR_##syscall_name)
//err没用使用,也没有传递宏参,第一次见到
# define INTERNAL_SYSCALL_RAW(name, err, nr, args...) \
({ \
register int _a1 asm ("r0"), _nr asm ("r7"); \
LOAD_ARGS_##nr (args) \
_nr = name; \
asm volatile ("swi 0x0 @ syscall " #name \
: "=r" (_a1) \
: "r" (_nr) ASM_ARGS_##nr \
: "memory"); \
_a1; })

关于宏INTERAL_SYSCALL_RAW还是满有意思的,写了个函数测试下,真实的看下库如何向系统调用传参:

#define LOAD_ARGS_0()
#define ASM_ARGS_0 #define LOAD_ARGS_1(a1) \
int _a1tmp = (int)(a1); \
LOAD_ARGS_0 () \
_a1 = _a1tmp; #define ASM_ARGS_1 ASM_ARGS_0, "r" (_a1) #define LOAD_ARGS_2(a1, a2) \
int _a2tmp = (int)(a2); \
LOAD_ARGS_1(a1) \
register int _a2 asm ("a2") = _a2tmp; #define ASM_ARGS_2 ASM_ARGS_1, "r" (_a2) #define LOAD_ARGS_3(a1, a2, a3) \
int _a3tmp = (int)(a3); \
LOAD_ARGS_2 (a1, a2) \
register int _a3 asm ("a3") = _a3tmp; #define ASM_ARGS_3 ASM_ARGS_2, "r" (_a3) #define LOAD_ARGS_4(a1, a2, a3, a4) \
int _a4tmp = (int) (a4); \
LOAD_ARGS_3 (a1, a2, a3) \
register int _a4 asm ("a4") = _a4tmp; #define ASM_ARGS_4 ASM_ARGS_3, "r" (_a4) #define LOAD_ARGS_5(a1, a2, a3, a4, a5) \
int _v1tmp = (int)(a5); \
LOAD_ARGS_4 (a1, a2, a3, a4) \
register int _v1 asm ("v1") = _v1tmp; #define ASM_ARGS_5 ASM_ARGS_4, "r" (_v1) #define INTERNAL_SYSCALL_RAW(name, err, nr, args...) \
({ \
register int _a1 asm("r0"), _nr asm("r7"); \
LOAD_ARGS_5 (args) \
_nr = name; \
asm volatile ("swi 0x0" \
: "=r" (_a1) \
: "r" (_nr) ASM_ARGS_##nr \
: "memory" \
); \
_a1; \
}) void test(void)
{
INTERNAL_SYSCALL_RAW(, , , , , , , );
}

预处理后即为:

void test(void)
{
({
register int _a1 asm("r0"), _nr asm("r7");
int _v1tmp = (int)();
int _a4tmp = (int) ();
int _a3tmp = (int)();
int _a2tmp = (int)();
int _a1tmp = (int)();
_a1 = _a1tmp;
register int _a2 asm ("a2") = _a2tmp;
register int _a3 asm ("a3") = _a3tmp;
register int _a4 asm ("a4") = _a4tmp;
register int _v1 asm ("v1") = _v1tmp;
_nr = ;
asm volatile (
"swi 0x0"
: "=r" (_a1)
: "r" (_nr) , "r" (_a1), "r" (_a2),
                       "r" (_a3), "r" (_a4), "r" (_v1)
: "memory"
);
_a1;
});
}

相应的汇编代码:

test:
stmfd sp!, {r4, r7, fp}
add fp, sp, #
sub sp, sp, # mov r3, #
str r3, [fp, #-] mov r3, #
str r3, [fp, #-] mov r3, #
str r3, [fp, #-] mov r3, #
str r3, [fp, #-] mov r3, #
str r3, [fp, #-] ldr r0, [fp, #-]
ldr r1, [fp, #-]
ldr r2, [fp, #-]
ldr r3, [fp, #-]
ldr r4, [fp, #-]
mov r7, #
#APP
@ "go.c"
swi 0x0
@ ""
sub sp, fp, #
ldmfd sp!, {r4, r7, fp}
bx lr
05-06 08:40