一個更好的解釋見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的信號會發生什麼,但也有其他的方式來發送發信號給追蹤者並開始追蹤,儘管他們不像執行和等待那樣整潔。