Forum: Compiler & IDEs Zugriff auf SP *vor* Funktionsaufruf


von The H. (helge_k)


Lesenswert?

Ich möchte in einem Exception-Handler auf die Exception-Information, die 
auf dem Stack liegt zugreifen. Dazu habe ich ein Makro geschrieben, das 
die Informationen in eine Variable auf File-Scope kopiert. Dieses Makro 
wird in jedem Exception-Handler als erste Anweisung verwendet.

Bei der Implementierung habe ich eine lokale Variable TopOfStack 
angelegt und diese als Referenzadresse benutzt:
1
#define SaveExceptionInfo \
2
  int TopOfSTack; \
3
  ExceptionInfo.ReturnAddress = (&TopOfStack)[9]; \
etc.

Je nach Optierungslevel des GCC ist aber der Abstand zwischen der 
Exception-Information und der Variablen unterschiedlich. Beim Eintritt 
in die Funktion können je nach Level 8 oder 16 Bytes als Offset dazu 
kommen. Wie kann ich innerhalb des Makros unabhängig vom 
Optimierungslevel sicher auf die Adresse der Exception-Information 
zugreifen?

Die Optimierung könnte lokal für Funktionen mittels pragma spezifiziert 
werden. Aber dieses muss vor der Funktion erfolgen, während das Makro 
natürlich innerhalb der Funktion verwendet werden muss. Dadurch lässt 
sich das pragma nicht anwenden.

von (prx) A. K. (prx)


Lesenswert?

__builtin_frame_address könnte helfen:
http://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Return-Address.html

von The H. (helge_k)


Lesenswert?

Leider hilft das nicht wirklich. Die Frameadresse ist der Wert des SP 
Registers nachdem alle Register gesichert und Platz für die lokalen 
Variablen gemacht wurde.

__builtin_return_address geht übrigens auch nicht. Diese Funktion 
liefert den Wert des LR Registers des ARM Cortex-M3.

von The H. (helge_k)


Lesenswert?

Es ist nicht möglich innerhalb einer normalen C-Funktion den 
Stackpointer bei Eintritt in die Funktion zu bekommen. Je nach 
Optimierungslevel setzt der GCC den Stackpointer vor der ersten 
Instruktion um einen größeren oder kleineren Wert um.

Abhilfe schafft hier nur das _nakded attribute. Damit kann man eine 
Funktion definieren, in der der effektiv nur Inline-Assembly möglich 
ist. In de Inline-Assembly kann man sich den Stackpointer beschaffen und 
dann eine passende C-Funktion mit normalen Stackfame aufrufen. Details 
gibt es hier:

http://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html

von Bronco (Gast)


Lesenswert?

Ich hatte mal ein ähnliches Problem mit dem Sleep-Mode des MSP430.
Der Sleep-Zustand ist dort im Condition-Register gespeichert, welches 
beim Aufruf einer weckenden ISR auf den Stack geschrieben wird. Um den 
MSP430 nach der ISR wach zu halten, mußte man das Sleep-Flag auf dem 
Stack verändern.

Ich hatte es so gelöst:
Anstatt der eigentlichen C-Funktion wird eine Assembler-Funktion 
aufgerufen. Diese hat immer ein fixes Stack-Verhalten (d.h. die Anzahl 
von auf-den-Stack-gesicherten-Daten ist immer gleich).
Zu Beginn der Assembler-Funktion hab ich mir die aktuelle Adresse im 
Stackpointer gemerkt.
Dann hab ich die C-Funktion aufgerufen.
Die C-Funktion return-te in die Assembler-Funktion und nun konnte ich 
mit der zuvor gemerkten Stackadresse das Condition-Register 
manipulieren.
Hat perfekt funktioniert!

Später wurde dieser Umweg überflüssig, weil eine neuere Version des 
IAR-Compilers eine spezielle Instrinsic-Funktion für genau diese 
Anwendung zur Verfügung gestellt hat.

von The H. (helge_k)


Lesenswert?

Ja, letztendlich muss man es mit Assembler machen. Eine Möglichkeit 
hatte ich im letzten Post adressiert.

Wenn man den GCC durch den eines anderen Herstellers ersetzt, ergeben 
sich natürlich völlig neue Mögllichkeiten.

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.