Hallo,
mir ist leider kein besserer Titel eingefallen.
Baue ja immernoch an meinem MIPS1 GDB Server rum.
Der GDB kann sich auch mit dem verbinden und man kann Speicher sowie
Register lesen/schreiben.
Breakpoints gehen auch 1a.
Nur "richtiges" Debuggen ala durchsteppen geht nicht, da macht der GDb
total komische Sachen.
Das MIPS Programm ist mit der Option -g gebaut, damit ich Debuginfos in
der elf habe.
Diese elf Datei gebe ich dem GDB als Option mit und mit dem GDB load
Befehl landet der Programmcode dann auch im Prozessor.
Dann setze ich einen Breakpoint auf uart_init und lasse den GDB laufen.
Natürlich bleibt er dann beim Aufruf von uart_init stehen, das funzt
also.
Wenn ich nun mit step durchsteppe, dann wirds komisch.
Der GDB zeigt mir manche Codezeilen doppelt an und springt auch wild in
den Codezeilen herum:
das sieht natürlich falsch aus und dabei hat die CPU noch nichtmal eine
Funktion aufgerufen, laut "info register" hat die CPU dabei diesen ASM
Code durchlaufen:
1
0000fe88 <uart_init>:
2
fe88: 27bdffc8 addiu sp,sp,-56
3
fe8c: 2482ffff addiu v0,a0,-1
4
fe90: afb4002c sw s4,44(sp)
5
fe94: afb30028 sw s3,40(sp)
6
fe98: 3c140004 lui s4,0x4
7
fe9c: 3c130004 lui s3,0x4
8
fea0: 00021080 sll v0,v0,0x2
9
fea4: 2694d130 addiu s4,s4,-11984
10
fea8: 2673d120 addiu s3,s3,-12000
11
feac: 000418c0 sll v1,a0,0x3
Irgendwie sieht es so aus, als würde der GDb die Debuginformationen
ignorieren?
Denn mit den Infos würde er ja soweit gehen bis eine C Codezeile
abgeschlossen ist.
Fällt da jemanden ein worans liegen könnte?
Der Optimizer ist an.
Der darf auch mehrere C Zeilen in eine CPU-Instruktion packen und auch
Instruktionen lustig durcheinander würfeln - solange das Ergebnis
dasselbe ist. Macht er gerne bei Initialisierungen von Variablen um ein
paar Tatkzyklen zu sparen.
Verständlich wird das Ganze erst wenn man sich das Disassembly genau
anschaut.
Der oben gezeigte Assembler Code sieht wie ein Prolog einer Funktion
aus. Der ist schlecht einer konkreten Zeile zuzuordnen, daher nimmt er
die allererste.
Ist "fifos_init" zufällig ein Macro?
Eigentlich (böses Wort) ist -O2 raus beim debuggen.
Aber das hat natürlich noch keiner der vorcompilierten Library gesagt,
argh...
Danke für den Hinweis!
Hier ist das erklärt:
http://www.delorie.com/gnu/docs/gdb/gdb_17.html
Noch ne kurze andere Frage:
Wie kann ich mit dem GDB ein laufendes Programm anhalten?
In meinem GDB Server ist der Befehl dafür implementiert, aber beim GDB
selbst ist nach continue ja kein Command Prompt mehr vorhanden und
STRG+C sendet keinen Befehl ab.
Mw E. schrieb:> Noch ne kurze andere Frage:> Wie kann ich mit dem GDB ein laufendes Programm anhalten?
In eine "freestanding environment", also einem ohne OS o.ä., muss die
Hardware (Prozessor und Debugger-Hardware) das unterstützen. In einem
"hosted environment", also einem mit OS, Monitor, X-visor, o.ä., ist es
oft Aufgabe des Hosts (also des OS), kann aber auch durch die HW
erledigt bzw. unterstützt werden.
Jetzt habe ich ewig nichts mehr mit MIPS gemacht. Ich erinnere mich
dunkel, dass die CPU einen eigenen Debug-Mode hat, den man u.a. mit
einem Debug Interrupt erreichen kann. Dann steht die CPU und man kann in
den Gedärmen rumwühlen.
Den Interrupt, oder was auch immer MIPS heute so verwendet, müsste durch
deine Debugging-HW, gesteuert durch den Debugging-Server, ausgelöst
werden.
Auf GDB-Seite ist das Ganze ein Hack, weil der Mechanismus ursprünglich
für Unix-Programme die durch Signale abgebrochen werden können gedacht
war. Erstmal gibt es zwei Stop-Modi, all-stop
(https://sourceware.org/gdb/onlinedocs/gdb/All_002dStop-Mode.html) und
non-stop - ja, non-stop ist ein Stop-Modus... (für einzelne Threads).
Wir gehen mal von all-stop aus ("set non-stop off"). Auf dem
Remote-Interface hat GDB zwei Möglichkeiten ein all-stop auszulösen:
https://sourceware.org/gdb/onlinedocs/gdb/Interrupts.html#Interrupts
Entweder durch eine Telnet Break-Sequenz, oder ein Zeichensequenz wie
0x03 (kann auch anders, z.B. als 0x03'g' konfiguriert sein).
Du könntest mit Wireshark nachsehen, was GDB an den Debug-Server sendet.
Wenn es die Telnet Break-Sequenz ist, dann mal auf 0x03 umstellen, "set
remotebreak off", "set remote interrupt-sequence Ctrl-C".
Wenn gar nichts gesendet wird, sieh mit "info signals" nach, wie GDB ein
Ctrl-C (was einem SIGINT entspricht) handhabt. Wenn SIGINT nicht auf
stop steht, dann SIGINT mittels "handle SIGINT stop" setzen.
Wenn das auch nichts hilft, dann gibt deine Shell / dein Command-Window
Ctrl-C nicht an den GDB weiter: Shell konfigurieren oder wechseln.
Sehr nützliche Informationen, sowas müsste man sich sonst mühselig
zusammenklamüsern.
Da ich den GDB Server, wie oben erwähnt, selber geschrieben habe, habe
ich eh in der Hand was dieser Tut.
Mein GDB Server bekommt ja vom GDB selber nicht den Befehl, dass er die
CPU anhalten soll. Zudem ist die MIPS CPU selber gebaut und daher hab
ich da auch ein Debugregister, welches die CPU anhalten kann.
Wenn denn mein GDB Server diesen Befehl bekommen würde ;)
Die CPU: http://www.fritzler-avr.de/spaceage2/
Die Konsole leitet STRG+C schon weiter, der GDb zeig dann "^C" an wenn
ich das drückeund wenn ich sehr oft STRG+C dem GDb sende, dann fragt er
mich auch, ob ich die Verbindung zum remote target abbrechen möchte.
Wireshark brauch ich nicht (dachte ich), mein GDB Server loggt momentan
noch den Debugoutput auf der Konsole mit. Daher weis ich ja, dass vom
GDB kein Befehl kommt.
Aber der GDB sendet wohl doch was, dabei habe ich eigentlich auf 0x03
geachtet.
GDB sendet dann bei mir wohl die BREAK Sequenz. Ich dachte bisher, dass
dann ein vCont Packet kommen muss. Weil ich GDB bei der Init Seuquenz
gesagt habe, dass mein vcont alles unterstützt.
Jedenfalls gehts jetzt, ich frage mit ioctl ab ob der TCP Socket Bytes
hat und halte dann die CPU an und sage dem GDB, dass die CPU angehalten
ist -> LÄUFT!
Mw E. schrieb:> In meinem GDB Server ist der Befehl dafür implementiert, aber beim GDB> selbst ist nach continue ja kein Command Prompt mehr vorhanden und> STRG+C sendet keinen Befehl ab.
Der GDB selbst sollte aber auf CTRL+C oder CTRL+PAUSE reagieren, und
entsprechend ein Kommando senden IIRC.
Mit OpenOCD hat man übrigens die Möglichkeit über ein weiters
Telnet-Terminal den µC anzuhalten. Nur so als Idee.
Das Problem is ja schon gelöst, siehe mein letzter Post.
Der zusätzliche Syscall macht den MIPS Emulator jetzt endlich fast so
langsam wie das Original.
Miin GDB Server hat ja sein eigenes Terminal, da hätt ich das dann auch
mit dem Anhalten implementiert wenns nach Hannes Jaegers Informationen
nicht geklappt hätte.
Wenn beides fertig ist (GDB Server + MIPS Emulator) wirds auch
veröffentlicht.
Läuft zwar beides schon, aber an manchen Stellen muss ich noch anfassen.