Ich habe ein "gefährliches" Programm in C++ geschrieben, das von einem Stack-Frame zu einem anderen hin und her springt. Das Ziel besteht darin, von der untersten Ebene eines Callstacks zu einem Aufrufer zu springen, etwas zu tun und dann wieder zurückzuspringen, wobei jedes dazwischen liegende Gespräch übersprungen wird.Was macht das PIC-Register (% ebx)?
Ich mache dies, indem ich manuell die Stack-Basisadresse (Einstellung %ebp
) ändere und zu einer Label-Adresse springe. Es funktioniert völlig, mit gcc und icc beide, ohne irgendeine Stapelkorruption überhaupt. Der Tag, an dem das klappte, war ein kühler Tag.
Jetzt nehme ich das gleiche Programm und überschreibe es in C, und es funktioniert nicht. Insbesondere funktioniert es nicht mit gcc v4.0.1 (Mac OS). Sobald ich zu dem neuen Stapelrahmen gesprungen bin (wobei der Stapelbasiszeiger korrekt gesetzt wurde), werden die folgenden Anweisungen ausgeführt, die kurz vor einem Anruf zu fprintf
sind. Der letzte Befehl aufgeführt hier abstürzt, dereferencing NULL:
lea 0x18b8(%ebx), %eax
mov (%eax), %eax
mov (%eax), %eax
Ich habe einige Debug getan, und ich habe herausgefunden, dass durch Einstellen der %ebx
Register manuell, wenn ich Stack-Frames wechseln (Wert unter Verwendung von I beobachtet, bevor er die Funktion an erster Stelle), repariere ich den Fehler. Ich habe gelesen, dass dieses Register sich mit "positionsunabhängigem Code" in gcc beschäftigt.
Was ist positionsunabhängiger Code? Wie funktioniert positionsunabhängiger Code? Worauf zeigt dieses Register?
Sie können setjmp/longjmp in Betracht ziehen, um diese Funktionalität zu erhalten, ohne direkt mit% ebx zu mucken. –
Im Allgemeinen ja, du hast Recht. In diesem Fall muss ich in der Lage sein, zu einem Anrufer zu springen, eine andere Funktion auszuführen und dann zurück zum Angerufenen zu springen. Mit setjmp/longjmp würde der Stapel des Angerufenen von der anderen Funktion überschrieben werden. –