3

I am trying to mock a function (for unit testing parent function) using GDB. One way to do it would be to set a break point in function you intend to mock and use GDB return command.

However I am unable to do the same when GDB call command is used.

(gdb) b secret_check
Breakpoint 1 at 0x80483ba: file ut_gdb.c, line 6.
(gdb) start
Temporary breakpoint 2 at 0x804843c: file ut_gdb.c, line 34.
Starting program: ut.bin
Temporary breakpoint 2, main () at ut_gdb.c:34
34          int res = 0;
(gdb) bt
#0  main () at ut_gdb.c:34
(gdb) call fact(3)
Breakpoint 1, secret_check (check_type=1) at ut_gdb.c:6
6               if(check_type == 0){
The program being debugged stopped while in a function called from GDB.
Evaluation of the expression containing the function
(fact) will be abandoned.
When the function is done executing, GDB will silently stop.
(gdb) bt
#0  secret_check (check_type=1) at ut_gdb.c:6
#1  0x080483ff in fact (n=3) at ut_gdb.c:19
#2  
#3  main () at ut_gdb.c:34

Is it a limitation in GDB ?

Kamath
  • 4,461
  • 5
  • 33
  • 60

3 Answers3

0

Are you sure that this doesn't work? Just ignore the long message you get.

For my case fn1 calls fn2. I want to test fn1 and mock fn2:

b fn2
call fn1   
// gdb stops on the breakpoint
return somevalue
c

And everything seems OK. (I use cygwin gdb 7.8.)


Please take a look at: Debugging a programmatically called function with GDB

Community
  • 1
  • 1
Aykut Kllic
  • 898
  • 9
  • 14
0

I would expect so. The limitation is probably that GDB cannot be stopped at (and able to continue from) two breakpoints at once. GDB has to maintain information about the current point where the program stopped in order to be able to continue. In order to support what you're trying to do, it would need to maintain a stack of "continue" states, and have some ability for you to specify which one you want to continue from.

Brooks Moses
  • 9,267
  • 2
  • 33
  • 57
  • Is it easy to add this feature into GDB ? – Kamath Jun 08 '11 at 05:53
  • I'm not a GDB developer, so I don't know. But my guess, from working with a bunch of them, is that it would be quite difficult. The assumption that there is a single "continue" state rather than a list of them -- if my guess that there is only one of them is correct -- would probably show up in all sorts of places through the whole program, and you'd have to find and fix all of them. If it were easy, someone would probably have fixed it already. – Brooks Moses Jun 10 '11 at 01:55
0

It's possible to do this with GDB's Python interface:

import gdb

class MyBreak(gdb.Breakpoint):
  def __init__(self, spec):
    gdb.Breakpoint.__init__(self, spec)
    self.silent = True

  def stop(self):
    #do whatever you need

    return False

MyBreak("secret_check")

You need to be careful with what you do in the stop callback, not everything is legal. I don't mean it won't work, but it might crash and/or change in future versions for instance:

def stop(self):
  print gdb.selected_thread().is_running() # True
  gdb.execute("return 5") #working, but you're not really supposed to do it!
  ...

In the upcoming 7.4 version of GDB, the FinishBreakpoint should be able to help you a lot with your mocked functions (just an example, I didn't test it):

class MyFinishBreakpoint (gdb.FinishBreakpoint)
  def __init__(self, param):
    gdb.FinishBreakpoint()
    self.param = param

  def stop (self):
    #change self.param as you want
    return False

class MyBreak(gdb.Breakpoint):
  def stop(self):
    #read parameters according to calling conventions
    param = gdb.parse_and_eval("...")
    MyFinishBreakpoint(param)

    return False
Kevin
  • 4,618
  • 3
  • 38
  • 61