首页
社区
课程
招聘
[分享]linux arm 系统调用
发表于: 2015-1-9 11:09 7310

[分享]linux arm 系统调用

2015-1-9 11:09
7310
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直播授课

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 3
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
高大上啊,学学习了
2015-1-9 14:28
0
游客
登录 | 注册 方可回帖
返回
//