第一章 跳转指令的分类
是否需要条件
有条件跳转
jz jnz jo jno jb ...
无条件跳转
jmp loop call ret
跳转地址
Jmp near
跳转地址为 下一条指令的地址 + 偏移 , 模块内的跳转用jmp near
Jmp far
跳转地址 存储在内存或寄存器中,模块间的跳转用Jmp far,地址可能存储在.got或.got.plt中 (got的作用就是dynamic object的地址, 比如当一个dynamic object的地址多次被引用时,如果没有got, 那么就要多次重定位 )
第二章 syscall
概述
syscall用作系统调用, rax寄存器用作传入系统调用号, 系统调用号可在/usr/include/asm/unistd.h(真实文件分别为unistd_32.h 和unistd_64.h)中查到。C库中有 int syscall(int number, …);的wrapper
function。其中一些系统调用在C库中有wrapper function, 比如open, close之类。当没有直接的wrapper function时, 可以用C库中的syscall或直接用汇编来调用系统调用。
syscall指令的调用约定(64位系统)
rax 系统调用号
rcx 返回地址
rdi rsi rdx r10 r8 r9 (fastcall rcx替换成 r10)
返回值 rax
syscall的运行方式
系统调用的注册使用了IA32_LSTAR寄存器, 当执行syscall时, 跳到IA32_LSTAR寄存器值的地址处。写该寄存器使用wrmsr指令, ecx传IA32_LSTAR的地址(0xc0000082)
当没有开启PTI时,IA32_LSTAR的值为entry_SYSCALL_64,当有系统调用时, 调用堆栈为
sys_call_table[sysno]
do_syscall_64
entry_SYSCALL_64.
PS:当在查一个系统调用的源码时可能搜不到, 因为函数名用了宏,如read系统调用, 用了SYSCALL_DEFINE3