можно ли в обработчике SIGSEGV получить адрес инструкции (о call stack говорить не приходится, но было бы круто), благодаря которой было сгенерировано это исключение? Или адрес памяти, по кторому произошло исключение? В общем, любую информацию, которая может сказать, какой код вызвал segment violation?
Посмотри информацию по структуре siginfo_t в sigaction(2). Можно, например, что-то вроде Код (Text): void on_sigsegv(int sig, siginfo_t *si, void *ptr) { printf("SIGSEGV at %p\n", si->si_addr); printf("Reason: "); switch (si->si_code) { case SEGV_MAPERR: printf("Address not mapped to object\n"); break; case SEGV_ACCERR: printf("Invalid permissions for mapped object\n"); break; } ... }
знаю, что поднимаю старую тему, но очень актуально понадобилось мне отлавливать баги динамически тестю! на вышеприведённом коде, ставя перехватчик сигнала через sigaction на сигнале например SIGFPE , si_addr как и положено содержит адрес исключения а вот на SIGSEGV - в si_addr всегда НОЛЬ пробывал как на сях писать, так и на фасме, одна хрень рыл гугл. выхода не нашёл а задача то простая - программно (без отладчика) отлавливать адрес, по котрому возникает SIGSEGV п.с. BSD 7.1 , BSD 7.3 помогите люди добрые кто чем может
Поройся в стеке обработчика. Насколько я понимаю, там лежат все значения регистров на момент возникновения SIGSEGV. А с отладчиком -- это не программно? Можно ж из обработчика SIGSEGV запустить gdb, приаттачиться к себе, и делать всё что угодно.
gdb это жесть. я под ald отлаживаю а вообще имелось ввиду отлавливание багов автоматически выяснилось, что в в si_addr при SIGSEGV не адрес исключения, а адрес памяти, а адрес исключения лежит по адресу третьего параметра + 4Ch как […] люди пишут...? в большинстве документаций вообще ничего нет про это даже близко
CLG gdb автоматизируется, в этом вся фишка. Смотри: Код (Text): #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <signal.h> int attach_gdb (pid_t target) { static char buf[6]; static char *argv[] = { // команда для запуска gdb, и выполнения в нём команд bt и kill: "gdb", "--pid", buf, "-ex", "bt", "-ex", "kill", NULL }; snprintf (buf, 6, "%d", target); int i; for (i = 0; argv[i] != NULL; i ++) { printf ("%s ", argv[i]); } printf ("\n"); execvp (argv[0], argv); } void sigsegv_handler (int snum) { pid_t parent_pid = getpid (); pid_t pid = fork (); if (!pid) { pid = fork (); if (!pid) attach_gdb (parent_pid); else if (pid) exit (0); } if (pid < 0) { fprintf (stderr, "Oops: I cant fork gdb!\n"); } else { waitpid (pid); while (1) ; } exit (1); } int main () { struct sigaction act = { .sa_handler = sigsegv_handler, .sa_flags = 0 }; sigemptyset (&act.sa_mask); sigaction (SIGSEGV, &act, NULL); int val = ((int*)0)[0]; // здесь вылетает SIGSEGV return val; }