Forum: Compiler & IDEs GDB Remote Protokoll MIPS


von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Hallo,
Programmiere grade einen MIPS Emulator damit das Projekt hier auch mal 
von Zuhause weiterlaufen kann:
http://www.fritzler-avr.de/spaceage2/
Das Gerät spricht zwar den MIPS1 Befehlsatz aber unter der Haube ist es 
dann doch anders, zB anderes Exceptionhandling.

Der Emulator läuft, jetzt soll er mit dem GDB reden können.
Das geht auch gut bis der GDB die Register abfragt:
"warning: Invalid remote reply: 5"
Und der GDB hängt sich komplett auf.
Die Register sende ich in der Reihenfolge wie es hier steht:
https://sourceware.org/gdb/onlinedocs/gdb/MIPS-Register-packet-Format.html#MIPS-Register-packet-Format
Also:
"All registers are transferred as thirty-two bit quantities in the 
order: 32 general-purpose; sr; lo; hi; bad; cause; pc; 32 floating-point 
registers; fsr; fir; fp."

Als wüsste er nicht welche Register kommen und eine xml Config kann ich 
dem GDB nicht geben, da er behaptet, dass der XML Parser zur Compilezeit 
nicht dabei war, aber bei configure habe ich ihm "--with-libexpat" 
mitgegeben.
Eigentlich sollte der GDB sich die config vom GDb Server holen, aber 
solch ein Befehl wird vor dem Register lesen nicht gesendet vom GDB.
HÄ?

Also wie bekomm ich jetzt den Registerlesebefehl so gebaut, dass der GDB 
das frisst?

Hier noch die Kommunikation:
alloziere MIPS CPU Speicher
fülle MIPS CPU Speicher (256532 bytes)
GDB: warte auf eingehende Verbindung vom GDB Client auf 0.0.0.0:2842
GDB: eingehende Verbindung von: 127.0.0.1:4510

(GDB ->) 
$qSupported:multiprocess+;swbreak+;hwbreak+;qRelocInsn+;fork-events+;vfo 
rk-events+;exec-events+;vContSupported+;QThreadEvents+;no-resumed+#df
(GDB <-) +
GDB command: qSupported
(GDB <-) $PacketSize=4076#01

(GDB ->) $vMustReplyEmpty#3a
(GDB <-) +
GDB command: vMustReplyEmpty
(GDB <-) $#00

(GDB ->) $Hg0#df
(GDB <-) +
GDB command: Hg0
(GDB <-) $OK#9a

(GDB ->) $qTStatus#49
(GDB <-) +
GDB command: qTStatus
(GDB <-) $#00

(GDB ->) $?#3f
(GDB <-) +
GDB command: ?
(GDB <-) $5#35

(GDB ->) $qfThreadInfo#bb
(GDB <-) +
GDB command: qfThreadInfo
(GDB <-) $m 0#bd

(GDB ->) $qsThreadInfo#c8
(GDB <-) +
GDB command: qsThreadInfo
(GDB <-) $l#6c

(GDB ->) $Hc-1#09
(GDB <-) +
GDB command: Hc-1
(GDB <-) $OK#9a

(GDB ->) $qC#b4
(GDB <-) +
GDB command: qC
(GDB <-) $#00

(GDB ->) $qAttached#8f
(GDB <-) +
GDB command: qAttached
(GDB <-) $0#30

(GDB ->) $qOffsets#4b
(GDB <-) +
GDB command: qOffsets
(GDB <-) $Text=0;Data=0;Bss=0;#3f

(GDB ->) $Hg0#df
(GDB <-) +
GDB command: Hg0
(GDB <-) $OK#9a

(GDB ->) $g#67
(GDB <-) +
GDB command: g
(GDB <-) 
$00000000000000000000000000000000000000000000000000000000000000000000000 
000000000000000000000000000000000000000000000000000000000000000000000000 
000000000000000000000000000000000000000000000000000000000000000000000000 
000000000000000000000000000000000000000000000000000000000000000000000000 
000000000000000000000000000000000000000000000000000000000000000000000000 
000000000000000000000000000000000000000000000000000000000000000000000000 
000000000000000000000000000000000000000000000000000000000000000000000000 
000000000000000000000000000000000000000000000000000000000000000000000000 
000000000#80

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Mw E. schrieb:

