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 开发者_StackOverflow中文版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 ?
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.
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
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
精彩评论