Debugging — Änderungen 2362 → 2363

Zeile 5: Zeile 5:
  
 
= print(f)/cout =
 
= print(f)/cout =
−
Diese Methode ist schon etwas praktischer als die letzte. Debug-Ausgaben werden eigentlich in jedem Stadium der Entwicklung immer wieder gebraucht. Man platziert an den relevanten Stellen im Code Text-Ausgaben um beispielsweise zu sehen, welche Funktion aufgerufen wurde oder wie oft eine Schleife durchläuft usw.
+
Diese Methode ist schon etwas praktischer als die letzte. Debug-Ausgaben werden eigentlich in jedem Stadium der Entwicklung immer wieder gebraucht. Man platziert an den relevanten Stellen im Code [[Textausgabe | Text-Ausgaben]] um beispielsweise zu sehen, welche Funktion aufgerufen wurde oder wie oft eine Schleife durchläuft usw.
  
 
= RS232 =
 
= RS232 =
Zeile 17: Zeile 17:
  
 
= Exception-Meldungen =
 
= Exception-Meldungen =
−
Wenn der Kernel schon ein wenig weiter ausgebaut ist, und Exceptions abfängt, können diese Meldungen so ausgebaut werden, damit sie alle nötigen Informationen ausgeben. Um die Registerinhalte auszugeben empfiehlt es sich, diese in der ISR für die Exceptions auf den Stack zu legen, und dem Exception-Handler einen Pointer auf das zuletzt gepushte Register zu übergeben. Dabei sollte man darauf, dass nichts anderes zwischen dem Interrupt-Stack-Frame und den Registern liegt, da der Handler sonst nicht mehr wirklich an eip und esp aus dem Interrupt-Stack-Frame ran kommen kann. Der Exception-Handler kann dann eine nette Meldung mit allen nötigen Infos ausgeben.
+
Wenn der Kernel schon ein wenig weiter ausgebaut ist, und [[Ausgabe_2#Exceptions | Exceptions]] abfängt, können diese Meldungen so ausgebaut werden, damit sie alle nötigen Informationen ausgeben. Um die Registerinhalte auszugeben empfiehlt es sich, diese in der [[ISR]] für die Exceptions auf den Stack zu legen, und dem Exception-Handler einen Pointer auf das zuletzt gepushte Register zu übergeben. Dabei sollte man darauf, dass nichts anderes zwischen dem Interrupt-Stack-Frame und den Registern liegt, da der Handler sonst nicht mehr wirklich an eip und esp aus dem Interrupt-Stack-Frame ran kommen kann. Der Exception-Handler kann dann eine nette Meldung mit allen nötigen Infos ausgeben.
  
 
= objdump =
 
= objdump =
−
Sobald man die Adresse hat, muss man daraus irgendwie auf die Codestelle schliessen können. Dabei kann das GNU-Tool objdump eine grosse Hilfe sein. Dies ist aber nur möglich, wenn man ein Binärformat wie ELF benutzt, bei flachen Binaries fehlen dem Tool nötige Informationen. objdump kann dabei mit dem Parameter -d Assembler-Code mit Adresse vor jeder Instruktion generieren. Wenn man den Code mit Debug-Infos (bei gcc mit dem Parameter -g) kompiliert und linkt kann objdump mit dem Parameter -S sogar den zugehörigen Quelltext der ursprünglichen Sprache anzeigen.
+
Sobald man die Adresse hat, muss man daraus irgendwie auf die Codestelle schliessen können. Dabei kann das GNU-Tool objdump eine grosse Hilfe sein. Dies ist aber nur möglich, wenn man ein Binärformat wie [[elf|ELF]] benutzt, bei flachen Binaries fehlen dem Tool nötige Informationen. objdump kann dabei mit dem Parameter -d Assembler-Code mit Adresse vor jeder Instruktion generieren. Wenn man den Code mit Debug-Infos (bei gcc mit dem Parameter -g) kompiliert und linkt kann objdump mit dem Parameter -S sogar den zugehörigen Quelltext der ursprünglichen Sprache anzeigen.
 
Dieses Feature macht aber scheinbar in den aktuellen Versionen vorallem bei grossen Dateien noch Probleme. Dabei wird der Source am Anfang oft noch angezeigt, dann aber irgendwann wird nur noch der Assembler-Code angezeigt. Das kann man am besten umgehen, indem man den Abstand der gesuchten Speicherstelle zum Funktionsanfang berechnet, und danach nur den Dump der entsprechenden Objektdateien ansieht.
 
Dieses Feature macht aber scheinbar in den aktuellen Versionen vorallem bei grossen Dateien noch Probleme. Dabei wird der Source am Anfang oft noch angezeigt, dann aber irgendwann wird nur noch der Assembler-Code angezeigt. Das kann man am besten umgehen, indem man den Abstand der gesuchten Speicherstelle zum Funktionsanfang berechnet, und danach nur den Dump der entsprechenden Objektdateien ansieht.