1 概述
相比Intel支持的快速系统调用指令sysenter/sysexit,AMD对应的是syscall/sysret,不过现在,Intel也兼容这两条指令。
测试环境:
Ubuntu 12.04
Ubuntu 16.04 64
2 传统系统调用int 0x80
只用于32位系统,64位系统上不起作用;
系统调用号和返回结果
EAX指定要调用的函数(系统调用号)
EBX传递函数的第一个参数
ECX传递函数的第二个参数
EDX传递函数的第三个参数
返回值EAX
示例
3 32位系统调用sysenter
3.1 系统调用
系统调用号:
sys/syscall.h
/usr/include/i386-linux-gnu/asm/unistd_32.h
如:
#define __NR_getuid 24
#define __NR_getuid32 199
参数:
EAX指定要调用的函数(系统调用号)
EBX传递函数的第一个参数
ECX传递函数的第二个参数
EDX传递函数的第三个参数
ESI
EDI
EBP
返回值EAX
静态链接时,采用"call *_dl_sysinfo"指令;
动态链接时,采用"call *%gs:0x10"指令;
最终调用的是VDSO(linux-gate.so.1)中的__kernel_vsyscall函数;
__kernel_vsyscall函数包含sysenter指令;
syscall()函数也是类似的,根据静态/动态链接的不同分别采用的不同的指令,最终调用__kernel_vsyscall函数;
3.2 静态链接实例
millionsky@ubuntu-12:~/tmp$ gcc getuid_glibc.c -static millionsky@ubuntu-12:~/tmp$ gdb ./a.out (gdb) b main Breakpoint 1 at 0x8048ee3 (gdb) r Starting program: /home/millionsky/tmp/a.out
Breakpoint 1, 0x08048ee3 in main () (gdb) disass Dump of assembler code for function main: 0x08048ee0 <+0>: push %ebp 0x08048ee1 <+1>: mov %esp,%ebp => 0x08048ee3 <+3>: and $0xfffffff0,%esp 0x08048ee6 <+6>: sub $0x10,%esp 0x08048ee9 <+9>: call 0x8053c00 <getuid> |