Forum: Mikrocontroller und Digitale Elektronik [Cortex-M4] Breakpoint auf svc-Anweisung


von Christian G. (christian_g83)


Lesenswert?

Hallo, zusammen!

Gestern Abend hat mich ein kleines Problem auf meinem STM32F4 fast in 
den Wahnsinn getrieben: nach dem Auslösen eines Supervisor-Calls mittels 
"svc 0" ermittelte der SVC-Handler stets die SVC-Nummer 0xbe -- anstatt 
der erwarteten 0. (Zur Ermittlung dieser Nummer wird die Stelle im Code 
ausgelesen, an der sich das Argument der betreffenden svc-Instruktion 
befindet -- in diesem Fall eben die 0.)

Während der Memory-Dump der betreffenden Stelle mir den erwarteten Wert 
anzeigte, wurde vom Prozessor jedoch stets der Wert 0xbe ausgelesen -- 
der scheinbar aus dem Nichts auftauchte.

Des Rätsels Lösung: ich hatte einen Breakpoint auf die svc-Anweisung 
gesetzt. Dieser hat das Auslesen der betreffenden Code-Stelle 
beeinflusst, so dass die falsche SVC-Nummer ermittelt wurde.

Bleibt nur die Frage, warum der Memory-Dump davon nicht betroffen war. 
Hat jemand eine Ahnung, weshalb?

Christian

von Karl H. (kbuchegg)


Lesenswert?

Christian Gudrian schrieb:

> Bleibt nur die Frage, warum der Memory-Dump davon nicht betroffen war.
> Hat jemand eine Ahnung, weshalb?

Was denkst du, wie der Debugger Breakpoints realisiert?

von Christian G. (christian_g83)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Was denkst du, wie der Debugger Breakpoints realisiert?

Indem er zur Laufzeit den Code modifiziert?

Christian

von Karl H. (kbuchegg)


Lesenswert?

Christian Gudrian schrieb:
> Karl Heinz Buchegger schrieb:
>
>> Was denkst du, wie der Debugger Breakpoints realisiert?
>
> Indem er zur Laufzeit den Code modifiziert?

Genau!

Er nimmt die Instruktion raus und ersetzt sie durch Code, der im Prinzip 
einen Jump in den Debugger macht, damit er wieder die Kontrolle kriegt, 
wenn der Code an diese Stelle aufläuft.

von Christian G. (christian_g83)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Er nimmt die Instruktion raus und ersetzt sie durch Code, der im Prinzip
> einen Jump in den Debugger macht, damit er wieder die Kontrolle kriegt,
> wenn der Code an diese Stelle aufläuft.

Und genau deshalb habe ich mich gefragt, warum diese Änderung im 
Memory-Dump nicht zu sehen war. Da waren weiterhin die Opcodes für ein 
"svc 0" zu sehen -- sonst hätte ich nicht so lange gebraucht, um das zu 
bemerken.

Aber da das Anfertigen eines Memory-Dumps ja auch der Mithilfe des 
Debuggers bedarf, wird dieser vermutlich seine am Code gemachten 
Änderungen vor den geneigten Augen des Debuggenden verbergen und diesem 
so das Leben unnötig schwer machen.

Also merke: keine Breakpoints auf svc-Anweisungen.

Christian

von Karl H. (kbuchegg)


Lesenswert?

Christian Gudrian schrieb:
> Karl Heinz Buchegger schrieb:
>
>> Er nimmt die Instruktion raus und ersetzt sie durch Code, der im Prinzip
>> einen Jump in den Debugger macht, damit er wieder die Kontrolle kriegt,
>> wenn der Code an diese Stelle aufläuft.
>
> Und genau deshalb habe ich mich gefragt, warum diese Änderung im
> Memory-Dump nicht zu sehen war.

So dämlich sind die Programmierer des Debuggers nun auch wieder nicht.
Als Programmierer sollst du ja nicht sehen, dass der Code hier 
modifiziert wurde. Du sollst dich auf DEINEN Code konzentrieren und 
nicht auf die Magie, die der Debugger dahinter abziehen muss.

