x86中的系统调用表(ia32)

时间:2014-11-17 23:18:06

标签: c assembly linux-kernel x86 system-calls

我正在研究如何在内核代码中实现系统调用,并且我专注于x86架构,但是,我很难理解汇编代码和部分系统调用表的进入(或调用函数?)(就我所知,entry.S文件使用宏来"准备"用于系统调用),以及& #39;一个神秘的是:

ia32_do_call:
  IA32_ARG_FIXUP
  call *ia32_sys_call_table(,%rax,8) # xxx: rip relative

由于我使用网站lxr.free-electrons.com,我使用自由文本搜索来查看该功能是如何实现的,以便进一步理解。我碰到过这个:

const sys_call_ptr_t ia32_sys_call_table[__NR_ia32_syscall_max+1] = {
   /*
    * Smells like a compiler bug -- it doesn't work 
    * when the & below is removed.
    */
    [0 ... __NR_ia32_syscall_max] = &compat_ni_syscall,
#include <asm/syscalls_32.h>
};

这里发生了什么?

1 个答案:

答案 0 :(得分:1)

我也对该文件感到惊讶,因此,如果您到达这里,我会留下一些指针来帮助您。

首先,sys_call_ptr_tinclude/asm/syscall.h中定义为:

typedef long (*sys_call_ptr_t)(const struct pt_regs *);

因此,ia32_sys_call_table是我们所期望的函数指针数组。接下来,使用称为designated initializers的gcc扩展名初始化该数组(由于this question)。初始化的第一部分将表的每个条目都指向一个名为sys_ni_syscall的函数(我很确定,它似乎是通过一堆宏来创建的……)。这是在文件kernel/sys_ni.c中定义的:

/*                                                   
 * Non-implemented system calls get redirected here. 
 */                                                  
asmlinkage long sys_ni_syscall(void)                 
{                                                    
    return -ENOSYS;                                  
}                                                    

最后,通过查看两件事可以理解文件<asm/syscalls_32.h>的包含。首先,转到entry/syscalls/,然后运行

bash syscalltbl.sh syscall_32.tbl gen.c

并查看gen.c的内容。现在,从entry/syscall_32.c看这个宏:

#define __SYSCALL_I386(nr, sym) [nr] = __ia32_##sym,

在这一点上,也许还有一些grep,这个文件应该不会那么神秘。