it-swarm.com.de

Wie füge ich C-Backtrace in einen Kernel-Modul-Code ein?

Ich versuche also herauszufinden, welche Kernelprozesse einige Funktionen in einem Blocktreiber aufrufen. Ich dachte, es wäre einfach, backtrace () in die C-Bibliothek aufzunehmen. Aber ich habe Probleme, den Backtrace zu laden.

Ich habe diese Beispielfunktion kopiert, um die Rückverfolgung zu zeigen:

http://www.linuxjournal.com/files/linuxjournal.com/linuxjournal/articles/063/6391/6391l1.html

Alle Versuche zu kompilieren haben an der einen oder anderen Stelle den Fehler, dass eine Datei nicht gefunden werden kann oder dass die Funktionen nicht definiert sind.

Hier ist was am nächsten kommt.

In das Makefile habe ich die Compiler-Direktiven eingefügt:

 -rdynamic -I/usr/include 

Wenn ich den zweiten auslasse, -I/usr/include, meldet der Compiler, dass er den erforderlichen Header execinfo.h nicht finden kann.

Als nächstes habe ich in dem Code, in dem ich die Rückverfolgung durchführen möchte, die Funktion aus dem Beispiel kopiert:

//trying to include the c backtrace capability
#include <execinfo.h>

void show_stackframe() {
void *trace[16];
char **messages = (char **)NULL;
int i, trace_size = 0;

trace_size = backtrace(trace, 16);
messages = backtrace_symbols(trace, trace_size);
printk(KERN_ERR "[bt] Execution path:\n");
for (i=0; i<trace_size; ++i)
    printk(KERN_ERR "[bt] %s\n", messages[i]);
}
//backtrace function

Ich habe den Aufruf dieser Funktion später in eine Blocktreiberfunktion gestellt, in der das erste Zeichen des Fehlers auftritt. Einfach:

show_stackframe();

Also, wenn ich es kompiliere, die folgenden Fehler:

[email protected]:~/2.6-32$ make -s
Invoking make againt the kernel at /lib/modules/2.6.32-5-686/build
In file included from /usr/include/features.h:346,
        from /usr/include/execinfo.h:22,
        from /home/linux/2.6-32/block/block26.c:49:
/usr/include/sys/cdefs.h:287:1: warning: "__always_inline" redefined
In file included from /usr/src/linux-headers-2.6.32-5-common/include/linux/compiler-gcc.h:86,
        from /usr/src/linux-headers-2.6.32-5-common/include/linux/compiler.h:40,
        from /usr/src/linux-headers-2.6.32-5-common/include/linux/stddef.h:4,
        from /usr/src/linux-headers-2.6.32-5-common/include/linux/list.h:4,
        from /usr/src/linux-headers-2.6.32-5-common/include/linux/module.h:9,
        from /home/linux/2.6-32/inc/linux_ver.h:40,
        from /home/linux/2.6-32/block/block26.c:32:
/usr/src/linux-headers-2.6.32-5-common/include/linux/compiler-gcc4.h:15:1: warning: this is the location of the previous definition
    /home/linux/2.6-32/block/block26.c:50: warning: function declaration isn’t a prototype
WARNING: "backtrace" [/home/linux/2.6-32/ndas_block.ko] undefined!
WARNING: "backtrace_symbols" [/home/linux/2.6-32/ndas_block.ko] undefined!

Hinweis: block26.c ist die Datei, von der ich den Backtrace erhalten möchte.

Gibt es einen offensichtlichen Grund, warum die Zeichen backtrace und backtrace_symbols undefiniert bleiben, wenn sie in die .ko-Module kompiliert werden?

Ich vermute es, weil ich das Compiler-Include execinfo.h verwende, das sich auf dem Computer befindet und nicht in das Modul geladen wird.

Es ist meine ungebildete Vermutung, um es gelinde auszudrücken.

Kann jemand eine Hilfe anbieten, um die Backtrace-Funktionen in das Modul zu laden?

