views:

224

answers:

2

I would like to know from where inside a huge application a certain message is printed. The application is so big and old that it uses all conceivable ways of printing text to the terminal; for example printf(), fprintf(stdout, ...) etc.

I write to put a breakpoint on the write() system call but then I'm flooded with too many breakpoint stops because of various file I/O operations that use write() as well.

So basically I want gdb to stop whenever the program prints something to the terminal but at the same time I don't want gdb to stop when the program writes something to a file.

+4  A: 

Use a conditional breakpoint that checks the first parameter. On 64-bit x86 systems the condition would be:

(gdb) b write if 1==$rdi

On 32-bit systems, it is more complex because the parameter is on the stack, meaning that you need to cast $esp to an int * and index the fd parameter. The stack at that point has the return address, the length, buffer and finally fd.

This varies greatly between hardware platforms.

bjfrost
I messes around a bit with this and found that the FD number is availabe as "*(int)($esp+4)" and the string length as "(int)*(int)($esp + 12)" and finally the string data as "*(int)($esp + 8)".So for STDOUT you can do something like:break write if 1 == *(int)($esp+4)commandsprint (int)*(int)($esp + 12)x/s *(int)($esp + 8)endBut when I tried to use this in practice on a _huge_ application it turned out that this method is not foolproof because it doesn't handle redirects etc so if the app uses dup2() on stdout you might miss some stuff being printed to stdout.
martin
Here's a slightly more refined attempt:<pre>break writecommandssilentif !isatty(*(int)($esp + 4))cendecho \ntty write(), size: x/d (int)($esp + 12)echo tty write(), data: x/s *(int)($esp + 8)end</pre>
martin
A: 

With gdb 7.0, you can set conditional breakpoint on syscall write():

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

$ebx contains first syscall parameter - FD number here

ks1322