Aktuellen Context der CPU auslesen



  • Hi Leute,

    Ich bin gerade dabei im Rahmen des 5.Semesters meines Informatikstudiums eine Klasse für minimale Debugzwecke zu programmieren.
    Der Aufbau ist derzeit so, dass ich keinen anderen Process öffne und dessen Thread/s debugge sondern einfach den aktuell laufenden vom Programm selbst.

    Im ersten war ich nun dabei mal den aktuellen CONTEXT auszulesen und bin dabei auf gewisse Probleme bzw vl auch eher ein Verständnissproblem gekommen.

    Ich nutzer dafür derzeit die Funktion RtlCaptureContext bzw hab es auch mit inline asm getestet.

    CONTEXT ctxx;
    	::ZeroMemory(&ctxx,sizeof(ctxx));
    	ctxx.ContextFlags = CONTEXT_FULL;
    	::RtlCaptureContext(&ctxx);
    
            /*__asm {
    		mov [ctxx.Eax], eax;	
    	}*/
    

    Ich verwende absichtlich nicht die Funktion GetThreadContext() aufgrund diesem Zitat aus MSDN Seite

    If you call GetThreadContext for the current thread, the function returns successfully; however, the context returned is not valid.

    Was ich jedoch bei der Funktion RtlCaptureContext vermisse ist die Übergabe eines HANDLE´s zu einem Thread. Daher nahm ich an die Funktion ist nur für den derzeit aktiven gedacht?

    Jz zu meinem Problem bzw Frage:
    Wann genau muss ich die Register abfragen ausgeben? Schließlich ändern sich diese ja ständig und die Ausgabe meiner Register stimmen beispielsweise nicht mit denen des VS Debuggers zu dem Zustand der Ausgabe aus, da beispielsweise bei der Ausgabe (aufruf von std::cout) wieder einige Funktionen aufgerufen werden und die werte sich wieder ändern.

    Hoffe es ist verständlich was meine Frage ist.
    Danke im Vorhinein



  • bis auf EIP/RIP und ESP/RSP, kann der Kontext, zumindest unmittelbar nach entsprechender inline- Routine, aktuell sein (GPRs,FPU/MMX,XMM,EFLAG,...).
    Du musst außerdem beachten, dass du im ring3 nicht den vollständigen Kontext erfassen kannst, da es z.B. nicht möglich ist die Debuggregister zu lesen.



  • Wie stellst Du Dir das vor, den eigenen Prozess zu debuggen???



  • Nun ich will den Prozess nicht wirklich debuggen (was ja in dem Sinne auch nicht möglich ist) sondern nur einen Crashdump erstellen in weitestem Sinne. Derzeit bin ich aber noch bei den Grundlagen und dabei habe ich mich erstmal mit dem Context beschäftigt.
    Nachdem mein nächstes Ziel die Möglichkeit der Ausgabe des bisherigen Callstacks
    ist benötige ich den aktuellen Context so und so.
    Und nachdem ich gestern dein wirklich tolles Tutorial Walking the Stack gelesen habe erlaube ich es mir dir gleich noch 2 Fragen zu diesem Thema zu stellen 😛

    Was genau macht die Funktion StackWalk64() eigentlich under the hood? Die Doku ist für eine so mächtige Funktion doch etwas begrenzt und da ich selbst noch ein Anfänger in dieser Materie bin kommen mir da ein paar Verständnissprobleme auf.
    Die Funktion liefert mir ein Stackframe zurück. Bekomm ich dann automatisch das nächste wenn ich die Funktion nochmal aufrufe?
    Und macht es irgendeinen Unterschied von wo ich meine Funktionen aufrufe (zb einfach im main oder aus einer Klasse oder aus einer exportierten Funktion einer DLL)? Intern müssen ja irgendwie alle bisherigen Funktionsaufrufe mitgespeichert werden damit ich diese dann zu einem bestimmten Zeitpunkt ausgeben kann.
    Ich wäre wirklich wirklich begeistert wenn womöglich jemand ein Disassembly der Funktion erläutern könnte wo man die Schritte auch genau nachvollziehen kann



  • Mein StackWalker hast Du Dir aber schon angeschaut, oder? Hilft Dir zwar nicht für die Tiefen, aber zumindest für den Anfang... gerade mit dem Context...

    http://stackwalker.codeplex.com/
    😉



  • Das hab ich mir bereits angesehen soweit 🙂
    Wirklich toll gemacht und auch für mich als Anfänger großteils nachvollziebar. Hat es einen Grund das du viele Funktionen per Functionpointer definierst?

    Mir sind nun mittlerweile ein paar Dinge selbst klar geworden, die ich scheinbar falsch verstanden habe.
    Der Callstack ist ja nur da um Funktionen anzuzeigen die innerhalbe von einander aufgerufen worden sind oder?

    Also der Callstack beim Aufruf von c() aus main

    void a(){
    	d();
    }
    void b() {
    
    	a();
    }
    void c() {
    	b();
    }
    void d() {
    	mydbg->InitStack();
    }
    int main() {
     c();
    }
    

    Sollte mir InitStack() -> d() -> a() -> b() -> c() -> main ..
    ausgeben.

    Wobei dieser Aufruf:

    int main() {
    mydbg->DumpRegister();
    	mydbg->GetPid();
    
    	d();
    }
    

    Nur InitStack und d() ausgibt, da die Funktionen DumpRegister() und GetPid() außerhalb aufgerufen werden.

    Sofern ich das richtig sehe kann ich den Punkt erstmal abhaken.



  • Da es verschiedene Version der dbghelp.dll gibt, hab ich das alles per GetProcAddress gemacht... auch kann ich so bestimen, *welche* DLL ich genau lade... (also aus welchem Verzeichnis)


Log in to reply