> Als wüsste er nicht welche Register kommen und eine xml Config kann ich
> dem GDB nicht geben, da er behaptet, dass der XML Parser zur Compilezeit
> nicht dabei war, aber bei configure habe ich ihm "--with-libexpat"
> mitgegeben.

Du musst auch die libexpat (mitsamt Headern) daliegen haben, damit
er das wirklich nimmt.

Hilft dir aber (wie du schon bemerkt hast) für die Register nicht
weiter.  Ist nur nützlich, um die Speicherkonfiguration vom Target
rüberzureichen (Flash, RAM).

Prinzipiell denke ich, dass dein Prinzip richtig ist, aber schau doch
einfach mal im GDB selbst nach, was er bei MIPS für die Register
erwartet.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Hallo,
der Fehler war dann doch einfacher als Gedacht und lag nicht am Register 
auslesen.
Die Reihenfolge im Link ist zudem korrekt.

Die Verwirrung kam, weil der Fehler vom GDB erst nach dem Register 
einlesen ausgegeben wurde.

Der Fehler war aber hier:
(GDB ->) $?#3f
(GDB <-) +
GDB command: ?
(GDB <-) $5#35

Die Antwort muss $S05# lauten.
Dann ist der GDB glücklich und ich kann Register/RAM lesen/schreiben.
Mehr hab ich bisher auch noch nicht implementiert.

Aber es gibt ein neues Problem.

Mit "info Register" kann ich mir die Register ansehen
und mit set $s0 = 4000 Register setzen.

Zum setzen nimmt er den P Befehl, also P1d=wert (Beispielhaft).
Danach ließt der GDB mit g wieder alle Register aus.

Nach einer Weile rumspielen (Register setzen und lesen) fängt der GDB an 
den M Befehl zum Register setzen zu nutzen, das ist natürlich falsch.
Zum Auslesen der Register nutzt er dann auch auf einmal den m Befehl.
Dann steht bei info register natürlich nur Müll, weil er Speicher 
ausließt.

Muss das heute Abend mal nochmal nachstellen.
Dann gibts mehr Infos.

Villeicht weis da aber wer jetzt schon genaueres?
GDB 7.12 nutze ich für mips-elf

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Also das Verhalten, mit dem Registerfail, konnte ich bisher nicht 
reproduzieren.

Kleiner Rant am Rande zu Memory Breakpoints:
Bei einem Memory Breakpoint überschreibt man den Befehl mit etwas was 
die CPU zu einer Exception veranlasst, wenn diese dort vorbeikommt.
GDB ließt den Befehl aus und sagt mir dann ich soll da doch nen 
Membreakpoint hinsetzen (Z0)

(GDB ->) $m200,4#5f
(GDB <-) +
(GDB <-) $3c040003#bd

(GDB ->) $Z0,200,4#a8
(GDB <-) +
(GDB <-) $OK#9a

Dann lass ich die CPU laufen und der Breakpoint wird erreicht.
Danach nehme ich den Step Befehl und vorher sagt mir GDB nur per z0, 
dass ich den Breakpoint rausnehmen soll.
Sagt mir aber nicht wie das word vorher dort Aussah, darum soll ich mich 
also selber kümmern gnarf

(GDB ->) $z0,200,4#c8
(GDB <-) +
(GDB <-) $OK#9a

(GDB ->) $s#73
(GDB <-) +

Beim Emulator kann ich ja einfach das Binary nochmal aufmachen und 
wieder das Word reinkopieren.
Aber später soll der GDB Server dann auch per USB mit den Hardware 
Debugregistern des TTL MIPS reden.

: Bearbeitet durch User
von Mw E. (Firma: fritzler-avr.de) (fritzler)


