系统调用
内核实现了很多系统调用函数,为每个函数提供一个标识,也就是系统调用号,在不同的架构中可能不同。
通过syscall(2) man page可以看到完整的系统调用列表
系统调用的执行流程:
- 用户程序调用C库或者直接通过自身的汇编指令进行系统调用,需要传递的变量及系统的调用编号保存在CPU寄存器中;
- 进程进入内核态,通过寄存器保存的系统调用编号识别系统函数,并执行系统调用;
- 系统调用结束后,结果、返回值和参数保存在寄存器,用户程序获取结果
go提供了syscall包直接通过汇编代码进行系统调用。
ptrace
定义
long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
- pid:要跟踪的进程ID
- request:使用的ptrace请求
Go - syscall
数据结构
寄存器数据:syscall.PtraceRegs
状态数据:syscall.WaitStatus
封装的系统调用
PTRACE_ATTACH:func PtraceAttach(pid int) (err error)
PTRACE_DETACH:func PtraceDetach(pid int) (err error)
PTRACE_SYSCALL:func PtraceSyscall(pid int, signal int) (err error)
PTRACE_GETREGS:func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error)
等待状态改变:func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error)
存储位置
参考:https://man7.org/linux/man-pages/man2/syscall.2.html
x86_64
Orig_rax:系统调用时系统调用号
Rax:返回时返回值
regs.rdi - Stores the first argument
regs.rsi - Stores the second argument
regs.rdx - Stores the third argument
regs.r10 - Stores the fourth argument
regs.r8 - Stores the fifth argument
regs.r9 - Stores the sixth argument
arm/EABI
调用参数r0-r6
返回值r0,r1
调用号r7
读取方式
文件描述符int fd,通过/proc/pid/fd/%llu来读取filepath
sprintf(fdpath,"/proc/%u/fd/%llu",proc,regs.rdi);
size = readlink(fdpath, filepath, 256); //this gives the filepath for a particular fd
filepath[size] = '\0';
printf("File-%s-\n", filepath);
指向缓冲区的指针void *buf,通过PTRACE_PEEKDATA / PTRACE_PEEKTEXT读取,ptrace一次返回8字节,所以要迭代读取数据,同时需要一个指针指向内存的开始位置,用于后续读取字符串。比如read参数第二个参数指示缓冲区位置,第三个参数指示长度
char message[1000];
char* temp_char2 = message;
int j = 0;
long temp_long;
while( j < (regs.rdx/8) ) //regs.rdx stores the size of the input buffer
{
temp_long = ptrace(PTRACE_PEEKDATA, proc, regs.rsi + (j*8) , NULL);
memcpy(temp_char2, &temp_long, 8);
temp_char2 += sizeof(long);
++j;
}
message[regs.rdx] = '\0';
printf("Message-%s-\n\n", message);
参考链接
https://github.com/eaburns/ptrace
LinuGo - 用Go看到进程中发生的系统调用
linux 系统调用号表
ptrace手册
Linux System Call Table for x86 64
Extracting system call name and arguments using ptrace
strace 源码分析 (快速分析源码,半小时搞懂)
ptrace函数深入分析
strace 是如何工作的
go语言类似strace的项目
jfrabaute/libtrace
jfrabaute/gotrace
eaburns/ptrace
agis/gtrace(看起来还可以)
maebashi/go-strace
hugelgupf/go-strace(这个库很不错)
hugelgupf/go-strace/strace 文档