Segment violation

Тема в разделе "WASM.UNIX", создана пользователем Iceberg, 1 сен 2006.

  1. Iceberg

    Iceberg New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2005
    Сообщения:
    54
    Адрес:
    Санкт-Петербург
    можно ли в обработчике SIGSEGV получить адрес инструкции (о call stack говорить не приходится, но было бы круто), благодаря которой было сгенерировано это исключение? Или адрес памяти, по кторому произошло исключение? В общем, любую информацию, которая может сказать, какой код вызвал segment violation?
     
  2. Bert

    Bert New Member

    Публикаций:
    0
    Регистрация:
    11 май 2005
    Сообщения:
    20
    Адрес:
    Russia
    Посмотри информацию по структуре siginfo_t в sigaction(2). Можно, например, что-то вроде
    Код (Text):
    1. void on_sigsegv(int sig, siginfo_t *si, void *ptr)
    2. {
    3.         printf("SIGSEGV at %p\n", si->si_addr);
    4.         printf("Reason: ");
    5.         switch (si->si_code) {
    6.         case SEGV_MAPERR:
    7.                 printf("Address not mapped to object\n");
    8.                 break;
    9.         case SEGV_ACCERR:
    10.                 printf("Invalid permissions for mapped object\n");
    11.                 break;
    12.         }
    13.         ...
    14. }
     
  3. CLG

    CLG New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2010
    Сообщения:
    7
    знаю, что поднимаю старую тему, но очень актуально
    понадобилось мне отлавливать баги динамически

    тестю! на вышеприведённом коде, ставя перехватчик сигнала через sigaction

    на сигнале например SIGFPE , si_addr как и положено содержит адрес исключения
    а вот на SIGSEGV - в si_addr всегда НОЛЬ

    пробывал как на сях писать, так и на фасме, одна хрень
    рыл гугл. выхода не нашёл

    а задача то простая - программно (без отладчика) отлавливать адрес, по котрому возникает SIGSEGV
    п.с. BSD 7.1 , BSD 7.3

    помогите люди добрые кто чем может
     
  4. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    Поройся в стеке обработчика. Насколько я понимаю, там лежат все значения регистров на момент возникновения SIGSEGV.
    А с отладчиком -- это не программно? Можно ж из обработчика SIGSEGV запустить gdb, приаттачиться к себе, и делать всё что угодно. ;)
     
  5. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    Есть прогресс? Если есть, расскажи, мне тоже интересно =)
     
  6. CLG

    CLG New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2010
    Сообщения:
    7
    gdb это жесть. я под ald отлаживаю
    а вообще имелось ввиду отлавливание багов автоматически

    выяснилось, что в в si_addr при SIGSEGV не адрес исключения, а адрес памяти, а адрес исключения лежит по адресу третьего параметра + 4Ch
    как […] люди пишут...? в большинстве документаций вообще ничего нет про это даже близко
     
  7. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    CLG
    gdb автоматизируется, в этом вся фишка. Смотри:
    Код (Text):
    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <unistd.h>
    4. #include <sys/types.h>
    5. #include <signal.h>
    6. int attach_gdb (pid_t target)
    7. {
    8.     static char buf[6];
    9.     static char *argv[] = {
    10.                 // команда для запуска gdb, и выполнения в нём команд bt и kill:
    11.         "gdb", "--pid", buf, "-ex", "bt", "-ex", "kill", NULL
    12.     };
    13.     snprintf (buf, 6, "%d", target);
    14.     int i;
    15.     for (i = 0; argv[i] != NULL; i ++) {
    16.         printf ("%s ", argv[i]);
    17.     }
    18.     printf ("\n");
    19.     execvp (argv[0], argv);
    20. }
    21. void sigsegv_handler (int snum)
    22. {
    23.     pid_t parent_pid = getpid ();
    24.     pid_t pid = fork ();
    25.     if (!pid) {
    26.         pid = fork ();
    27.         if (!pid)
    28.             attach_gdb (parent_pid);
    29.         else if (pid)
    30.             exit (0);
    31.     }
    32.     if (pid < 0) {
    33.         fprintf (stderr, "Oops: I cant fork gdb!\n");
    34.     } else {
    35.         waitpid (pid);
    36.         while (1)
    37.             ;
    38.     }
    39.     exit (1);
    40. }
    41.  
    42. int main ()
    43. {
    44.     struct sigaction act = {
    45.         .sa_handler = sigsegv_handler, .sa_flags = 0
    46.     };
    47.     sigemptyset (&act.sa_mask);
    48.     sigaction (SIGSEGV, &act, NULL);
    49.     int val = ((int*)0)[0]; // здесь вылетает SIGSEGV
    50.     return val;
    51. }
     
  8. CLG

    CLG New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2010
    Сообщения:
    7
    у меня не на сях софт :)
    я пишу под bsd на фасм

    я имел ввиду вообще без отладчика. так надо :)