How to evaluate functions in GDB?
-
20-09-2019 - |
Question
I wonder why evaluate function doesn't work in gdb? In my source file I include, when debugging in gdb, these examples are wrong evaluations.
(gdb) p pow(3,2)
$10 = 1
(gdb) p pow(3,3)
$11 = 1
(gdb) p sqrt(9)
$12 = 0
Solution
My guess is that the compiler and linker does some magic with those particular functions. Most likely to increase performance.
If you absolutely need pow()
to be available in gdb then you can create your own wrapper function:
double mypow(double a, double b)
{
return pow(a,b);
}
Maybe also wrap it into a #ifdef DEBUG
or something to not clutter the final binary.
BTW, you will notice that other library functions can be called (and their return value printed), for instance:
(gdb) print printf("hello world")
$4 = 11
OTHER TIPS
You need to tell gdb that it will find the return value in the floating point registers, not the normal ones, in addition to give the parameters the right types.
I.e.:
(gdb) p ((double(*)())pow)(2.,2.)
$1 = 4
The syntax for calling a function in gdb is
call pow(3,2)
Type
help call
at the gdb prompt for more information.
Actually, at least on my LINUX implementation of gcc, many of the math functions are replaced with variants specific to the types of their arguments via some fancy substitutions pulled in by math.h and bits/mathcalls.h (included from within math.h). As a consequence, functions like pow and exp are called instead as __pow
or *__GI___exp
(your results may vary depending on the types of the arguments and perhaps the particular version).
To identify what exactly the function is that is linked in to my code I put a break at a line where just that function is called, e.g. have a line in my code with b=exp(c);
. Then I run in gdb up till that break point and then use the "step" command to enter the call from that line. Then I can use the "where" command to identify the name of the called routine. In my case that was *__GI___exp
.
There are probably cleverer ways to get this information, however, I was not able to find the right name just by running the preprocessor alone (the -E option) or by looking at the assembly code generated (-s).
pow is defined as a macro , not a function. The call in gdb can only call functions in your program or in shared library. So, the call to pow in gdb should failed.
(gdb) p pow(3,2)
No symbol "pow" in current context.
here is the gcc generated binary code of source calling pow (int, int):
(gdb) list
1 int main() {
2 int a=pow(3,2);
3 printf("hello:%d\n", a);
4 }
(gdb) x/16i main
0x4004f4 <main>: push %rbp
0x4004f5 <main+1>: mov %rsp,%rbp
0x4004f8 <main+4>: sub $0x10,%rsp
0x4004fc <main+8>: movl $0x9,-0x4(%rbp)
=> 0x400503 <main+15>: mov -0x4(%rbp),%eax
0x400506 <main+18>: mov %eax,%esi
0x400508 <main+20>: mov $0x40060c,%edi
0x40050d <main+25>: mov $0x0,%eax
0x400512 <main+30>: callq 0x4003f0 <printf@plt>
0x400517 <main+35>: leaveq
0x400518 <main+36>: retq
0x400519: nop
0x40051a: nop
0x40051b: nop
0x40051c: nop
0x40051d: nop
here is the gcc generated binary code of source calling pow (float, float):
(gdb) list
1 int main() {
2 double a=pow(0.3, 0.2);
3 printf("hello:%f\n", a);
4 }
(gdb) x/16i main
0x4004f4 <main>: push %rbp
0x4004f5 <main+1>: mov %rsp,%rbp
0x4004f8 <main+4>: sub $0x10,%rsp
0x4004fc <main+8>: movabs $0x3fe926eff16629a5,%rax
0x400506 <main+18>: mov %rax,-0x8(%rbp)
0x40050a <main+22>: movsd -0x8(%rbp),%xmm0
0x40050f <main+27>: mov $0x40060c,%edi
0x400514 <main+32>: mov $0x1,%eax
0x400519 <main+37>: callq 0x4003f0 <printf@plt>
0x40051e <main+42>: leaveq
0x40051f <main+43>: retq
NAME
pow, powf, powl - power functions
SYNOPSIS
#include <math.h>
double pow(double x, double y);
You shouldn't pass an int in the place of a double
call pow( 3. , 2. )
Also, passing a single argument is not enough, you need two arguments just like the function expects
wrong: call pow ( 3. )