一个更好的解释见How Debuggers Work Part 1,但总的来说,没有,也不会直到tracee接收的信号跟踪do_something()函数。
在ptrace的调用来自同一人ptrace的你引用的描述:
一个进程可以通过调用fork(2),并具有 所产生的孩子做一个 启动跟踪PTRACE_TRACEME,后面(通常)由execve(2)。或者,一个进程可以开始使用PTRACE_ATTACH或PTRACE_SEIZE跟踪另一个进程。
被跟踪时,即使信号 被忽略,每次信号传递时,tracee都会停止。 (SIGKILL有个例外,它有其通常的作用)。在下一次waitpid(2)调用(或相关的“等待”系统调用之一)时,跟踪器将会通知 ;该呼叫 将返回一个状态值,其中包含指示 tracee中停止原因的信息。
当tracee调用exec时,它会收到一个信号,这就是它停止的原因。
要illustrace,示踪程序mainer.c没有铃铛或口哨声:
//mainer.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <unistd.h>
int main(int argc, char ** argv)
{
pid_t child_pid;
char * programname = argv[1];
child_pid = fork();
if (child_pid == 0)
{
ptrace(PTRACE_TRACEME, 0, 0, 0);
execl(programname, programname, NULL);
}
else if (child_pid > 0)
{
int status;
wait(&status);
while (WIFSTOPPED(status))
{
struct user_regs_struct regs;
ptrace(PTRACE_GETREGS, child_pid, 0, ®s);
unsigned instr = (PTRACE_PEEKTEXT, child_pid, regs.eip, 0);
printf("EIP = 0x%08x, instr = 0x%08x\n", regs.eip, instr);
ptrace(PTRACE_SINGLESTEP, child_pid, 0, 0);
wait(&status);
}
}
}
当tracee命中EXEC,它将接收信号,并且控制传递给家长,谁正在等待。 大会程序追查,但只是跟踪一个C程序时,提取有用的东西就太多打算:
; hello.asm
section .text
global _start
_start:
mov edx,len1
mov ecx,hello1
mov ebx,1
mov eax,4
int 0x80
mov edx,len2
mov ecx,hello2
mov ebx,1
mov eax,4
int 0x80
mov eax,1
int 0x80
section .data
hello1 db "Hello",0xA
len1 equ $ - hello1
hello2 db "World",0xA
len2 equ $ - hello2
运行此,./mainer hello
EIP = 0x08048080, instr = 0x00000000
EIP = 0x08048085, instr = 0x00000000
EIP = 0x0804808a, instr = 0x00000000
EIP = 0x0804808f, instr = 0x00000000
EIP = 0x08048094, instr = 0x00000000
Hello
EIP = 0x08048096, instr = 0x00000000
EIP = 0x0804809b, instr = 0x00000000
EIP = 0x080480a0, instr = 0x00000000
EIP = 0x080480a5, instr = 0x00000000
EIP = 0x080480aa, instr = 0x00000000
World
EIP = 0x080480ac, instr = 0x00000000
EIP = 0x080480b1, instr = 0x00000000
如果我们修改mainer.c所以孩子进程在调用do_something()之前调用跟踪的结果完全相同。这就是我如何修改它,如果你喜欢结果是一样的,你可以确认自己。
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <unistd.h>
int do_something(void) //added this function
{
printf("Doing something");
return 0;
}
int main(int argc, char ** argv)
{
pid_t child_pid;
char * programname = argv[1];
child_pid = fork();
if (child_pid == 0)
{
ptrace(PTRACE_TRACEME, 0, 0, 0);
do_something(); //added this function call
execl(programname, programname, NULL);
}
else if (child_pid > 0)
{
int status;
wait(&status);
while (WIFSTOPPED(status))
{
struct user_regs_struct regs;
ptrace(PTRACE_GETREGS, child_pid, 0, ®s);
unsigned instr = (PTRACE_PEEKTEXT, child_pid, regs.eip, 0);
printf("EIP = 0x%08x, instr = 0x%08x\n", regs.eip, instr);
ptrace(PTRACE_SINGLESTEP, child_pid, 0, 0);
wait(&status);
}
}
}
所以tracee不会停止,直到它接收到的信号,这是当它调用exec,并调用功能,不产生对tracee的信号会发生什么,但也有其他的方式来发送发信号给追踪者并开始追踪,尽管他们不像执行和等待那样整洁。