基于ARM平台分析Linux系统调用过程
Linux 3.10.44 + ARM V7 + Android:4.4.2
一 open
以open系统调用为例在bionic中的入口代码位于bionic/libc/bionic/open.c中,源代码如下:
int open(const char *pathname, int flags, ...)
{
mode_t mode = 0;
flags |= O_LARGEFILE;
if (flags & O_CREAT)
{
va_list args;
va_start(args, flags);
mode = (mode_t) va_arg(args, int);
va_end(args);
}
return __open(pathname, flags, mode);
}
仅在创建新文件时,mode参数才有作用。
二 __open
代码位于bionic/libc/arch-arm/syscalls/__open.S中,源代码如下:
ENTRY(__open)
mov ip, r7
ldr r7, =__NR_open
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
END(__open)
首先将r7内容保存到ip寄存器中,将系统调用号放到R7中,然后调用SWI(软中断,已更新成SVC)指令陷入内核模式,后边的处理就交给内核了。从内核返回后首先做的就是恢复R7寄存器,然后判断调用是否成功,如果失败的话设置errno。
三 vector_swi
异常处理的代码位于arch/arm/kernel/entry-armv.S,摘取如下:
__vectors_start:
W(b) vector_rst
W(b) vector_und
W(ldr) pc, __vectors_start + 0x1000
W(b) vector_pabt
W(b) vector_dabt
W(b) vector_addrexcptn
W(b) vector_irq
W(b) vector_fiq
在0x08偏移处的指令是将__vectors_start + 0x1000地址中的内容复制给PC,那么该地址是什么值呢?参考该文件下边的内容,该操作执行后会调用到vector_swi中执行。
.section .stubs, "ax", %progbits
__stubs_start:
@ This must be the first word
.word vector_swi
vector_swi源代码位于arch/arm/kernel/entry-common.S
S_FRAME_SIZE及S_PC定义在arch/arm/kernel/asm-offsets.c和arch/arm/include/uapi/asm/ptrace.h中,参考如下定义,整个frame包含18个寄存器,除了r0~r15外再增加cpsr和原r0。
#ifndef __KERNEL__
struct pt_regs {
long uregs[18];
};
#endif /* __KERNEL__ */
#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]
以下是SWI handler去掉一些宏开关,在CONFIG_OABI_COMPAT和CONFIG_ARM_THUMB都设置为Y情况下的代码。
/*===================================