web-dev-qa-db-fra.com

Comment évaluer les fonctions dans GDB?

Je me demande pourquoi évaluer la fonction ne fonctionne pas dans gdb? Dans mon fichier source inclus, lors du débogage dans gdb, ces exemples sont des évaluations erronées.

(gdb) p pow(3,2)

$10 = 1

(gdb) p pow(3,3)

$11 = 1

(gdb) p sqrt(9)

$12 = 0
28
Tim

Je suppose que le compilateur et l'éditeur de liens font de la magie avec ces fonctions particulières. Très susceptible d’augmenter les performances. 

Si vous avez absolument besoin que pow() soit disponible dans gdb, vous pouvez créer votre propre fonction de wrapper:

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

Peut-être aussi l'envelopper dans un #ifdef DEBUG ou quelque chose pour ne pas encombrer le binaire final.

En passant, vous remarquerez que d’autres fonctions de la bibliothèque peuvent être appelées (et leur valeur de retour imprimée), par exemple:

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

La syntaxe pour appeler une fonction dans gdb est

call pow(3,2)

Type 

help call

sur l'invite gdb pour plus d'informations.

17
Charles E. Grant

Vous devez dire à gdb qu'il trouvera la valeur de retour dans les registres à virgule flottante, et non les registres normaux, en plus de donner les types appropriés aux paramètres.

C'est à dire.:

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

1 $ = 4

17
anon

En fait, du moins dans mon implémentation LINCC de gcc, de nombreuses fonctions mathématiques sont remplacées par des variantes spécifiques aux types de leurs arguments via des substitutions fantaisies tirées de math.h et de bits/mathcalls.h (inclus dans math.h ). En conséquence, des fonctions telles que pow et exp sont appelées à la place par __pow ou *__GI___exp (vos résultats peuvent varier en fonction des types d'arguments et peut-être de la version particulière). 

Pour identifier la fonction qui est liée à mon code, je mets une rupture à la ligne où cette fonction est appelée, par exemple. avoir une ligne dans mon code avec b=exp(c);. Puis je cours dans gdb jusqu’à ce point d’arrêt, puis utilise la commande "step" pour entrer l’appel à partir de cette ligne. Ensuite, je peux utiliser la commande "where" pour identifier le nom de la routine appelée. Dans mon cas, c'était *__GI___exp.

Il existe probablement des moyens plus intelligents d’obtenir ces informations. Cependant, je n’étais pas en mesure de trouver le bon nom en exécutant uniquement le préprocesseur (option -E) ou en consultant le code d’assemblage généré (-s). 

4
Robert Indik

pow est défini comme une macro, pas une fonction. L’appel dans gdb ne peut appeler que des fonctions de votre programme ou de la bibliothèque partagée. Donc, l'appel à pow dans gdb devrait échouer.

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

voici le code binaire généré par gcc de l'appelant source 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

voici le code binaire généré par gcc de la source appelant 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
1
Houcheng
NAME
   pow, powf, powl - power functions

SYNOPSIS
   #include <math.h>

   double pow(double x, double y);

Vous ne devriez pas passer un int à la place d'un double

 call pow( 3. , 2. )

De plus, passer un seul argument ne suffit pas, vous avez besoin de deux arguments exactement comme la fonction

 wrong: call pow ( 3. )
0
Adrian Panasiuk