Я пытаюсь отслеживать / перенаправлять системные вызовы в моем собственном процессе. LD_PRELOAD не работает, когда fwrite
вызывает write
внутри libc, а хуки got / plt, похоже, имеют ту же проблему. Я ищу решение на основе ptrace, но я не могу использовать fork () и запускать основное приложение в качестве дочернего, потому что приложение взаимодействует со своим родителем через сигналы.
В 2006 году есть ветка, в которой говорится, что трассировщик может находиться в группе потоков, отличной от трассируемой, но на практике это не работает: http://yarchive.net/comp/linux/ptrace_self_attach.html
pid = fork();
if (pid == 0) {
prctl(PR_SET_PTRACER, getppid());
raise(SIGSTOP);
} else {
sleep(1);
ptrace(PTRACE_SEIZE, pid, NULL, NULL);
for (;;) {
int status;
int ret = waitpid(pid, &status, 0);
warn("wait=%d:", ret);
ret = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
warn("ptrace=%d:", ret);
}
}
Проблема, с которой я столкнулся, заключается в том, что ptrace (PTRACE_SYSCALL) ожидает, что трассируемый объект будет в состоянии ptrace-wait, т.е. он должен поднять сигнал SIGSTOP, и трассировщику необходимо wait () для него. Поскольку в этом случае отношение инвертируется (трассировщик является потомком трассируемого), PTRACE_SYSCALL возвращает ESRCH.
Как strace уходит с рук при трассировке существующего pid?