2009-10-08 14 views
18

Belirli bir mesajın yazdırıldığı büyük uygulamasının içinden nerede olduğunu bilmek istiyorum. Uygulama çok büyük ve eskidir ve metnin terminale yazdırılmasının tüm akla yatkın yollarını kullanır; örneğin, printf(), fprintf (stdout, ...) vb.gdb'de "terminale basılmış bir şey" üzerine nasıl bir kesme noktası koyabilirim?

Write() sistem çağrısında bir kesme noktası yazmak için yazarım ancak çeşitli dosya I/nedeniyle çok fazla kesme noktası durdu O da write() işlevini kullanır.

Temel olarak, program bir şeyleri bir terminale yazdırdığında gdb'nin durmasını istiyorum ama aynı zamanda programın bir dosyaya bir şey yazması sırasında gdb'nin durmasını istemiyorum.

+1

Standart bir tampon ve belirli bir dizi boruya yerleştirildiğinde kırılsın mı?] (http://stackoverflow.com/questions/8235436/how-can-i-monitor-whats-being-put-into-the-standard- out-buffer-and-break-ne zaman-a) –

+0

Terminalde görünen "bir şey" için kaynağı grep'leyemezsiniz, sonra orada bir kırılma noktası yerleştiremez misiniz? – Calmarius

cevap

18

İlk parametreyi kontrol eden bir koşullu kesme noktası kullanın. 64 bit x86 sistemlerde durum olacaktır:

(gdb) b yazma == $ rdi 32 bit sistemlerde

1 eğer parametre yığın, bunun nedeni, yani daha karmaşıktır int * 'a int * yazmanız ve fd parametresini dizine eklemeniz gerekir. Bu noktada yığın dönüş adresi, uzunluk, arabellek ve son olarak fd'ye sahiptir.

Bu, donanım platformları arasında büyük farklılıklar gösterir. gdb 7.0 ile

+1

Ben bununla biraz uğraştım ve FD numarasının "* (int) ($ esp + 4)" olarak ve "(int) * (int) ($ esp + 12)" olarak dize uzunluğunun mevcut olduğunu ve Son olarak dize verileri "* (int) ($ esp + 8)" olarak. Böylece gibi bir şey yapabilirsiniz STDOUT için: mola yazma eğer 1 == * (int) ($ ESP + 4) print (int) * (int) ($ ESP + 12) x/s komutları * (int) ($ esp + 8) end Ancak bu uygulamayı bir _huge_ uygulamasında kullanmayı denediğimde, uygulamanın dup2 kullanması durumunda yeniden yönlendirme işlemlerini yapmadığı için bu yöntemin kusursuz olmadığına karar verildi.() stdout'ta stdout'a yazdırılan bazı şeyleri özlüyor olabilirsiniz. – martin

+0

Biraz daha hassas bir girişim:

 break write commands silent if !isatty(*(int)($esp + 4)) c end echo \ntty write(), size: x/d (int)($esp + 12) echo tty write(), data: x/s *(int)($esp + 8) end 
martin

11

, sen syscall yazma() şartına kesme noktası ayarlayabilirsiniz:

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

$ ebx ilk sistem çağrısı parametresi var - burada FD numarası

Ayrıca bkz [I izleyebilirsiniz nasıl konduğunu ne
+0

Not: 'printf' arabelleğe alınmış, bu nedenle birleştirilmiş ikinci' printf' çağrısında ilk 'printf' için' write '' yazdığını görebilirsiniz. –