Vielen Dank, dass Sie sich diese Anfrage angesehen haben.

Ich arbeite an Debian. Wenn ich die Funktion und so herausnehme, kompiliert das Modul gut und funktioniert fast perfekt.

Von ndasusers

23
ndasusers

Verwenden Sie die dump_stack()-Funktion in Ihrem Kernel-Modul, um den Stack-Inhalt und eine Rückverfolgung zum Kernel-Protokoll zu drucken. Es ist in linux/kernel.h im Include-Ordner im Kernel-Quellverzeichnis deklariert.

45
jmkeyes

Wenn Sie den Stack-Trace irgendwie speichern und seine Elemente verarbeiten müssen, kann save_stack_trace() oder dump_trace() auch eine Option sein. Diese Funktionen sind in <linux/stacktrace.h> bzw. <asm/stacktrace.h> deklariert.

Es ist nicht so einfach wie dump_stack(), aber wenn Sie mehr Flexibilität benötigen, können sie hilfreich sein. 

So kann save_stack_trace() verwendet werden (ersetzen Sie HOW_MANY_ENTRIES_TO_STORE mit dem Wert, der Ihren Bedürfnissen entspricht, 16-32 ist normalerweise mehr als genug):

unsigned long stack_entries[HOW_MANY_ENTRIES_TO_STORE];
struct stack_trace trace = {
    .nr_entries = 0,
    .entries = &stack_entries[0],

    .max_entries = HOW_MANY_ENTRIES_TO_STORE,

    /* How many "lower entries" to skip. */
    .skip = 0
}; 
save_stack_trace(&trace);

Das stack_entries-Array enthält nun die entsprechenden Anrufadressen. Die Anzahl der gefüllten Elemente ist nr_entries.

Noch eine Sache, die hervorgehoben werden sollte. Wenn die Stack-Einträge, die zur Implementierung von save_stack_trace(), dump_trace() oder dump_stack() gehören, nicht ausgegeben werden sollen (auf verschiedenen Systemen kann die Anzahl solcher Einträge variieren), kann der folgende Trick angewendet werden, wenn Sie save_stack_trace() verwenden. Sie können __builtin_return_address(0) als "Anker" -Eintrag verwenden und nur die Einträge bearbeiten, die "nicht darunter" sind.

19
Eugene

Die Funktion dump_stack() is kann zum Drucken Ihres Stapels und somit zum Zurückverfolgen verwendet werden. Wenn Sie jedoch vorsichtig vorgehen und nicht in einen sich wiederholenden Pfad wie Schleifen oder Paketempfangsfunktionen setzen, kann der Dmesg-Puffer gefüllt werden. Dies kann zum Absturz des eingebetteten Geräts (weniger Speicher und CPU) führen.

Diese Funktion ist in linux/kernel.h deklariert.

0
SHASHI BHUSAN

Ich weiß, dass es sich bei dieser Frage um Linux handelt, aber da dies das erste Ergebnis für "Backtrace-Kernel" ist, haben wir hier ein paar weitere Lösungen:


DragonFly BSD

Es ist print_backtrace(int count) von /sys/sys/systm.h . Es ist in /sys/kern/kern_debug.c und/oder /sys/platform/pc64/x86_64/db_trace.c implementiert. Es kann durch Suchen nach panic, das in /sys/kern/kern_shutdown.c implementiert ist, gesucht werden und ruft print_backtrace(6) auf, wenn DDB definiert ist und trace_on_panic gesetzt ist, was beide Standardeinstellungen sind.


FreeBSD

Es ist kdb_backtrace(void) von /sys/sys/kdb.h . Ebenso ist es leicht zu finden, indem Sie herausfinden, was die panic -Implementierung aufruft, wenn trace_on_panic wahr ist.


OpenBSD

Wenn Sie die panic - Route wählen, scheint es sich um db_stack_dump() ZU HANDELN, IMPLEMENTIERT IN /sys/ddb/db_output.c . Die einzige Kopfzeile ist /sys/ddb/db_output.h .

0
cnst