strace
在开始之前,我们先看一看strace的实现骨架。Ptrace一直都没有相应的使用标准,但在不同的操作系统中它的接口都是类似的,尤其是它的核心功能,但多多少少都会有一些细微的差别。Ptrace(2)的原型类似如下:
long ptrace(int request, pid_t pid, void *addr, void *data);
pid
是tracee
的进程ID,一个tracee
一次只能绑定一个tracer
,但一个tracer
可以绑定多个tracee
。
request
域负责选择一个指定的Ptrace
函数,例如ioctl(2)
接口。对于strace
来说,只有下面是必须的:
PTRACE_TRACEME
:它的父进程必须跟踪这个进程。
PTRACE_SYSCALL
:继续运行,但是会在下一个系统调用入口暂停运行。
PTRACE_GETREGS
:获取tracee
的寄存器备份。
另外两个数据域,即addr
和data
,它们负责给选定的Ptrace
函数提供参数,一般这两个数据都可以忽略,这里我选择传入0。
strace
接口本质上是其他命令的前缀:
$strace [strace options] program [arguments]
我的最小化配置不包含任何参数,所以要做的第一件事就是假设它至少包含一个参数(fork(2)),通过argv传递。
在加载目标程序之前,新的进程会告知内核它的父进程将会对它进行跟踪监视,tracee
将会被这个Ptrace
系统调用挂起:
pid_tpid = fork();
switch(pid) {
case -1: /* error */
FATAL("%s", strerror(err