как я могу поставить точку останова на то, что выводится на терминал в gdb?

Я хотел бы знать, откуда внутри огромного приложения печатается определенное сообщение. Приложение настолько большое и старое, что использует все мыслимые способы вывода текста на терминал; например printf (), fprintf (stdout, ...) и т. д.

Я пишу, чтобы поставить точку останова на системный вызов write (), но затем меня заваливают слишком большим количеством остановок точки останова из-за различных операций ввода-вывода файлов, которые также используют write ().

По сути, я хочу, чтобы gdb останавливался всякий раз, когда программа что-то выводит на терминал, но в то же время я не хочу, чтобы gdb останавливался, когда программа что-то записывает в файл.


person martin    schedule 08.10.2009    source источник
comment
Разве вы не можете просто grep источник того, что появляется в терминале, а затем поместить там точку останова?   -  person Calmarius    schedule 07.12.2013


Ответы (2)


Используйте условную точку останова, которая проверяет первый параметр. В 64-битных системах x86 условие будет следующим:

(gdb) b написать if 1 == $ rdi

В 32-битных системах это более сложно, потому что параметр находится в стеке, а это означает, что вам нужно преобразовать $ esp в int * и проиндексировать параметр fd. Стек в этой точке имеет адрес возврата, длину, буфер и, наконец, fd.

Это сильно варьируется между аппаратными платформами.

person bjfrost    schedule 08.10.2009
comment
Я немного испортил это и обнаружил, что номер FD доступен как * (int) ($ esp + 4), а длина строки как (int) * (int) ($ esp + 12) и, наконец, строковые данные как * (число) ($ esp + 8). Итак, для STDOUT вы можете сделать что-то вроде: break write if 1 == * (int) ($ esp + 4) commands print (int) * (int) ($ esp + 12) x / s * (int) ($ esp + 8) end Но когда я попытался использовать это на практике в огромном приложении, оказалось, что этот метод не надежен, потому что он не обрабатывает перенаправления и т. Д., Поэтому, если приложение использует dup2 () на stdout вы можете пропустить некоторые вещи, которые выводятся на stdout. - person martin; 20.10.2009
comment
Вот немного более изощренная попытка: ‹pre› команды прерывания записи без звука if! Isatty (* (int) ($ esp + 4)) c end echo \ ntty write (), size: x / d (int) ($ esp + 12) echo tty write (), данные: x / s * (int) ($ esp + 8) end ‹/pre› - person martin; 20.10.2009

В gdb 7.0 вы можете установить условную точку останова для системного вызова write ():

(gdb) catch syscall write
Catchpoint 1 (syscall 'write' [4])
(gdb) condition 1 $ebx==1

$ ebx содержит первый параметр системного вызова - здесь номер FD

person ks1322    schedule 06.01.2010
comment
Примечание: printf находится в буфере, поэтому может случиться так, что вы увидите только write для первого printf на втором printf вызове, объединенном. - person Ciro Santilli 新疆再教育营六四事件ۍ 28.07.2015