Шаг 1 : Инициализация sigaction
:
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
sigemptyset(&act.sa_mask);
act.sa_sigaction = handler;
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
Шаг 2 : Сделать эту sigaction
ручку SIGSEGV
:
sigaction(SIGSEGV, &act, NULL);
(Необязательно) Шаг 3 : Заставьте его обрабатывать и другие сигналы памяти:
sigaction(SIGBUS, &act, NULL);
sigaction(SIGTRAP, &act, NULL);
При необходимости добавьте обработку ошибок
Шаг 4 : определение функции обработчика:
void handler(int signal, siginfo_t* siginfo, void* uap) {
printf("Attempt to access memory at address %p\n",
siginfo->si_addr);
#ifdef LINUX_64BIT
printf("Instruction pointer: %p\n",
(((ucontext_t*)uap)->uc_mcontext.gregs[16]));
#elif LINUX_32BIT
printf("Instruction pointer: %p\n",
(((ucontext_t*)uap)->uc_mcontext.gregs[14]));
#endif
}
Вы можете обратиться к справочным страницам для ucontext_t
и siginfo_t
для получения более интересных данных, которые может извлечь ваш обработчик.