2012-02-09 2 views
6

Мне нужно распечатать трассировку стека из обработчика сигнала 64-битного mutli-threaded приложения C++, работающего в Linux. Хотя я нашел несколько примеров кода, ни один из них не компилируется. Моя точка блокировки получает адрес вызывающего (точка, где был сгенерирован сигнал), адрес из структуры ucontext_t. Вся информация, которую я мог найти, указывает на регистр EIP как ucontext.gregs [REG_EIP] или ucontext.eip. Похоже, что оба они являются x86-специфичными. Мне нужен 64-разрядный совместимый код для процессоров Intel и AMD. Может ли кто-нибудь помочь?Печать трассировки стека из обработчика сигнала

+0

Меня это не удивит, если это невозможно. Вы пробовали делать это на 32-битной? Кроме того, какой дистрибутив? –

+0

В 64 бит регистр RIP. Довольно уверен, что он где-то там. –

+0

Это красная шляпа 4.1.2-50. Не может быть 32-битным приложением, поскольку мы работаем с большими областями памяти до 60+ ГБ. – GMichael

ответ

1

Обычный способ получения трассировки стека, чтобы получить адрес локальной переменной, а затем добавить некоторое магическое число для него, в зависимости от того, как компилятор генерирует код (который может зависеть от параметров оптимизации , используемых для скомпилируйте код) и оттуда вернитесь. Вся очень система зависит, но выполнимо, если вы знаете, что делаете.

Вопрос о том, работает ли это в обработчике сигналов, - это еще один вопрос. Я не знаю о платформе, которую вы описываете, но многие системы устанавливают отдельный стековый блок для обработчиков сигналов, без ссылки на прерываемый стек в доступной для пользователя памяти.

+0

Вы не имеете в виду ссылку на прерванный стек? –

+0

@wood_brian Не в доступной памяти пользователя. (ОС явно хранит информацию в некотором роде.) –

+0

Вы написали прерванный статический. Я думал, ты имел в виду прерывистый стек. –

4

есть функция glibc backtrace. На странице руководства приведен пример вызова:

#define SIZE 100 
void myfunc3(void) { 
     int j, nptrs; 

     void *buffer[100]; 
     char **strings; 

     nptrs = backtrace(buffer, SIZE); 
     printf("backtrace() returned %d addresses\n", nptrs); 

     /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO) 
      would produce similar output to the following: */ 

     strings = backtrace_symbols(buffer, nptrs); 
     if (strings == NULL) { 
      perror("backtrace_symbols"); 
      exit(EXIT_FAILURE); 
     } 

     for (j = 0; j < nptrs; j++) 
      printf("%s\n", strings[j]); 

     free(strings); 
    } 

См. Справочную страницу для большего контекста.

трудно определить, действительно ли это гарантировано работает от обработчика сигналов, поскольку posix перечисляет только несколько возвратных функций, которые гарантированно будут работать. Помните: обработчик сигнала может вызываться, пока остальная часть вашего процесса находится прямо в середине вызова malloc.

У меня догадка заключается в том, что это обычно работает, но время от времени оно может терпеть неудачу. Для отладки это может быть достаточно хорошим.

Смежные вопросы