GDB: установить точку останова для обработчика SIGBUS - PullRequest
9 голосов
/ 11 января 2010

Я пытаюсь отладить простой сборщик мусора с остановкой и копированием (написанный на C), используя GDB. GC работает с SIGBUS. Я установил точку останова в верхней части моего обработчика сигнала SIGBUS. Я сказал GDB передать SIGBUS моей программе. Тем не менее, это не похоже на работу.

Следующая программа (объясненная в строке) показывает суть моей проблемы:

#include <stdio.h>
#include <sys/mman.h>
#include <assert.h>
#include <signal.h>

#define HEAP_SIZE 4096

unsigned long int *heap;

void gc(int n) {
  signal(SIGBUS, SIG_DFL); // just for debugging
  printf("GC TIME\n");
}

int main () {

  // Allocate twice the required heap size (two semi-spaces)
  heap = mmap(NULL, HEAP_SIZE * 2, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED,
              -1, 0);
  assert (heap != MAP_FAILED);
  // 2nd semi-space is unreadable. Using "bump-pointer allocation", a SIGBUS
  // tells us we are out of space and need to GC.
  void *guard = mmap(heap + HEAP_SIZE, HEAP_SIZE, PROT_NONE, MAP_ANON |
                     MAP_SHARED | MAP_FIXED, -1, 0);
  assert (guard != MAP_FAILED);
  signal(SIGBUS, gc);
  heap[HEAP_SIZE] = 90; // pretend we are out of heap space
  return 0;
} 

Я компилирую и запускаю программу на Mac OS X 10.6 и получаю ожидаемый результат:

$ gcc debug.c
$ ./a.out
GC TIME
Bus error

Я хочу запустить и отладить эту программу с помощью GDB. В частности, я хочу установить точку останова в функции gc (действительно, обработчик сигнала gc). Естественно, я должен сказать GDB, чтобы он не останавливался и на SIGBUS:

$ gdb ./a.out 
GNU gdb 6.3.50-20050815 (Apple version gdb-1346) (Fri Sep 18 20:40:51 UTC 2009)
... snip ...
(gdb) handle SIGSEGV SIGBUS nostop noprint
Signal        Stop  Print   Pass to program Description
SIGBUS        No    No  Yes     Bus error
SIGSEGV       No    No  Yes     Segmentation fault
(gdb) break gc
Breakpoint 1 at 0x100000d6f

Однако мы никогда не достигнем точки останова:

(gdb) run
Starting program: /snip/a.out 
Reading symbols for shared libraries +. done

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x0000000100029000
0x0000000100000e83 in main ()
(gdb) 

По-видимому, обработчик сигнала не вызывается (GC TIME не печатается). Кроме того, мы все еще в main (), в ошибочном mov:

0x0000000100000e83 <main+247>:  movq   $0x5a,(%rax)

Есть идеи?

Спасибо.

Ответы [ 4 ]

5 голосов
/ 29 июля 2011

Внутренне неудачный доступ к памяти приводит к тому, что исключение Маха EXC_BAD_ACCESS отправляется программе. Обычно это переводится в сигнал SIGBUS UNIX. Однако GDB перехватывает исключения Маха непосредственно перед трансляцией сигнала. Решение состоит в том, чтобы дать gdb команду set dont-handle-bad-access 1 перед запуском вашей программы. Затем используется нормальный механизм, и точки останова внутри вашего обработчика сигнала соблюдаются.

5 голосов
/ 12 января 2010

Тот же код (модифицированный для обработки и SIGSEGV) работает как положено в GDB в Linux;это может быть ошибка в порте OS X или GDB на эту платформу.

Поиск в Google находит испорченное поведение OS X точно так же, как у вас в 10.1, с неким обходным решением (set inferior-bind-exception-port off перед запуском программы).

(В Windows . *1009* имеется аналогичная ошибка)

4 голосов
/ 11 января 2010

Как насчет помещения for( ;; ); после printf(), нормального запуска программы и последующего подключения к процессу с помощью gdb после печати GC TIME?

2 голосов
/ 11 января 2010

Почему вы ожидаете получить SIGBUS? SIGBUS обычно означает ошибку выравнивания в архитектуре, где некоторые типы данных имеют требования выравнивания. Похоже, вы просто пытаетесь получить доступ к памяти за пределами выделенной области, и я ожидаю, что тогда вы получите SIGSEGV вместо SIGBUS.

Edit:

Похоже, что имя Mac OS X, которое я называю SIGSEGV, называется SIGBUS. Поэтому игнорируйте этот ответ.

Если это поможет, то точка останова работает как положено (то есть работает), когда я пытаюсь запустить программу в системе Linux, с заменой SIGBUS на SIGSEGV.

Редактировать 2:

Можете ли вы попробовать поймать SIGSEGV в вашей программе? Кажется, что тип сигнала может варьироваться в зависимости от того, где отображается память в Mac OS X (я только что прочитал обсуждение здесь и здесь ), и просто возможно, другой сигнал быть брошенным при запуске в отладчике?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...