Can gdb break on/dprintf on/specify location as: return from specified function?

821 Views Asked by At

I'm debugging some C code. I want to dprintf a message when a certain function returns, regardless of how it actually returns, and even if it returns without hitting a literal return statement (for example, when a void function reaches the end of its body). I understand I could write e.g. dprintf name_of_fn:13, "message %d\n", param or something for a function whose body was 13 lines long. But this sucks if I'm actively editing the function, since I might be changing the length of its body.

Is this possible? Does anyone know how to do this?

Thanks homies

2

There are 2 best solutions below

1
On

here is a simple example, from: https://sourceware.org/gdb/onlinedocs/gdb/Dynamic-Printf.html

The referenced page goes into all the details of using dprintf with gdb

      (gdb) set dprintf-style call
      (gdb) set dprintf-function fprintf
      (gdb) set dprintf-channel mylog
      (gdb) dprintf 25,"at line 25, glob=%d\n",glob

      Dprintf 1 at 0x123456: file main.c, line 25.

      (gdb) info break
      1       dprintf        keep y   0x00123456 in main at main.c:25
              call (void) fprintf (mylog,"at line 25, glob=%d\n",glob)
              continue
      (gdb)
2
On

It is not easily possible, but it can be done. It requires either a trick or some Python programming.

The trick is old-school. What you do is make a breakpoint at the start of the function, then set a temporary breakpoint at the return location that does what you want. For example:

break function
commands
  up-silently
  tbreak
  commands
    printf "hi!\n"
    cont
  end
  cont
end

One thing to note here is that tbreak without arguments will stop at the current PC -- which in the up frame is the return location.

This will work pretty well in many situations -- but not all. In particular, if you are using next to step through the code, and you step over a call to function (even one somewhere far down the stack), gdb will act as though you typed cont, and will forget to stop for the next. (Also I have a vague recollection that in some versions of gdb you can't nest commands like this. So there may be that to contend with as well.)

This next quirk, FWIW, is one of the things that dprintf was meant to deal with more nicely.

With Python scripting, you can do better -- you can make it work correctly with next as well. The way to do this is to subclass gdb.FinishBreakpoint, and, in the code above, create an instance of your subclass.

Your subclass can do all the actions you like. In your case, you would implement the stop method to print the message you want, and then return False. This is what will let the finish breakpoint not cause a user-visible stop, and thus make next work properly.

One other nice thing about FinishBreakpoint is that you have access to the function's return value.