Ich versuche, das Kernelmodul zu debuggen. Ich vermute da einige Speicherlecks. Um dies zu überprüfen, habe ich einen Build mit aktiviertem Memory Leak Debugging für Kernel und Module vorbereitet. Und ich wurde davor gewarnt:
[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)
Es ist kein Problem, Adressen zu übersetzen, die auf den Kernel zeigen:
Aber ich kann das nicht tun, wenn die Adressen von my_module stammen:
$ addr2line -f -e vmlinux.kmeml bf0a56b8
??
??:0
Ich habe es auch mit der Moduldatei versucht:
$ addr2line -f -e my_module.ko bf0a56b8
??
??:0
Wie kann ich diese Adressen in Dateien und Zeilennummern übersetzen?
Eugen
Ich nehme an, das Modul wurde mit Debug-Informationen erstellt. Wenn ja, können Sie gdb oder objdump verwenden, um herauszufinden, zu welcher Quelldatei und Zeile jede Adresse gehört. Etwas wie das:
$ gdb "$(modinfo -n my_module)"
(gdb) list *(some_function+0x12c)
Gdb teilt nun den Namen der Quelldatei und die darin enthaltene Zeile mit.
Sie können auch mit objdump etwas Ähnliches machen, aber es ist etwas schwieriger. Demontieren Sie zuerst das Modul:
objdump -dSlr my_module.ko > my_module.disasm
Bei Anruf mit -S Option, objdump wird die Quellzeilen gegebenenfalls in die resultierende Auflistung aufnehmen.
Sie können nun in der Liste bis zum Code von scrollen some_function, finden Sie die Anweisung bei Offset 0x12c vom Beginn der Funktion. Die Quellzeile wird darüber angezeigt.
BEARBEITEN:
Nach vielen Versuchen fand ich das aber heraus addr2line kann tatsächlich für Kernelmodule verwendet werden, eu-addr2line (ein ähnliches Tool von elfutils) scheint zuverlässiger zu sein. Das heißt, manchmal addr2line Ausgabe falscher Quellzeilen, aber eu-add2line habe die Dinge richtig gemacht.
Benutzen eu-addr2linemüssen möglicherweise die Bibliotheken libdw und libebl installiert werden, wenn sie nicht bereits zusammen mit elfutils installiert sind.
Wenn die Debug-Informationen für ein Kernel-Modul in einer separaten Datei gespeichert sind (dies ist oft der Fall für die von den großen Linux-Distributionen bereitgestellten Kernel), sollte der Pfad zu dieser Datei als verwendet werden <path_to_the_module>.
Eine Randbemerkung. Wenn Sie mit x86 arbeiten und Ihr Linux-Kernel 2.6.31 oder neuer ist, finden Sie möglicherweise ein leichteres KEDR-System (kedr.berlios.de) nützlich, um Ihre Module auf Speicherlecks zu überprüfen. Im Gegensatz zu eingebauten Kernel-Einrichtungen wie Kmemleak erfordert KEDR keinen Neuaufbau des Kernels. Es sollte recht einfach einzurichten und zu verwenden sein.
– Eugen
27. Mai 2011 um 14:01 Uhr
gby
Sie müssen in der Tat addr2line auf Ihrem Kernelmodul und nicht auf dem Kernel ausführen, aber es gibt eine Wendung –
Die Kernel-Moduldatei verwendet relative Adressen, die Absturzadresse, die Sie haben, besteht tatsächlich aus:
Offset innerhalb des Moduls + Modulladeadresse ist Speicher.
Was Sie also tun müssen, ist, zuerst die Ladeadresse des Kernelmoduls im Speicher zu finden, indem Sie cat /proc/modules ausführen und herausfinden, zu welchem Modul diese Adresse gehört. Falls Sie es nicht wissen, subtrahieren Sie die Ladeadresse des Moduls von der Absturzadresse und füttere das an addr2line
viel Glück
Vielleicht sollten Sie den Parameter -g verwenden, um das Modul zu kompilieren.