> Aber da das Anfertigen eines Memory-Dumps ja auch der Mithilfe des
> Debuggers bedarf, wird dieser vermutlich seine am Code gemachten
> Änderungen vor den geneigten Augen des Debuggenden verbergen und diesem
> so das Leben unnötig schwer machen.

Nicht unnötig schwer.
Du bist auf einen Sonderfall gelaufen, an den die Programmierer des 
Debuggers nicht gedacht haben. Könnte man so gesehen als Bug bezeichnen. 
Alle Instruktionen, die weitere Erkentnisse aus dem Code selbst 
nachladen, muss der Debugger mit der heißen Kneifzange anfassen.

von Christian G. (christian_g83)


Lesenswert?

Karl Heinz Buchegger schrieb:

> So dämlich sind die Programmierer des Debuggers nun auch wieder nicht.

Die Dämlichkeit habe ich ehrlich gesagt eher bei mir gesucht.

> Du bist auf einen Sonderfall gelaufen, an den die Programmierer des
> Debuggers nicht gedacht haben. Könnte man so gesehen als Bug bezeichnen.

Weiß nicht. Wie sollte man da anders vorgehen? Soweit möglich 
Hardware-Breakpoints verwenden?

Wie läuft es denn nach einer Unterbrechung normalerweise weiter? Die 
Instruktion, die durch die Injektion des Breakpoints entfernt wurde, 
muss ja irgendwann ausgeführt werden. Das wird aber vermutlich am 
eigentlich Code vorbei geschehen, da der Breakpoint ja im Code 
verbleibt.

> Alle Instruktionen, die weitere Erkentnisse aus dem Code selbst
> nachladen, muss der Debugger mit der heißen Kneifzange anfassen.

Die Messung beeinflusst das Experiment. Klassischer Heisenbug.

Ein konservativer Debugger sollte sich also weigern, einen Breakpoint 
auf eine svc-Anweisung zu setzen?

Christian

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

Christian Gudrian schrieb:
> Weiß nicht. Wie sollte man da anders vorgehen? Soweit möglich
> Hardware-Breakpoints verwenden?

Wieviele BPs hast Du denn aktiviert? Ein vernünftiger Debugger sollte
doch sowieso zunächst die Hardware BPs des Prozessors verwenden.

> Ein konservativer Debugger sollte sich also weigern, einen
> Breakpoint auf eine svc-Anweisung zu setzen?

Alternativ könnte man den Parameter der SVC Instruktion auch
ignorieren und die SVC Nummer in einem normalen Register übergeben.
Das spart einem diesen hässlichen Teil der Auswertung. Geht natürlich
nur, wenn man Kontrolle über den Code hat.

--
Marcus

von Christian G. (christian_g83)


Lesenswert?

Marcus Harnisch schrieb:

> Wieviele BPs hast Du denn aktiviert?

Das war der einzige.

> Ein vernünftiger Debugger sollte
> doch sowieso zunächst die Hardware BPs des Prozessors verwenden.

Eclipse mit ARM-Plug-in. Eigentlich ganz brauchbar.

> Alternativ könnte man den Parameter der SVC Instruktion auch
> ignorieren und die SVC Nummer in einem normalen Register übergeben.

Das macht doch keinen Spaß. :)

> Das spart einem diesen hässlichen Teil der Auswertung. Geht natürlich
> nur, wenn man Kontrolle über den Code hat.

Die Auswertung ist in der Tat hässlich. Trotzdem muss man da mal durch, 
wenn man den Cortex kennenlernen will.

Christian

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

Christian Gudrian schrieb:
>> Das spart einem diesen hässlichen Teil der Auswertung. Geht natürlich
>> nur, wenn man Kontrolle über den Code hat.
>
> Die Auswertung ist in der Tat hässlich. Trotzdem muss man da mal durch,
> wenn man den Cortex kennenlernen will.

Das sage ich den Kursteilnehmern auch immer. Und dann rate ich ihnen, 
dass ganz schnell wieder zu vergessen. Die Auswertung des Parameters ist 
der einzige Grund warum der SVC Handler (oder Teile desselben) in 
Assembler implementiert werden muss.

Gruß
Marcus

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.