In einem Versuch, ein Betriebssystem zu schreiben, muss ich die Adresse der aktuellen Funktion Ende (direkt vor Epilog) für Task-Wechsel.
Konkret ist mein Problem, eine EIP zu bekommen, um meine neu erstellte Aufgabe (Prozess) innerhalb des kopierten Stapels zuweisen. Ich habe es bereits geschafft, Register für einen Prozess zu speichern/wiederherzustellen, aber ich muss herausfinden, welchen Wert der Kindprozess in seinem EIP haben wird.GCC - Etikett Adresse zurück aktuelle EIP anstelle von realen Etikett Adresse
verwenden ich GCC-Erweiterungen C-Standard: Labels as Values und Local Labels
Aus der Dokumentation: Sie die Adresse eines in der aktuellen Funktion (oder eine enthaltende Funktion) mit dem unären Operator ‚& &‘ definierte Label erhalten. Der Wert hat den Typ void *.
und: GCC ermöglicht es Ihnen, lokale Beschriftungen in jedem verschachtelten Blockbereich zu deklarieren. Ein lokales Label ist wie ein gewöhnliches Label, aber Sie können es nur (mit einer goto-Anweisung oder indem Sie seine Adresse angeben) innerhalb des Blocks, in dem es deklariert ist, referenzieren.
pid_t fork(void)
{
__label__ fork_end;
...
task->regs.eip = (uintptr_t)&&fork_end;
...
return task->pid;
fork_end:;
}
GCC tut es kompilieren, mit nur Warnungen über Nicht-Standard-Code.
Wenn jedoch zerlegt, gdb zeigt:
task->regs.eip = (uintptr_t)&&fork_end;
0x00105008 <+87>: mov $0x105008,%edx
0x0010500d <+92>: mov -0xc(%ebp),%eax
0x00105010 <+95>: mov %edx,0x40(%eax)
...
fork_end:;
}
0x00105096 <+229>: leave
0x00105097 <+230>: ret
ich task->regs.eip = (uintptr_t)&&fork_endl
erwarten 0x00105096
statt 0x00105008
zu speichern.
CFLAGS
sind -O0 -std=gnu99 -fgnu89-inline -DDEBUG -ggdb3 -ffreestanding -fbuiltin
(Warnungen Optionen hier nicht gezeigt).
Kommentieren __label__ fork_end;
ändert nichts.
Bitte geben Sie einen Verweis auf die GCC-Dokumentation über '&&' und geben Sie an, was es in Ihrem Verständnis tut. Es warnt nicht, wenn Erweiterungen verwendet werden. Siehe [fragen] und geben Sie alle erforderlichen Informationen an. – Olaf
Bearbeitet und @Olaf, gcc warnt vor nicht standardmäßigen Code mit der Option "-Wpedantic". Danke für Ihre Ratschläge. – Aerath
Aha, ich verstehe. Die Verwendung von "Wpedantic" mit Erweiterungen klingt nach einer schlechten Idee. Wie auch immer, Ihr Cast ist eine Implementierung definiert und ein "uint32_t" ist nicht erforderlich, um einen Zeiger zu halten, noch gibt es eine 1: 1 Zuweisung. Auf einem 64-Bit-System sind Sie bereits kaputt. Verwenden Sie mindestens die richtigen Typen. Gibt es einen Grund, warum Sie nicht 'void *' als Zeiger, sondern als Integer verwenden? – Olaf