x86_64: Erzwingt, dass gcc Argumente auf dem Stack übergibt

8

Ich arbeite an einer setjmp / longjmp benutzerdefinierten Implementierung für x86-64-Systeme, die den gesamten Kontext der CPU speichert (nämlich alle xmm, fpu stack, etc; nicht nur Callee-save-Register). Dies wird direkt in Assembly geschrieben.

Der Code funktioniert in minimalen Beispielen (wenn er direkt von einer Assembly-Quelle aufgerufen wird). Das Problem tritt auf, wenn es mit C-Code verwendet wird, da die Parameter an die Funktionen homebrew setjmp / longjmp übergeben werden. Tatsächlich schreibt SysV ABI für x64_64-Systeme vor, dass Argumente über Register weitergegeben werden sollten (wenn sie höchstens 6 sind). Die Signatur meiner Funktionen sind:

long long set_jmp(exec_context_t *env);
__attribute__ ((__noreturn__)) void long_jmp(exec_context_t *env, long long val);

Natürlich kann das nicht so funktionieren, wie es ist. In der Tat, wenn ich set_jmp eingeben, wurden rdi und rsi bereits geplottert, um einen Zeiger auf env und val zu behalten. Gleiches gilt für long_jmp in rdi .

Gibt es eine Möglichkeit, GCC zu erzwingen, z.B. indem man sich auf irgendein Attribut verlässt, um das Argument zu zwingen, über den Stapel zu gehen? Dies wäre viel eleganter als das Wrapping von set_jmp und long_jmp mit einigen define, die die gestopften Register manuell auf den Stack schieben, um sie später wieder zu finden.

    
ilpelle 11.12.2015, 15:31
quelle

1 Antwort

2

Sie können das Überschreiben der Register vermeiden, indem Sie die Funktion mit Inline-Assembly aufrufen.

%Vor%

Hier wird eine Ganzzahl auf den Stack geschoben und die Funktion foo aufgerufen. foo stellt den Wert in seiner lokalen Variablen i zur Verfügung. Nach der Rückkehr wird der Stapelzeiger auf seinen ursprünglichen Wert zurückgesetzt.

    
dancancode 30.01.2016 21:04
quelle