Я использую libunwind-ptrace
для мониторинга стека вызовов удаленного процесса.
Необходимо периодически получать имя текущего вызова функции, поэтому после подключения к удаленному процессу с помощью ptrace (который будет SIGSTOP удаленный процесс), сначала я пишу al oop, который выбирает состояния с фиксированным интервалом, затем продолжаю удаленный процесс с PTRACE_CONT
(вызов любого сигнала, включая сбор информации, например, GETREGS
, отправленный ptrace, остановит удаленный процесс) .
Однако я обнаружил, что таймер работает не так, как я ожидал. Это замедляет выполнение удаленного процесса, а не просто изменяет частоту дискретизации, не влияя на выполнение удаленной программы. Я полагаю, что PTRACE_CONT
не продолжает процесс немедленно.
Затем я закомментирую таймер сна и добавлю waitpid
logi c, чтобы поймать сигнал, отправленный PTRACE_CONT
, что удивительно, это дает мне результат остановленный сигнал с номером 27 , который является SIGPROF
сигналом.
Коды перечислены ниже:
#include "libunwind.h"
#include "libunwind-x86_64.h"
#include "libunwind-ptrace.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
static unw_addr_space_t as;
static struct UPT_info *ui;
struct timespec t = { .tv_sec = 0, .tv_nsec = 1000000 };
void do_backtrace(pid_t pid) {
ui = _UPT_create(pid);
if (!ui) {
printf("_UPT_create failed\n");
}
unw_cursor_t c;
int rc = unw_init_remote(&c, as, ui);
if (rc != 0) {
printf("unw_init_remote failed with ret value:%d\n", rc);
_UPT_destroy(ui);
return;
}
unw_word_t offset, pc;
char fname[64];
fname[0] = '\0';
(void) unw_get_proc_name(&c, fname, sizeof(fname), &offset);
_UPT_destroy(ui);
}
int main(int argc, char **argv) {
as = unw_create_addr_space (&_UPT_accessors, 0);
if (!as)
printf("unw_create_addr_space() failed\n");
if (argc != 2 && argc != 3) {
printf("usage: ./a.out pid [ns]\n");
return -1;
}
pid_t target_pid = atoi(argv[1]);
if (argc == 3) {
t.tv_nsec = atol(argv[2]);
printf("sample at %ld ns\n", t.tv_nsec);
}
if (ptrace(PTRACE_ATTACH, target_pid, 0, 0) != 0) {
printf("ptrace attach %d failed\n", target_pid);
return -1;
}
if (ptrace(PTRACE_CONT, target_pid, 0, 0) != 0) {
printf("ptrace continue %d failed\n", target_pid);
return -1;
}
int status;
while (1) {
waitpid(target_pid, &status, __WALL);
if (WIFEXITED (status)) {
printf("target process exited.\n");
break;
}
else if (WIFCONTINUED(status)) {
printf("continued: %d\n", status);
}
else if (WIFSIGNALED(status)) {
printf("terminated by: %d\n", WTERMSIG(status));
}
else if (WIFSTOPPED(status)) {
printf("stopped by: %d\n", WSTOPSIG(status));
}
else {
printf("signal: %d\n", status);
}
//nanosleep(&t, NULL);
do_backtrace(target_pid);
if (ptrace(PTRACE_CONT, target_pid, 0, SIGCONT) != 0) {
printf("ptrace continue %d failed\n", target_pid);
return -1;
}
}
printf("ptrace detached: %ld\n", ptrace(PTRACE_DETACH, target_pid, 0, 0));
return 0;
}
Любой может сказать мне почему таймер не работает, и механизм ptrace
для остановки и возобновления удаленного процесса?
Большое спасибо.