2013-03-27 3 views
4

Я пытаюсь отладить программу, которая часто заставляет GDB останавливаться и отображать SIGTRAP, когда она не находится в точке останова. Это происходит при загрузке динамических библиотек и других обычных вещей. Есть около 1000 таких событий, прежде чем моя точка останова окончательно ударит, поэтому мне не удалось вручную «продолжить» все эти нерелевантные SIGTRAP. Но если я использую команду handle SIGTRAP nostop noprint, то GDB не остановится в моей точке останова.Как заставить GDB останавливаться на SIGTRAP только на контрольных точках?

Похоже, что должен быть способ обучения GDB, чтобы он понимал, какой SIGTRAP хорош для остановки, и который не подходит для остановки. Ясно, что GDB знает, находится ли он в точке останова, потому что вывод очень надежно отличается: в точке останова он упоминает «точку останова» и показывает номер точки останова, но в любом другом SIGTRAP он просто говорит «SIGTRAP». Поэтому вместо того, чтобы печатать сообщение о SIGTRAP, мне бы очень хотелось, чтобы GDB просто сказал себе: «Вау, это SIGTRAP, и здесь нет точки останова. Посмотрите на меня, я собираюсь остановиться и распечатать бесполезное сообщение SIGTRAP, которое полностью разрушает сессию отладки! Как насчет того, что я просто продолжаю спокойно? " Пожалуйста, дайте мне знать, если у кого-то есть способ сделать это.

ответ

2

Вы можете установить catchpoints, чтобы поймать сигнал SIGTRAP и добавить команды, чтобы решить, продолжать или останавливаться. В этом обработчике вы можете проверить convenience variables, например $_siginfo, по причине сигнала.

Особый интерес представляет $_siginfo.si_code, его значение зависит от передаваемого сигнала. На странице руководства Linux sigaction(2) описаны точные отношения. Вы можете найти числовые значения для этих SI_USER, SI_KERNEL и т. Д. Кодов путем компиляции программы или поиска в заголовках (в моей системе используется заголовок /usr/include/bits/siginfo.h). Некоторые значения я столкнулся являются:

  • 0x00 (0): SI_USER
  • 0x80 (128): SI_KERNEL
  • 0x02 (2): TRAP_TRACE

С этой информацией в руке, здесь является примером, который улавливает SIGTRAP и печатает причину, а затем продолжает:

catch signal SIGTRAP 
commands 
p $_siginfo.si_code 
c 
end 
# Set another breakpoint for testing 
break sleep 

Теперь рассмотрим эту тестовую программу, которая спит 5 секунд, а затем запускает отладки ловушку на x86 (-64):

#include <unistd.h> 
int main(void) { 
    for (;;) { 
     sleep(5); 
     asm("int3"); 
    } 
    return 0; 
} 

Эта программа держит остановки gdb на int3 линии, потому что сигнал ловится (si_code случается 0x80 , SI_KERNEL), но затем инструкция повторяется снова. Поэтому, чтобы пропустить эту команду, счетчик программ ($pc) должен быть увеличен. После этого, я узнал эту информацию о SIGTRAP и si_code:

  • Breakpoints спускового SIGTRAP с кодом 128 (SI_KERNEL).
  • После продолжения разгона SIGTRAP с кодом 2 (TRAP_TRACE) принимается (из-за точки перехвата для SIGTRAP).
  • Инструкция int3 запускает SIGTRAP с кодом 128. Таким образом, вам нужно что-то, чтобы отличать инструкции.

Вот окончательный GDB команды, которые пропустить int3 ловушки и по-прежнему держать изломов функциональны:

catch signal SIGTRAP 
commands 
silent # do not print catchpoint hits 
# ignore the int3 instruction (this address was looked up at 
# the tracepoint using print $pc) 
if $pc == 0x400568 
    set $pc++ # skip int3 
    c 
end 
# Ignore TRAP_TRACE that is used for breakpoints 
if $_siginfo.si_code == 2 
    c 
end 
end 

Заключительное примечание: SIGTRAP используется внутри отладчика, то возможно, что вышеуказанные уловы слишком много. Это было протестировано с GDB 7.10 на Arch Linux.

+0

Кстати, это зависит от архитектуры, но идея в целом применима. Возможно, вам нужно «установить $ pc + = ...» или изменить номера 'si_code'. – Lekensteyn

+0

'silent' не работает в моем gdb. Что я могу использовать вместо этого? – Alex

+0

@Alex Define «не работает», это предотвращает печать сообщения, но оно не будет автоматически продолжено после того, как точка catch будет удалена. – Lekensteyn

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