系统调用流程梳理
#define __NR_SYSCALL_BASE __NR_OABI_SYSCALL_BASE
//提供给应用层使用
#define __NR_restart_syscall (__NR_SYSCALL_BASE+ 0)
#define __NR_exit (__NR_SYSCALL_BASE+ 1)
#define __NR_fork (__NR_SYSCALL_BASE+ 2)
#define __NR_read (__NR_SYSCALL_BASE+ 3)
#define __NR_write (__NR_SYSCALL_BASE+ 4)
#define __NR_open (__NR_SYSCALL_BASE+ 5)
#define __NR_close (__NR_SYSCALL_BASE+ 6)
......
#define __NR_setns (__NR_SYSCALL_BASE+375)
#define __NR_process_vm_readv (__NR_SYSCALL_BASE+376)
#define __NR_process_vm_writev (__NR_SYSCALL_BASE+377)
scno .req r7 @ syscall number
tbl .req r8 @ syscall table pointer
why .req r8 @ Linux syscall (!= 0)
tsk .req r9 @ current thread_info
#define S_R0 0 /* offsetof(struct pt_regs, ARM_r0) @ */
#define S_R1 4 /* offsetof(struct pt_regs, ARM_r1) @ */
#define S_R2 8 /* offsetof(struct pt_regs, ARM_r2) @ */
#define S_R3 12 /* offsetof(struct pt_regs, ARM_r3) @ */
#define S_R4 16 /* offsetof(struct pt_regs, ARM_r4) @ */
#define S_R5 20 /* offsetof(struct pt_regs, ARM_r5) @ */
#define S_R6 24 /* offsetof(struct pt_regs, ARM_r6) @ */
#define S_R7 28 /* offsetof(struct pt_regs, ARM_r7) @ */
#define S_R8 32 /* offsetof(struct pt_regs, ARM_r8) @ */
#define S_R9 36 /* offsetof(struct pt_regs, ARM_r9) @ */
#define S_R10 40 /* offsetof(struct pt_regs, ARM_r10) @ */
#define S_FP 44 /* offsetof(struct pt_regs, ARM_fp) @ */
#define S_IP 48 /* offsetof(struct pt_regs, ARM_ip) @ */
#define S_SP 52 /* offsetof(struct pt_regs, ARM_sp) @ */
#define S_LR 56 /* offsetof(struct pt_regs, ARM_lr) @ */
#define S_PC 60 /* offsetof(struct pt_regs, ARM_pc) @ */
#define S_PSR 64 /* offsetof(struct pt_regs, ARM_cpsr) @ */
#define S_OLD_R0 68 /* offsetof(struct pt_regs, ARM_ORIG_r0) @ */
#define S_FRAME_SIZE 72 /* sizeof(struct pt_regs) @ */
linux-3.5/arch/arm/include/asm/ptrace.h
struct pt_regs {
unsigned long uregs[18];
#define ARM_cpsr uregs[16]
#define ARM_pc uregs[15]
#define ARM_lr uregs[14]
#define ARM_sp uregs[13]
#define ARM_ip uregs[12]
#define ARM_fp uregs[11]
#define ARM_r10 uregs[10]
#define ARM_r9 uregs[9]
#define ARM_r8 uregs[8]
#define ARM_r7 uregs[7]
#define ARM_r6 uregs[6]
#define ARM_r5 uregs[5]
#define ARM_r4 uregs[4]
#define ARM_r3 uregs[3]
#define ARM_r2 uregs[2]
#define ARM_r1 uregs[1]
#define ARM_r0 uregs[0]
#define ARM_ORIG_r0 uregs[17]
/* 0 */ CALL(sys_restart_syscall)
CALL(sys_exit)
CALL(sys_fork_wrapper)
CALL(sys_read)
CALL(sys_write)
/* 5 */ CALL(sys_open)
......
/* 375 */ CALL(sys_setns)
CALL(sys_process_vm_readv)
CALL(sys_process_vm_writev)
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls @第一次才会执行(NR_syscalls==1),syscalls_padding=3,保证以4对齐
#define syscalls_counted
#endif
.rept syscalls_padding
CALL(sys_ni_syscall)
.endr
.equ NR_syscalls,0
#define CALL(x) .equ NR_syscalls,NR_syscalls+1
#include "calls.S"
#undef CALL
#define CALL(x) .long x
* This is the syscall table declaration for native ABI syscalls.
* With EABI a couple syscalls are obsolete and defined as sys_ni_syscall.
*/
#define ABI(native, compat) native
#ifdef CONFIG_AEABI
#define OBSOLETE(syscall) sys_ni_syscall
#else
#define OBSOLETE(syscall) syscall
#endif
.type sys_call_table, #object
ENTRY(sys_call_table)
#include "calls.S"
#undef ABI
#undef OBSOLETE
.align 5
ENTRY(vector_swi)
/****************************将中断发生前的寄存器状态备份入栈**********/
sub sp, sp, #S_FRAME_SIZE @在栈上开辟18*4的空间备份跳转之前的寄存器值
stmia sp, {r0 - r12} @ Calling r0 - r12,备份r0 - r12寄存器
ARM( add r8, sp, #S_PC )
ARM( stmdb r8, {sp, lr}^ ) @ Calling sp, lr
mrs r8, spsr @ called from non-FIQ mode, so ok. 将CPSR的值存在r8中
str lr, [sp, #S_PC] @ Save calling PC
str r8, [sp, #S_PSR] @ Save CPSR
str r0, [sp, #S_OLD_R0] @ Save OLD_R0 备份r0到栈空间中r17的位置(因为没有SPSR 所以这里多备份了一个r0,估计是为了标准化)
zero_fp @清空fp寄存器r11
/*
* Get the system call number.
*/
#if defined(CONFIG_OABI_COMPAT)
/*
* If we have CONFIG_OABI_COMPAT then we need to look at the swi
* value to determine if it is an EABI or an old ABI call.
*/
#ifdef CONFIG_ARM_THUMB
tst r8, #PSR_T_BIT
movne r10, #0 @ no thumb OABI emulation
ldreq r10, [lr, #-4] @ get SWI instruction
#else
ldr r10, [lr, #-4] @ get SWI instruction // get SWI instruction 利用lr取得swi指令的内容
//跳转前code段的内存{地址:内容:流水级},从下面的内存分布可以清楚看出lr - 4的含义
//{0x8:xxx:fetch<--pc},{0x4:xxx:decode<--lr},{0x0:swi num:exe}
#endif
#ifdef CONFIG_CPU_ENDIAN_BE8
rev r10, r10 @ little endian instruction
#endif
#elif defined(CONFIG_AEABI)
/*
* Pure EABI user space always put syscall number into scno (r7).
*/
#elif defined(CONFIG_ARM_THUMB)
/* Legacy ABI only, possibly thumb mode. */
tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs
addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in
ldreq scno, [lr, #-4]
#else
/* Legacy ABI only. */
ldr scno, [lr, #-4] @ get SWI instruction
#endif
/************为进入syscall具体函数做准备,主要是使调用符合ATPCS规范***********/
#ifdef CONFIG_ALIGNMENT_TRAP
ldr ip, __cr_alignment
ldr ip, [ip] //?
mcr p15, 0, ip, c1, c0 @ update control registe 读ip中的数据到c1
#endif
enable_irq
get_thread_info tsk
adr tbl, sys_call_table @ load syscall table pointer
#if defined(CONFIG_OABI_COMPAT)
/*
* If the swi argument is zero, this is an EABI call and we do nothing.
*
* If this is an old ABI call, get the syscall number into scno and
* get the old ABI syscall table address.
*/
bics r10, r10, #0xff000000
eorne scno, r10, #__NR_OABI_SYSCALL_BASE
ldrne tbl, =sys_oabi_call_table
#elif !defined(CONFIG_AEABI)
bic scno, scno, #0xff000000 @ mask off SWI op-code
eor scno, scno, #__NR_SYSCALL_BASE @ check OS number
#endif
ldr r10, [tsk, #TI_FLAGS] @ check for syscall tracing
stmdb sp!, {r4, r5} @ push fifth and sixth args
#ifdef CONFIG_SECCOMP
tst r10, #_TIF_SECCOMP
beq 1f
mov r0, scno
bl __secure_computing
add r0, sp, #S_R0 + S_OFF @ pointer to regs
ldmia r0, {r0 - r3} @ have to reload r0 - r3
1:
#endif
tst r10, #_TIF_SYSCALL_WORK @ are we tracing syscalls?
bne __sys_trace
cmp scno, #NR_syscalls @ check upper syscall limit
adr lr, BSYM(ret_fast_syscall) @ return address
ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine PC = *(tbl+(scno<<2))
add r1, sp, #S_OFF
2: mov why, #0 @ no longer a real syscall
cmp scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE)
eor r0, scno, #__NR_SYSCALL_BASE @ put OS number back
bcs arm_syscall
b sys_ni_syscall @ not private func
open()->SYSCALL_DEFINE3(open, ...)->do_sys_open()->do_filp_open()->
path_openat()->do_last()->nameidata_to_filp()->do_dentry_open()->open(inode, f)