Я пытаюсь реализовать 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. Я не понимаю этого, так как ребенок использует exit (42). Также,
некоторые системные вызовы отца обнаруживаются в мертвом процессе сына. Все заставляет меня думать, что WIFEXITED возвращает 0 со статусом ребенка, даже после того, как ребенок вызывает exit ().
Вот пример вывода:
[...]
[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
Почему выход ребенка не вступает в силу?
Задача ещё не решена.
Других решений пока нет …