2012-10-28 18 views
23

Der Call Trace enthält Einträge wie folgt aus:Was bedeuten Fragezeichen? im Linux-Kernel Panik Anrufspuren?

[<deadbeef>] FunctionName+0xAB/0xCD [module_name] 
[<f00fface>] ? AnotherFunctionName+0x12/0x40 [module_name] 
[<deaffeed>] ClearFunctionName+0x88/0x88 [module_name] 

Was ist die Bedeutung der ist '?' Vor AnotherFunctionName markieren?

Antwort

27

'?' bedeutet, dass die Information über diesen Stack-Eintrag wahrscheinlich nicht zuverlässig ist.

Der Stack-Ausgabemechanismus (siehe die Implementierung von dump_trace() function) konnte nicht beweisen, dass die gefundene Adresse eine gültige Rückgabeadresse im Aufruf-Stack ist.

'?' selbst wird von printk_stack_address() ausgegeben.

Der Stapeleintrag ist möglicherweise gültig oder nicht. Manchmal kann man es einfach überspringen. Es kann hilfreich sein, die Demontage des betroffenen Moduls zu untersuchen, um zu sehen, welche Funktion bei ClearFunctionName+0x88 aufgerufen wird (oder, auf x86, unmittelbar vor dieser Position).

Zuverlässigkeit bezüglich

Auf x86, wenn dump_stack() aufgerufen wird, die Funktion, die den Stapel tatsächlich untersucht wird print_context_stack() in arch/x86/kernel/dumpstack.c definiert. Schau dir seinen Code an, ich werde versuchen, es unten zu erklären.

Ich nehme an, dass DWARF2-Stapelabwicklungsfunktionen in Ihrem Linux-System nicht verfügbar sind (höchstwahrscheinlich nicht, wenn es sich nicht um OpenSUSE oder SLES handelt). In diesem Fall scheint print_context_stack() folgendes zu tun.

Es beginnt mit einer Adresse (Variable 'stack' im Code), die garantiert die Adresse eines Stapelspeicherorts ist. Es ist tatsächlich die Adresse einer lokalen Variablen in dump_stack().

Die Funktion erhöht diese Adresse wiederholt (while (valid_stack_ptr ...) { ... stack++}) und prüft, ob das, worauf sie verweist, auch eine Adresse im Kernel-Code sein könnte (if (__kernel_text_address(addr)) ...). Auf diese Weise wird versucht, die Rücksprungadressen der Funktionen zu finden, die beim Aufruf dieser Funktionen auf den Stapel geschoben wurden.

Natürlich ist nicht jeder vorzeichenlose lange Wert, der wie eine Rücksprungadresse aussieht, tatsächlich eine Rücksendeadresse. Also versucht die Funktion das zu überprüfen. Wenn Frame-Pointer im Code des Kernels verwendet werden (% ebp /% rbp-Register werden dafür verwendet, wenn CONFIG_FRAME_POINTER gesetzt ist), können sie verwendet werden, um die Stack-Frames der Funktionen zu durchlaufen. Die Rücksprungadresse für eine Funktion liegt direkt über dem Rahmenzeiger (d. H. Bei %ebp/%rbp + sizeof(unsigned long)). print_context_stack prüft genau das.

Wenn es einen Stapelrahmen gibt, für den der Wert "Stack" auf die Rückgabeadresse verweist, wird der Wert als zuverlässiger Stapeleintrag betrachtet. ops->address wird dafür mit reliable == 1 aufgerufen, es wird schließlich printk_stack_address() aufrufen und der Wert wird als eine zuverlässige Call-Stack-Eintrag ausgegeben. Andernfalls wird die Adresse als unzuverlässig angesehen. Es wird trotzdem ausgegeben, aber mit '?' vorangestellt.

[NB] Wenn Rahmenzeigerinformationen nicht verfügbar sind (z. B. wie in Debian 6), werden alle Aufrufstapeleinträge aus diesem Grund als unzuverlässig markiert.

Die Systeme mit DWARF2 Unwinding-Unterstützung (und mit CONFIG_STACK_UNWIND gesetzt) ​​ist eine ganz andere Geschichte.

+0

Große Antwort - es fehlt eine Sache, um es zu vervollständigen (und ich bin etwas verblüfft von der Ebene der Indirektion in der Arc-Code) - Was macht den Eintrag unzuverlässig? – qdot

+0

Ich habe meine Antwort bearbeitet. Hoffentlich ist meine Erklärung nicht zu verwirrend. – Eugene

+0

Anreise :) Ihre Antwort bestätigt tatsächlich einige meiner Verdächtigungen darüber, wie es funktioniert - um ein bisschen Hintergrundinformationen zu geben, ich versuche, einen binären Blob + Wrapper wie Treiber zu aktualisieren - so ist der Kernel eigentlich mein eigener Build .. Der Grund, warum ich verwirrt wurde und eine Erklärung wollte, ist, dass anscheinend einige Funktionen innerhalb des Blobspeichers Zeiger in lokalen Variablen funktionieren, was das ganze System ein wenig ausschaltet. Bitte beende deine "ganze andere Geschichte" - vor allem, wie es funktioniert, wenn der Hauptkern DWARF2 ist, aber ein Teil eines Moduls nicht. – qdot