Angehängte Dateien:

Lesenswert?

So ziemlich jede GDB GUI mag wohl den MIPS GDB nicht, hab ich 
rausgefunden.
kdbg, ddd usw und auch Code::Blocks.
Es geht alles bis auf Register anzeigen.

Das liegt wohl daran wie der MIPS GDB die Register anzeigt, denn es sind 
immer 32 Register.
Deswegen zeigt er diese in mehreren Zeilen horizontal an.
Andere GDB Versionen (x86/ARM) zeigen die Register vertikal an.
(siehe Bilder im Anhang)

Daher muss ich das wohl im Sourcecode des GDB ändern, nur finde ich die 
Stelle nicht wo dies getan wird.
Hat hier jemand Ahnung vom GDB Sourcecode und kann mir sagen welche 
Datei für MIPS die Register printed beim Befehl "info register"?
Da das intern alles mit Funktionspointern arbeitet um neue Architekturen 
hinzufügen zu können ist das recht unübersichtlich.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Hat da keiner eine Idee in welcher C Datei der GDB die MIPS Register auf 
der Konsole ausspuckt?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Mein "grep -R" meint, dass es in gdb/mips-tdep.c ist,
mips_print_registers_info(), welches in Folge print_gp_register_row()
aufruft.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Dann is mein grep doof, habe nämlich nach print_register gesucht.
Danke schonmal, dann Spiel ich heute Abend damit rum.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Da kram ich mal meinen alten Thread raus, weil ich wieder eine Frage 
habe zum Protokoll.

Momentan baue ich den GDB Server in den Debugger des MIPS TTL ein.
Somit soll nicht mehr nur das Programm im Simulator debuggt werden, 
sondern jetzt auch mal die echte Hardware!

Bisher kann ich Register/Speicher lesen/schreiben.
Somit kann ich jetzt per GDB das programm laden und vergleichen.
Beim Vergleichen kann ja das qCRC genutzt werden.

Das funktioniert auch bei den kleinen Sections, aber bei einer 70kbyte 
.text Section gibts einen Fehler.
Ich vermute, dass dem GDB die Antwort zu lange dauert.
Gibt es irgendein keepalive, dass man zwischendrinn senden kann?

GDB Ausgabe:
1
Loading section reset, size 0x10 lma 0x0
2
Loading section eirq, size 0x8 lma 0x100
3
Loading section ovw, size 0x4 lma 0x120
4
Loading section undef, size 0x4 lma 0x140
5
Loading section sysc, size 0x4 lma 0x160
6
Loading section break, size 0x4 lma 0x180
7
Loading section .text, size 0xfb58 lma 0x200
8
Loading section .rodata, size 0x18e8 lma 0xfd58
9
Loading section .data, size 0x990 lma 0x11640
10
Loading section .sdata, size 0x9c lma 0x11fd0
11
Start address 0x0, load size 73364
12
Transfer rate: 23 KB/sec, 4075 bytes/write.
13
Section reset, range 0x0 -- 0x10: matched.
14
Section eirq, range 0x100 -- 0x108: matched.
15
Section ovw, range 0x120 -- 0x124: matched.
16
Section undef, range 0x140 -- 0x144: matched.
17
Section sysc, range 0x160 -- 0x164: matched.
18
Section break, range 0x180 -- 0x184: matched.
19
Ignoring packet error, continuing...
20
upload.gdbinit:4: Error in sourced command file:
21
Reply contains invalid hex digit 105

