系统调用入口函数源码分析system_call——X86_64

在实验中用到这一块,就去看源码分析整理了一下,全部为个人理解。有错误的地方,希望和大牛交流。大笑

首先解释一下,我实验的目的是获得系统调用入口函数system_call的起始地址和函数大小。

在linux-3.10.1, x86 64位的系统下,系统调用的入口地址保存在MSR寄存器中,通过rdmsrl(MSR_LSTAR,ksystem_call);便可获得系统调用的入口地址,然后对该入口地址进行解析得到入口函数为system_call,具体的函数实现在/linux-3.10.1/arch/x86/kernel/entry_64.S文件中。

Entry_64.S为一个汇编文件,即system_call函数是有汇编语言实现的,在ENTRY(system_call)与END(system_call)之间有很对其他的函数定义和调用,与C语言程序的结构不同,因此system_call以及它内部包含的所有的内核函数的符号信息都保存在kallsyms文件系统中,因此根据内核栈中的返回地址查询kallsyms得到的内核符号可能只是真正调用函数内部的一个中间函数,通过实验我们也验证了这个猜想,这也是在实验中根据内核函数中一个地址本该获得的内核符号为system_call,结果得到的却是system_call_fast_path的原因。

对system_call的函数实现分析之后我们得到图1的处理流程:


图1 system_call的处理过程

为了获取到正确的内核函数信息,在内核模块中使用kallsyms_lookup_name()函数以system_call为参数可以获得它对应的内核符号信息,在得到system_call结束后的第一个函数对应的地址信息,即可计算出system_call函数所占空间大小。

对于宿主机的系统调用表以及其他内核符号的信息,使用相同的方法获取。


下面是对system_call汇编源码的一些注释:

/*
 * System call entry. Up to 6 arguments in registers are supported.
 *
 * SYSCALL does not save anything on the stack and does not change the
 * stack pointer.  However, it does mask the flags register for us, so
 * CLD and CLAC are not needed.
 */

/*
 * Register setup:
 * rax  system call number
 * rdi  arg0
 * rcx  return address for syscall/sysret, C arg3
 * rsi  arg1
 * rdx  arg2
 * r10  arg3 (--> moved to rcx for C)
 * r8   arg4
 * r9   arg5
 * r11  eflags for syscall/sysret, temporary for C
 * r12-r15,rbp,rbx saved by C code, not touched.
 *
 * Interrupts are off on entry.
 * Only called from user space.
 *
 * XXXif we had a free scratch register we could save the RSP into the stack frame
 *      and report it properly in ps. Unfortunately we haven't.
 *
 * When user can change the frames always force IRET. That is because
 * it deals with uncanonical addresses better. SYSRET has trouble
 * with them due to bugs in both AMD and Intel CPUs.
 */

ENTRY(system_call)
CFI_STARTPROCsimple
CFI_SIGNAL_FRAME
CFI_DEF_CFArsp,KERNEL_STACK_OFFSET
CFI_REGISTERrip,rcx
/*CFI_REGISTERrflags,r11*/
SWAPGS_UNSAFE_STACK
//上面的几行代码执行了swapgs指令。修改gs寄存器从用户态切换到内核态,其实就是修改运行级别
/*
 * A hypervisor implementation might want to use a label
 * after the swapgs, so that it can do the swapgs
 * for the guest and jump here on syscall.
 */
GLOBAL(system_call_after_swapgs)

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值