Есть ли способ вернуть адрес, который вызвал SIGSEGV в C? - PullRequest
0 голосов
/ 29 ноября 2018

Я - дурачок C и работаю над проектом C, который попросил меня написать обработчик сигнала для перехвата сигнала SIGSEGV и выполнения некоторых операций.

По сути, основная программа будет пытаться получить доступ к фрагменту памяти, которыйне может быть прочитан или записан.Когда основная программа обращается к этому куску памяти, она поднимает сигнал SIGSEGV, и в моей функции обработчика сигналов я улавливаю сигнал и использую mprotect () для преобразования этого куска памяти в читаемый и записываемый.

Но я не знаю, есть ли способ получить адрес, который вызвал SIGSEGV, когда сигнал перехватывается моим обработчиком сигнала.Я не могу ничего сделать, если у меня нет фактического адреса, который вызвал SIGSEGV.И мне не разрешают захватывать адреса с основного в мой обработчик сигналов.

Может кто-нибудь помочь мне?Спасибо!

1 Ответ

0 голосов
/ 29 ноября 2018

По крайней мере, в Linux ответ - да.

Вы используете sigaction для регистрации вашего обработчика сигнала, и вы устанавливаете флаг SA_SIGINFO и устанавливаете обработчик sa_sigaction.

Это дает вам доступ к siginfo_t (второму аргументу вашего обработчика сигнала), который (среди прочего) содержит поле void *si_addr;, которое (для SIGSEGV) содержит ошибочный адрес.

#define _POSIX_C_SOURCE 199309L
#include <signal.h>

void my_handler(int sig, siginfo_t *info, void *ucontext) {
    ... info->si_addr ...
}

...
struct sigaction act = {0};
act.sa_sigaction = my_handler;
act.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &act, NULL);

Подробнее см. man 2 sigaction.

...