如何评估GDB中的功能?

时间:2009-08-30 19:42:46

标签: function gdb evaluation

我想知道为什么评估函数在gdb中不起作用?在我的源文件中包含,当在gdb中调试时,这些示例是错误的评估。

(gdb) p pow(3,2)

$10 = 1

(gdb) p pow(3,3)

$11 = 1

(gdb) p sqrt(9)

$12 = 0

6 个答案:

答案 0 :(得分:19)

除了给参数提供正确的类型之外,你需要告诉gdb它会在浮点寄存器中找到返回值,而不是正常寄存器中的返回值。

即:

  

(gdb)p((double(*)())pow)(2.,2。)

     

$ 1 = 4

答案 1 :(得分:18)

我的猜测是编译器和链接器对这些特定函数做了一些魔术。最有可能提高性能。

如果您绝对需要在{g}中使用pow(),那么您可以创建自己的包装函数:

double mypow(double a, double b)
{
    return pow(a,b);
}

也许还将它包装成#ifdef DEBUG或其他东西,以免弄乱最终的二进制文件。

顺便说一下,您会注意到可以调用其他库函数(并打印它们的返回值),例如:

(gdb) print printf("hello world")
$4 = 11

答案 2 :(得分:17)

在gdb中调用函数的语法是

call pow(3,2)

输入

help call

在gdb提示符下获取更多信息。

答案 3 :(得分:4)

实际上,至少在我的gcc的LINUX实现中,许多数学函数被替换为特定于其参数类型的变体,通过math.h和bits / mathcalls.h引入的一些奇特的替换(包含在内部) math.h中)。因此,像pow和exp这样的函数被称为__pow*__GI___exp(您的结果可能会因参数的类型和特定版本而异)。

为了确定与我的代码链接的功能究竟是什么,我在一个只调用该函数的行中放置了一个中断,例如:我的代码中有一行b=exp(c);。然后我在gdb中运行直到该断点,然后使用“step”命令从该行输入调用。然后我可以使用“where”命令来识别被调用例程的名称。在我的情况下是*__GI___exp

可能有更聪明的方法来获取此信息,但是,我无法仅通过单独运行预处理器(-E选项)或查看生成的汇编代码(-s)来找到正确的名称。

答案 4 :(得分:1)

pow定义为宏,而不是函数。 gdb中的调用只能调用程序或共享库中的函数。因此,在gdb中调用pow应该会失败。

  (gdb) p pow(3,2)
  No symbol "pow" in current context.

这里是gcc生成的源代码调用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

这里是源代码调用pow(float,float)的gcc生成的二进制代码:

  (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

答案 5 :(得分:0)

NAME
   pow, powf, powl - power functions

SYNOPSIS
   #include <math.h>

   double pow(double x, double y);

你不应该在双重

的位置传递一个int
 call pow( 3. , 2. )

另外,传递一个参数是不够的,你需要两个参数就像函数期望的那样

 wrong: call pow ( 3. )