linux arm框架下所有的系统调用都是通过SWI来实现的,因为在ARM 架构中有两个SWI指令,分别针对EABI和OABI (关于EABI和OABI 大家可以搜索相关资料,它们是Linux针对ARM架构的两种系统调用指令)
[EABI]
机器码:1110 1111 0000 0000 -- SWI 0
具体的调用号存放在寄存器r7中.
[OABI]
机器码:1101 1111 vvvv vvvv -- SWI immed_8
调用号进行转换以后得到指令中的立即数。立即数=调用号 | 0x900000
//这里是系统调用的宏
#include <asm/unistd.h>
//打开此文件我们看看里面的内容,这个可以看出系统调用号的基址
#define __NR_OABI_SYSCALL_BASE 0x900000
#if defined(__thumb__) || defined(__ARM_EABI__)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define __NR_SYSCALL_BASE 0
#else
#define __NR_SYSCALL_BASE __NR_OABI_SYSCALL_BASE
#endif
//下面我们来看看前面几个系统调用号
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#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)
如果我们希望在ptrace的时候知道目标进程当前是否在系统调用中,而且是处于什么系统调用中,我们需要下面一个方法来解析PTRACE_ATTACH后的系统调用状态
long getSysCallNo(int pid)
{
long scno = 0;
struct pt_regs regs;
ptrace(PTRACE_GETREGS, pid, NULL, ®s);
scno = ptrace(PTRACE_PEEKTEXT, pid, (void *)(regs.ARM_pc - 4), NULL);
if(scno == 0)
return 0;
/* Handle the EABI syscall convention. We do not
bother converting structures between the two
ABIs, but basic functionality should work even
if strace and the traced program have different
ABIs. */
if (scno == 0xef000000) {
scno = regs.ARM_r7;
} else {
if ((scno & 0x0ff00000) != 0x0f900000) {
return -1;
}
/*
* Fixup the syscall number
*/
scno &= 0x000fffff;
}
return scno;
}
int main(){
long scno=0;
struct pt_regs regs;
int pid = xxxxx;
if(0 != ptrace(PTRACE_ATTACH, pid, NULL, NULL))
{
printf("Trace process failed:%d.\n", errno);
return 1;
}
while(1)
{
wait(&status);
if(WIFEXITED(status))
{
break;
}
scno = getSysCallNo(pid, ®s);
if(scno == __NR_fork){
//这就表示目标进程当前正在做fork的系统调用
}
}
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课