c charger - addr2line sur le module noyau




un linux (4)

Vous devriez peut-être utiliser le paramètre -g pour compiler le module.

J'essaie de déboguer le module du noyau. Je soupçonne d'avoir des fuites de mémoire. Pour le vérifier, j'ai préparé la compilation avec le débogage de fuite de mémoire activé pour le noyau et les modules. Et j'ai eu un avertissement de cela:

[11839.429168] slab error in verify_redzone_free(): cache `size-64': memory outside object was overwritten
[11839.438659] [<c005575c>] (unwind_backtrace+0x0/0x164) from [<c0116ca0>] (kfree+0x278/0x4d8)
[11839.447357] [<c0116ca0>] (kfree+0x278/0x4d8) from [<bf083f48>] (some_function+0x18/0x1c [my_module])
[11839.457214] [<bf083f48>] (some_function+0x18/0x1c [my_module]) from [<bf08762c>] (some_function+0x174/0x718 [my_module])
[11839.470184] [<bf08762c>] (some_function+0x174/0x718 [my_module]) from [<bf0a56b8>] (some_function+0x12c/0x16c [my_module])
[11839.483917] [<bf0a56b8>] (some_function+0x12c/0x16c [my_module]) from [<bf085790>] (some_function+0x8/0x10 [my_module])
[11839.496368] [<bf085790>] (some_function+0x8/0x10 [my_module]) from [<bf07b74c>] (some_function+0x358/0x6d4 [my_module])
[11839.507476] [<bf07b74c>] (some_function+0x358/0x6d4 [my_module]) from [<c00a60f8>] (worker_thread+0x1e8/0x284)
[11839.517211] [<c00a60f8>] (worker_thread+0x1e8/0x284) from [<c00a9edc>] (kthread+0x78/0x80)
[11839.525543] [<c00a9edc>] (kthread+0x78/0x80) from [<c004f8fc>] (kernel_thread_exit+0x0/0x8)

Il n'y a pas de problème pour traduire les adresses pointant vers le noyau:

$ addr2line -f -e vmlinux.kmeml c0116ca0
verify_redzone_free
/[...]/kernel/mm/slab.c:2922

Mais je ne peux pas le faire si les adresses proviennent de my_module:

$ addr2line -f -e vmlinux.kmeml bf0a56b8
??
??:0

J'essayais aussi avec le fichier de module:

$ addr2line -f -e my_module.ko bf0a56b8
??
??:0

Comment puis-je traduire ces adresses en fichiers et numéros de ligne?


Je suppose que le module est construit avec les informations de débogage incluses. Si c'est le cas, vous pouvez utiliser gdb ou objdump pour trouver le fichier source et la ligne auxquels appartient chaque adresse. Quelque chose comme ça:

$ gdb "$(modinfo -n my_module)"
(gdb) list *(some_function+0x12c)

Gdb va maintenant indiquer le nom du fichier source et la ligne qu'il contient.

Vous pouvez également faire la même chose avec objdump mais c'est un peu plus difficile. Tout d'abord, démontez le module:

objdump -dSlr my_module.ko > my_module.disasm

Appelé avec l'option -S , objdump inclura les lignes sources dans la liste résultante, le cas échéant.

Vous pouvez maintenant faire défiler la liste jusqu'au code de some_function , trouver l'instruction au décalage 0x12c depuis le début de la fonction. La ligne source sera indiquée au-dessus.

MODIFIER:

Après de nombreuses expériences, j'ai découvert que bien que addr2line puisse être utilisé pour les modules du noyau, eu-addr2line (un outil similaire à elfutils) semble être plus fiable. C'est-à-dire que parfois, les lignes source addr2line incorrectes, mais eu-add2line fait les choses.

Pour utiliser eu-addr2line , il peut être nécessaire d'installer les bibliothèques libdw et libebl si elles ne sont pas déjà installées avec elfutils.

L'utilisation est similaire à celle de addr2line :

eu-addr2line -f -e <path_to_the_module> -j <section_name> <offset_in_section>

Si les informations de débogage pour un module de noyau sont stockées dans un fichier séparé (c'est souvent le cas pour les noyaux fournis par les principales distributions Linux), le chemin d'accès à ce fichier doit être utilisé comme <path_to_the_module> .


Vous devez en effet lancer addr2line sur votre module noyau et non sur le noyau mais il y a une torsion -

le fichier de module du noyau utilise des adresses relatives, l'adresse de crash que vous avez est en fait composée de:

offset à l'intérieur du module + l'adresse de chargement du module est la mémoire.

Donc, ce que vous devez faire est de trouver l’adresse de chargement du moduel du noyau en premier en faisant cat / proc / modules, en trouvant à quel module cette adresse appartient, au cas où vous ne le sauriez pas, soustrayez l’adresse de chargement du module et nourrir cela à addr2line

bonne chance


Basé sur le lien dans la réponse de @ sdaau ( http://www.mail-archive.com/[email protected]/msg00031.html ), j'ai créé mon propre script pour continuer simplement à envoyer des "s" et à lire la sortie de gdb en continu, lors de l'impression des sorties vers le fichier texte et le terminal, bien sûr, mon script peut être modifié pour répondre aux besoins de n'importe qui. Cependant, j'espère que les modifications apportées répondent aux besoins de la plupart des utilisateurs.

http://www.codeground.net/coding/gdb-step-into-all-lines-to-get-full-application-flow/

wget http://www.codeground.net/downloads/gdbwalkthrough.c
gcc gdbwalkthrough.c -o gdbwalkthrough
./gdbwalkthrough <application full path> [application arguments]






c debugging module linux-kernel kernel