Seite 1 von 1

EIP zur Compilierzeit auslesen

Verfasst: Mo Mär 29, 2010 9:32 pm
von Dirty Oerti
Tag zusammen :)

Ich bin auf der Suche nach einer möglichst einfachen Methode, zur Compilierzeit den EIP (also den Instruction Pointer, der auf die jeweilig als nächstes auszuführende Anweisung im Speicher zeigt) an einer bestimmten Stelle innerhalb einer Funktion auszulesen.
Den Wert zur Laufzeit auszulesen ist kein Problem, dieser Wert ändert sich zur Laufzeit aber nicht (die jeweilige Anweisung wandert ja nicht durch den Speicher) und kann also vorher schon ausgelesen werden. Die Frage ist nur wie.
Ich dachte schon an eine Lösung zwecks Labels, womit ich mich aber wenig auskenne (die bösen Labels ;) )
Hier in dem Fall ist ein Label kein Problem, ich springe so oder so wild durch den Code ;)

Um das mal in Code zu setzen:

Code: Alles auswählen

void tu_etwas()
{
int a = 0;
int b = 12345;
LABEL:
a = a + 1;
a = a / b;
}

//...

asm volatile("mov %0, %%ecx" : : "r"(&LABEL);
asm volatile("jmp *%ecx"); // Danach sollte ich oben bei a = a +1; sein.
Ideen?

Re: EIP zur Compilierzeit auslesen

Verfasst: Mo Mär 29, 2010 10:05 pm
von Dirty Oerti
Ok, für den GCC gibt es da etwas, ich würde es aber doch ganz gerne unabhängig vom verwendeten Compiler umsetzen.

http://en.wikipedia.org/wiki/C_syntax#S ... of_a_label
http://forum.chip.de/c-c/adresse-label-344602.html

Re: EIP zur Compilierzeit auslesen

Verfasst: Mo Mär 29, 2010 10:14 pm
von Kerli
Ich bin mir da jetzt nicht ganz sicher, aber ich bilde mir ein wo gelesen zu haben, dass es nur Compilerabhängig möglich ist...

Re: EIP zur Compilierzeit auslesen

Verfasst: Mo Mär 29, 2010 10:32 pm
von Dirty Oerti
Hm, das ist aber nervig.
Es ist ja auch möglich, die Adresse einer Funktion zu erhalten...

Re: EIP zur Compilierzeit auslesen

Verfasst: Mo Mär 29, 2010 10:52 pm
von Xin
Dirty Oerti hat geschrieben:Tag zusammen :)

Ich bin auf der Suche nach einer möglichst einfachen Methode, zur Compilierzeit den EIP (also den Instruction Pointer, der auf die jeweilig als nächstes auszuführende Anweisung im Speicher zeigt) an einer bestimmten Stelle innerhalb einer Funktion auszulesen.
In einem älteren System würde ich sagen, dass das nicht möglich ist, weil Du nicht weißt, wohin das Programm geladen wird.
Bei einem modernen System hast Du Deinen eigenen virtuellen Speicher. Das würde die Sache wieder realisierbar machen - aber dafür müsste der Compiler wissen, wie das OS Dich lädt. Du kannst daher eigentlich immer nur Sprünge relativ zur aktuellen Adresse machen.

Re: EIP zur Compilierzeit auslesen

Verfasst: Di Mär 30, 2010 10:18 am
von Dirty Oerti
Der Compiler weiß, wie das Programm geladen wird. Besser gesagt wohin in den virtuellen Speicher.
Zumindest solange es sich nicht um eine relocable Elfdatei handelt.

Und ich hab jetzt auch eine Lösung gefunden, die zwar nicht unbedingt umwerfend elegant ist, aber sie funktioniert:

Code: Alles auswählen

void meine_funktion()
{
// code
asm volatile("meine_unterbrechung:");
a = a + 1;
}


unsigned int GetUnterbrechung()
{
unsigned int eip;
asm volatile("mov $meine_unterbrechung, %0" : "=r"(eip));
return eip;
}


// in irgendeiner anderen Funktion, wo dieser Wert gebraucht wird
unsigned int eip_aus_funktion = GetUnterbrechung();

Der Rückgabewert der Funktion GetUnterbrechung bleibt immer gleich, zumindest solange das Programm immer an die selbe Stelle im Speicher gelinkt wird.
Die Funktion an sich ist notwendig, damit man den eip auch aus anderen Dateien auslesen kann.
Mir ist nämlich leider noch keine Möglichkeit aufgefallen, das LABEL meine_unterbrechung als global zu deklarieren.

Re: EIP zur Compilierzeit auslesen

Verfasst: Di Mär 30, 2010 11:33 am
von cloidnerux
Als anmerkung zu deinem Code:
1 Zeile C-Code sind nicht 1 Zeile Maschinencode.
Der Fuktionaufruf und das return sind mitunter mehrere MAschinenanweisungen, sodass dann a nicht auf die Stelle die du Herausfinden willst zeigt, sondern noch innerhalb deiner GetUnterbechung ist.

Re: EIP zur Compilierzeit auslesen

Verfasst: Di Mär 30, 2010 12:56 pm
von Dirty Oerti
Nö nö, da verstehst du jetzt was falsch :)
Der zurückgegebene Wert zeigt NIE auf eine Anweisung innerhalb der Get* Funktion.
Die Get Funktion tut nur das, was der Name auch schon sagt: Sie übergibt den Wert.
Der Wert wird ja zur Compilier/Linkzeit schon berechnet und da direkt eingesetzt, die Funktion sieht letztendlich also so aus wie

Code: Alles auswählen

unsigned int GetUnterbrechung()
{
unsigned int eip;
eip = 5;
return eip;
}
Nur eben mit angepasstem Wert.


Das 1 Zeile C Code nicht gleich 1 Zeile Assemblercode ist, ist klar.
Das definierte Label zeigt aber auf die nächste Anweisung. Und das ist die erste Anweisung von egal wie vielen Anweisungen, die aus der 1 Zeile C-Code "entstanden" sind.
Die einzigen Probleme, die hier entstehen (können und auch werden, wenn man das ernsthaft zu Sprüngen verwendet) sind Probleme mit dem Stack, da dieser dann evtl nicht gut aufgelöst wird.