2014-04-17 14 views
9

Stavo cercando di attraversare i frame dello stack delle chiamate ed estrarre alcune informazioni da essi. Sono in grado di estrarre i nomi dei file, i numeri di riga e i nomi delle funzioni utilizzando le API StackWalk64, SymGetSymFromAddr64 e SymGetLineFromAddr64 da WinDBG.Come leggere i parametri della funzione dai telai stack di chiamata a livello di codice in Windows?

Tuttavia, lo DWORD64 Params[4] in STACKFRAME64, che è un valore di ritorno da StackWalk64, supporta solo la lettura di quattro parametri di funzione a 64 bit da un frame. Ancora peggio, nel sistema a 32 bit, vengono utilizzati solo i 32 bit inferiori di Params[4], quindi un singolo parametro con più di 32 bit richiede due o più elementi.

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; 

Non ho trovato alcuna API per leggere TUTTI i parametri da uno stack frame senza limitazioni.

Stavo pensando di utilizzare ebp/rbp per estrarre i valori dallo stack (x86/x64) e dai registri (x64). Ma ancora, solo i valori "possibili" dei parametri possono essere ottenuti se faccio questo.

C'è qualche API che potrei usare per ottenere i valori precisi? Sarebbe ancora meglio se potessi ottenere il tipo e il nome dei parametri.

+0

Perché il downvote? Questa sembra una domanda ragionevole. –

+8

Non è possibile ottenere valori accurati perché il compilatore è libero di ottimizzare l'utilizzo dei parametri in modo tale che i parametri originali non vengano più memorizzati nello stack. (Ad esempio, su x64, i parametri vengono passati nei registri e potrebbero non essere mai effettivamente scritti nello stack.) I valori ottenuti da STACKFRAME64 sono uno sforzo ottimale. –

+0

@RaymondChen: corretto, ma non riesco a pensare a un motivo che tale API non possa esistere. Una variante di 'SymGetSymFromAddr64' in cui dovresti assegnare uno stackframe e un indice di parametri, invece di un semplice puntatore. –

risposta

1

Non ci sono API per questo. Perché dovrebbero esserci, i sistemi operativi moderni non sono interessati ad alcune persone che giocano con questa roba. Come detto prima, il compilatore è libero di fare ottimizzazioni in modo da non poter avere nessuno strumento deterministico per farlo. Ma ci sono euristiche! È possibile sapere quanti parametri sono in funzione se si analizza l'assemblea prima della chiamata o si ritira dopo la chiamata, si ha sempre l'indirizzo di ritorno che è possibile verificare se è in CS.

Soprattutto, dovresti leggere sul termine "stack unwinding".

+0

Quasi - le tabelle di svolgimento sono una cosa in questi giorni a causa dei requisiti EH, e quelle avranno bisogno dei dati dei parametri in modo che possano scaricare parametri di tipo pass-by-value di tipo non banale. – LThode