web-dev-qa-db-fra.com

Comment faire pour déboguer des bibliothèques partagées?

Quelqu'un peut-il me dire comment procéder au débogage à l'exécution sur des bibliothèques partagées?

Je dois exécuter une fonction dans ma bibliothèque partagée à l'exécution, mais elle est appelée par un autre programme . Comment puis-je faire quelque chose comme dbx avec des bibliothèques partagées?

J'utilise dbx sous AIX . Gdb est-il meilleur que dbx pour ce que j'essaie de faire ?.

35
debugger

Vous avez juste besoin d’appeler gdb avec l’exécutable (peu importe qu’il s’agisse du vôtre ou d’un tiers). Voici un exemple où je débogue la commande ls et définit un point d 'arrêt dans la bibliothèque (/ partagée) c . Cet exemple utilise gdb 6.8 qui prend en charge les points d'arrêt différés (en attente), ce qui facilite cette opération:

gdb /bin/ls
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu"...
(no debugging symbols found)
(gdb) b write
Function "write" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (write) pending.
(gdb) r
Starting program: /bin/ls
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
[Thread debugging using libthread_db enabled]
(no debugging symbols found)
(no debugging symbols found)
[New Thread 0x7f98d2d23780 (LWP 7029)]
[Switching to Thread 0x7f98d2d23780 (LWP 7029)]

Breakpoint 1, 0x00007f98d2264bb0 in write () from /lib/libc.so.6
(gdb)

Comme vous pouvez le voir, gdb gère automatiquement tous les threads utilisés par l'exécutable. Vous n'avez rien de spécial à faire pour les discussions. Le point d'arrêt fonctionnera dans n'importe quel thread.

Alternativement, si vous voulez attacher le débogueur à une application en cours d'exécution (j'utilise tail -f/tmp/ttt ici comme exemple):

ps ux | grep tail
lothar    8496  0.0  0.0   9352   804 pts/3    S+   12:38   0:00 tail -f /tmp/ttt
lothar    8510  0.0  0.0   5164   840 pts/4    S+   12:39   0:00 grep tail

gdb
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu"...
(no debugging symbols found)
(gdb) attach 8496
Attaching to program: /usr/bin/tail, process 8496
Reading symbols from /lib/librt.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/librt.so.1
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/libpthread.so.0...(no debugging symbols found)...done.
[Thread debugging using libthread_db enabled]
[New Thread 0x7f24853f56e0 (LWP 8496)]
Loaded symbols for /lib/libpthread.so.0
Reading symbols from /lib/ld-linux-x86-64.so.2...
(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
(no debugging symbols found)
0x00007f2484d2bb50 in nanosleep () from /lib/libc.so.6
(gdb) b write
Breakpoint 1 at 0x7f2484d57bb0
(gdb) c
Continuing.
[Switching to Thread 0x7f24853f56e0 (LWP 8496)]

Breakpoint 1, 0x00007f2484d57bb0 in write () from /lib/libc.so.6
(gdb)
30
lothar

Normalement, la procédure de débogage d’une bibliothèque partagée est sensiblement la même que pour le débogage d’un exécutable. La principale différence est qu’il peut être impossible de définir un point d’arrêt tant que la bibliothèque partagée n’est pas chargée en mémoire. Vous attachez le débogueur à l'exécutable principal.

Si vous déboguez une application qui ne vous appartient pas, mais utilise votre module dans une architecture de plug-in, vous utilisez toujours la même méthode. Assurez-vous (comme toujours) que vous disposez des informations de débogage disponibles pour votre bibliothèque partagée. Dans Windows, vous générez un fichier .pdb. Avec gcc, je pense que vous spécifiez un indicateur de compilateur spécial (-g?) Pour garantir que les informations de débogage sont fournies. Vous attachez le débogueur à l'application tierce.

9
1800 INFORMATION

Un autre exemple suite à la réponse de lothar:

J'exécute des tests sur une bibliothèque dynamique test.so (compilée à partir de test.c) sous Linux à l'aide de python et de la bibliothèque de tests unitaires de python unittest appelée tests/test_pwmbasic.py. (Le schéma de nommage est un peu monotone, je me rends compte que maintenant)

~/my/test/path/
    tests/
        __init__.py
        test_pwmbasic.py
    test.c
    test.so

Je veux déboguer ce qui est dans test.so à partir du stimulus dans test_pwmbasic.py. Voici comment je l'ai fait fonctionner ...

$ cd ~/my/test/path
$ gdb $(which python)
   ... gdb blah ...
(gdb) b test.c:179
(gdb) run
>>> from tests.test_pwmbasic import *
>>> import unittest
>>> unittest.main()
   ... unittest blah ...
Breakpoint 1, pwmTest_setDutyCycles (dutyCycles=0x7ffff7ece910) at ./test.c:179
(gdb) print pwm_errorCode
$1 = PWM_ERROR_NONE

et maintenant je veux épouser gdb

remarque: test.c inclut également ../pwm.c, afin que je puisse également utiliser un point d'arrêt dans cette bibliothèque avec

(gdb) b pwm.c:123
3
FraggaMuffin

Cela faisait longtemps que je n’avais pas besoin d’utiliser dbx sous AIX et j’étais également confronté à ce problème. L'installation de gdb n'était pas une option pour moi.

dbx  /path/to/your/program
(dbx) run [args to your program]
(dbx) set $ignoreonbptrap           # I kept hitting a trace/bpt trap
(dbx) set $deferevents              # allows setting bp in not loaded shared library
(dbx) set $repeat                   # useful, repeat commands with <enter> tjust like gdb
(dbx) stop in MySharedLibraryFunc   # defers breakpoint
(dbx) cont
1
codeDr

Je me souviens d'avoir testé des bibliothèques partagées en créant une application fictive qui l'utilisait. Si vous êtes prêt à faire beaucoup de travail, vous pouvez créer une deuxième bibliothèque partagée fictive qui ne fait que collecter des informations sur la manière dont la bibliothèque est utilisée par l'application tierce, puis laissez votre application fictive relire ces informations.

Bien sûr, ne doutez jamais de la puissance d'appels printf et fprintf bien placés.

1
Chas. Owens

Vous pouvez essayer de compiler et de lier la bibliothèque statiquement pour la déboguer.
Si votre bogue n'apparaît que lorsqu'il est compilé en partage, cela peut vous donner des indices.

0
PiedPiper