因为想跟踪下在新建进程时,如何处理新建进程的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, 5, \ 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, ), 0)) \ { \ __set_errno (INTERNAL_SYSCALL_ERRNO \
(_sys_result, )); \ _sys_result = (unsigned int) -1; \ } \ (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(120, , 5, 6, 7, 8, 9, 0); }
预处理后即为:
void test(void) { ({ register int _a1 asm("r0"), _nr asm("r7"); int _v1tmp = (int)(0); int _a4tmp = (int) (9); int _a3tmp = (int)(8); int _a2tmp = (int)(7); int _a1tmp = (int)(6); _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 = 120; 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, #8 sub sp, sp, #28 mov r3, #0 str r3, [fp, #-32] mov r3, #9 str r3, [fp, #-28] mov r3, #8 str r3, [fp, #-24] mov r3, #7 str r3, [fp, #-20] mov r3, #6 str r3, [fp, #-16] ldr r0, [fp, #-16] ldr r1, [fp, #-20] ldr r2, [fp, #-24] ldr r3, [fp, #-28] ldr r4, [fp, #-32] mov r7, #120 #APP @ 16 "go.c" 1 swi 0x0 @ 0 "" 2 sub sp, fp, #8 ldmfd sp!, {r4, r7, fp} bx lr