Как оценить функции в GDB? - PullRequest
       35

Как оценить функции в GDB?

28 голосов
/ 30 августа 2009

Интересно, почему функция оценки не работает в GDB? В моем исходном файле, который я включаю при отладке в gdb, эти примеры неверны.

(gdb) p pow(3,2)

$10 = 1

(gdb) p pow(3,3)

$11 = 1

(gdb) p sqrt(9)

$12 = 0

Ответы [ 6 ]

19 голосов
/ 15 ноября 2012

Вы должны указать GDB, что он найдет возвращаемое значение в регистрах с плавающей запятой, а не в обычных, кроме того, чтобы дать параметрам правильные типы.

т.е:.

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

$ 1 = 4

18 голосов
/ 31 августа 2009

Я предполагаю, что компилятор и компоновщик совершают магию с этими конкретными функциями. Скорее всего, увеличить производительность.

Если вам абсолютно необходимо, чтобы pow() был доступен в GDB, вы можете создать свою собственную функцию-обертку:

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

Может быть, также обернуть его в #ifdef DEBUG или что-то, чтобы не загромождать окончательный двоичный файл.

Кстати, вы заметите, что могут быть вызваны другие библиотечные функции (и напечатано их возвращаемое значение), например:

(gdb) print printf("hello world")
$4 = 11
17 голосов
/ 31 августа 2009

Синтаксис для вызова функции в GDB:

call pow(3,2)

Тип

help call

в приглашении GDB для получения дополнительной информации.

4 голосов
/ 10 января 2012

На самом деле, по крайней мере, в моей реализации Linux на gcc в Linux, многие математические функции заменены вариантами, специфичными для типов их аргументов, через некоторые причудливые подстановки, извлеченные из math.h и bits / mathcalls.h (включены изнутри math.h). Как следствие, такие функции, как pow и exp, называются вместо __pow или *__GI___exp (ваши результаты могут отличаться в зависимости от типов аргументов и, возможно, конкретной версии).

Чтобы определить, что именно представляет собой функция, связанная с моим кодом, я поместил разрыв в строку, где вызывается только эта функция, например, есть строка в моем коде с b=exp(c);. Затем я запускаю в gdb до этой точки останова, а затем использую команду «step» для ввода вызова с этой линии. Затем я могу использовать команду «где» для определения имени вызываемой подпрограммы. В моем случае это было *__GI___exp.

Возможно, есть более разумные способы получения этой информации, однако я не смог найти правильное имя, просто запустив один препроцессор (опция -E) или просмотрев сгенерированный код сборки (-s).

1 голос
/ 05 марта 2014

pow определяется как макрос, а не как функция. Вызов в GDB может вызывать только функции в вашей программе или в общей библиотеке. Таким образом, вызов pow в gdb не удался.

  (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

вот сгенерированный gcc двоичный код источника, вызывающего 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
0 голосов
/ 31 августа 2009
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. )
...