2014-04-17 10 views
9

Ich habe versucht, durch die Call-Stack-Frames zu gehen und einige Informationen daraus zu extrahieren. Ich bin in der Lage, die Dateinamen, Zeilennummern und Funktionsnamen zu extrahieren, indem Sie StackWalk64, SymGetSymFromAddr64 und SymGetLineFromAddr64 APIs von WinDBG verwenden.Wie liest man die Funktionsparameter aus Call-Stack-Frames programmgesteuert in Windows?

Die DWORD64 Params[4] in STACKFRAME64, die ein Rückgabewert von StackWalk64 ist, unterstützt nur das Zurücklesen vier 64-Bit-Funktionsparameter aus einem Rahmen. Schlimmer noch, bei einem 32-Bit-System werden nur die unteren 32 Bits von Params[4] verwendet, so dass ein einzelner Parameter mit mehr als 32 Bits zwei oder mehr Elemente benötigt.

typedef struct _tagSTACKFRAME64 { 
    ADDRESS64 AddrPC; 
    ADDRESS64 AddrReturn; 
    ADDRESS64 AddrFrame; 
    ADDRESS64 AddrStack; 
    ADDRESS64 AddrBStore; 
    PVOID  FuncTableEntry; 
    DWORD64 Params[4]; 
    BOOL  Far; 
    BOOL  Virtual; 
    DWORD64 Reserved[3]; 
    KDHELP64 KdHelp; 
} STACKFRAME64, *LPSTACKFRAME64; 

Ich konnte keinen API finden Sie alle Parameter aus einem Stapelrahmen ohne Einschränkung zu lesen.

Ich dachte daran, ebp/rbp zu verwenden, um die Werte aus dem Stapel (x86/x64) und den Registern (x64) zu extrahieren. Aber trotzdem können nur die "möglichen" Werte der Parameter erhalten werden, wenn ich dies tue.

Gibt es irgendeine API, die ich verwenden könnte, um die genauen Werte zu erhalten? Es wäre noch besser, wenn ich den Typ und den Namen der Parameter bekommen könnte.

+0

Warum der Downvote? Dies scheint eine vernünftige Frage zu sein. –

+8

Sie können keine genauen Werte erhalten, da der Compiler seine Parameterverwendung so optimieren kann, dass die ursprünglichen Parameter nicht mehr auf dem Stack gespeichert werden. (Zum Beispiel werden bei x64 Parameter in Registern übergeben und werden möglicherweise niemals tatsächlich in den Stapel geschrieben.) Die Werte, die Sie von STACKFRAME64 erhalten, sind die besten. –

+0

@RaymondChen: Richtig, aber ich kann mir keinen Grund vorstellen, warum solch eine API nicht existieren könnte. Eine Variante von 'SymGetSymFromAddr64', bei der man statt eines Zeigers einen Stackframe und einen Parameterindex angeben würde. –

Antwort

1

Es gibt keine API dafür. Warum sollte es welche geben, moderne Betriebssysteme sind nicht daran interessiert, dass einige Leute mit diesem Zeug spielen. Wie bereits erwähnt, kann der Compiler Optimierungen vornehmen, so dass Sie kein deterministisches Werkzeug dafür haben können. Aber es gibt Heuristiken! Sie können wissen, wie viele Parameter in Funktion sind, wenn Sie Assembly vor dem Aufruf oder ret nach dem Aufruf analysieren, Sie haben immer eine Absenderadresse, die Sie überprüfen können, ob sie in CS ist.

Vor allem - sollten Sie über den Begriff 'Stack Abwickeln' lesen.

+0

Fast - Abwicklungs-Tabellen sind heutzutage aufgrund der EH-Anforderungen eine Sache, und diese werden Parameterdaten benötigen, so dass sie pass-by-value-Parameter von nicht-trivialem Typ abwickeln können. – LThode