我正在尝试实现strace -f。请查看我的程序的主循环:
static void trace_syscalls(pid_t pid)
{
int status;
wait(&status);
unsigned int options = PTRACE_O_TRACEFORK | PTRACE_O_TRACECLONE
| PTRACE_O_TRACEVFORK | PTRACE_O_EXITKILL;
ptrace(PTRACE_SETOPTIONS, pid, 0, options);
std::list<pid_t> pids = { pid };
pid_t new_pid = 0;
struct user_regs_struct regs;
ptrace(PTRACE_SYSCALL, pid, 0, 0);
while (!pids.empty())
{
for (auto it_pid = pids.begin(); it_pid != pids.end(); it_pid++)
{
waitpid(*it_pid, &status, 0);
if (WIFEXITED(status))
{
std::cerr << "program exited with code " << WEXITSTATUS(status)
<< std::endl;
pids.erase(it_pid);
break;
}
// Entry of the sycall
ptrace(PTRACE_GETREGS, *it_pid, 0, ®s);
std::cerr << "[pid " << *it_pid << "] ";
switch_syscall(regs.orig_rax);
ptrace(PTRACE_SYSCALL, *it_pid, 0, 0); // Restart child
waitpid(*it_pid, &status, 0); // Waiting the syscall to end
// Exit of the syscall
ptrace(PTRACE_GETREGS, *it_pid, 0, ®s);
// Printing the return value
std::cerr << " = ";
if (regs.rax == (unsigned long long)-2)
std::cerr << -1 << "\n";
else
std::cerr << regs.rax << "\n";
if (regs.orig_rax == __NR_fork || regs.orig_rax == __NR_vfork
|| regs.orig_rax == __NR_clone)
{
ptrace(PTRACE_GETEVENTMSG, *it_pid, 0, &new_pid);
if (new_pid != 0 && !exists(pids, new_pid))
{
printf("NEW = %u\n", new_pid);
pids.push_front(new_pid);
ptrace(PTRACE_SYSCALL, new_pid, 0, 0);
}
}
ptrace(PTRACE_SYSCALL, *it_pid, 0, 0);
}
}
}
我目前正在追踪以下测试代码:
int main()
{
pid_t pid = 0;
pid = fork();
if (pid == 0)
{
printf("child\n");
exit(42);
}
sleep(1);
printf("parent\n");
return 0;
}
通过该测试,我得到一个输出,显示孩子和父亲都退出0.我不明白,因为孩子使用退出(42)。也, 在儿子的死亡过程中检测到父亲的一些系统调用。即使在孩子调用exit()之后,一切都让我觉得WIFEXITED返回0和子的状态。
以下是示例输出:
[...]
[pid 14229] mprotect() = 0
[pid 14229] mprotect() = 0
[pid 14229] munmap() = 0
[pid 14229] clone() = 18446744073709551578
NEW = 14230
[pid 14230] Syscall number: 5 = 0
[pid 14229] clone() = 18446744073709551578
[pid 14230] mmap() = 140012527452160
[pid 14229] Syscall number: 14 = 18446744073709551578
[pid 14230] Syscall number: 1child
= 6
[pid 14229] Syscall number: 13 = 18446744073709551578
[pid 14230] exit_group() = 18446744073709551578
[pid 14229] Syscall number: 14 = 0
[pid 14230] Syscall number: 14 = 0
[pid 14229] Syscall number: 35 = 0
[pid 14230] Syscall number: 35 = 0
[pid 14229] Syscall number: 5 = 0
[pid 14230] Syscall number: 5 = 0
[pid 14229] mmap() = 140012527452160
[pid 14230] mmap() = 140012527452160
[pid 14229] Syscall number: 1parent
= 7
[pid 14230] Syscall number: 1 = 7
[pid 14229] exit_group() = 18446744073709551578
program exited with code 0
program exited with code 0
为什么孩子的退出没有生效?