Debugausgabe meines GDB Servers:
1
(GDB ->) $X11640,990:@[...]#d8
2
(GDB <-) +
3
GDB command: X11640,990
4
(GDB <-) $OK#9a
5
6
(GDB ->) $X11fd0,9c: [...]#56
7
(GDB <-) +
8
GDB command: X11fd0,9c
9
(GDB <-) $OK#9a
10
11
(GDB ->) $P25=00000000#74
12
(GDB <-) +
13
GDB command: P25=00000000
14
(GDB <-) $OK#9a
15
16
(GDB ->) $m0,4#fd
17
(GDB <-) +
18
GDB command: m0,4
19
(GDB <-) $3c1d0050#f0
20
21
(GDB ->) $qCRC:0,10#40
22
(GDB <-) +
23
GDB command: qCRC
24
gdb_demux_commands_q: CRC
25
addr: 0x00000000
26
len:  16
27
(GDB <-) $C4775b330#12
28
29
(GDB ->) $qCRC:100,8#78
30
(GDB <-) +
31
GDB command: qCRC
32
gdb_demux_commands_q: CRC
33
addr: 0x00000100
34
len:  8
35
(GDB <-) $Cd3038f29#46
36
37
(GDB ->) $qCRC:120,4#76
38
(GDB <-) +
39
GDB command: qCRC
40
gdb_demux_commands_q: CRC
41
addr: 0x00000120
42
len:  4
43
(GDB <-) $Ce61cbe87#a8
44
45
(GDB ->) $qCRC:140,4#78
46
(GDB <-) +
47
GDB command: qCRC
48
gdb_demux_commands_q: CRC
49
addr: 0x00000140
50
len:  4
51
(GDB <-) $Ce61cbe87#a8
52
53
(GDB ->) $qCRC:160,4#7a
54
(GDB <-) +
55
GDB command: qCRC
56
gdb_demux_commands_q: CRC
57
addr: 0x00000160
58
len:  4
59
(GDB <-) $Ce61cbe87#a8
60
61
(GDB ->) $qCRC:180,4#7c
62
(GDB <-) +
63
GDB command: qCRC
64
gdb_demux_commands_q: CRC
65
addr: 0x00000180
66
len:  4
67
(GDB <-) $Ce61cbe87#a8
68
69
(GDB ->) $qCRC:200,fb58#76
70
(GDB <-) +
71
GDB command: qCRC
72
gdb_demux_commands_q: CRC
73
addr: 0x00000200
74
len:  64344
75
(GDB <-) $C66964a55#1d
76
77
(GDB ->) $D#44
78
(GDB <-) +
79
GDB command: D
80
(GDB <-) $OK#9a

Warum auch immer der GDB wegen eines invaliden Zeichens 105 rummeckert 
(das wäre ein 'i').

von Martin S. (strubi)


Lesenswert?

Moin,

den hier schon probiert?
1
set remotetimeout 99999

Wenn das auch nicht geht, liegt's an bloedem Timing, was insbes. bei 
seriellen GDB-backends auftreten kann. Leider ist das GDB-Protokoll 
ziemlich 'broken by design'. Nehme mal an, dass du nicht EJTAG 
implementiert hast..

: Bearbeitet durch Moderator
von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Das hab ich jetzt mal eingebaut, aber es ändert nichts.

Ich warte jetzt einfach noch 5sek zusätzlich bevor ich die Antwort 
schicke.
Das zeitliche Verhalten ist so:
1
(GDB ->) $qCRC:200,fb58#76
2
(GDB <-) +
3
GDB command: qCRC
4
gdb_demux_commands_q: CRC
5
addr: 0x00000200
6
len:  64344
7
---- Berechnungszeit + 5s ----
8
(GDB <-) $C66964a55#1d
9
10
---- GDB wirft die Fehlermeldung ---
11
12
(GDB ->) $D#44
13
(GDB <-) +
14
GDB command: D
15
(GDB <-) $OK#9a

Was nach den Klammern steht kommt über USB CDC rein oder wird darüber 
ausgesendet.
Das ohne Klammern ist Debugtext.

Komplett falsch kanns ja eigentlich nicht sein, sonst hätte der GDB 
schon bei den CRCs davor gemeckert?

Ich muss mal gucken ob ich den GDB dazu bringen kann mir anzuzeigen was 
er empfängt, dann könnt ich sehen ob da vllt doch ein 'i' irgendwie in 
den USB CDC TX Buffer reinfällt.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.