2015-04-30 35 views
7

lo smontaggio assomiglia:Perché non posso entrare in un'istruzione di chiamata durante Debug/Disassembly?

   methShort(ref x, ref y); 
000007FF00163F67 lea   r8,[rsp+34h] 
000007FF00163F6C lea   rdx,[rsp+30h] 
000007FF00163F71 mov   rcx,qword ptr [rsp+20h] 
000007FF00163F76 mov   rcx,qword ptr [rcx+8] 
000007FF00163F7A mov   rax,qword ptr [rsp+20h] 
000007FF00163F7F call  qword ptr [rax+18h] 

Il metodo "methShort" viene creato dinamicamente in .NET utilizzando Reflection.Emit. Prende due parametri Int32 come valori "byRef". Questo è in fase di debug come build in "modalità di rilascio".

Posso passare attraverso il montaggio fino all'istruzione "call". Il contenuto della memoria puntata da R8 e RDX (i parametri) sembra buono. Non so che tipo di magia abbia permesso al JIT di usare i registri per la chiamata invece che per la pila, ma questo non è il punto.

Quando si tenta di "Passare a" l'istruzione di chiamata, il debugger "lo supera" invece. La routine viene effettivamente chiamata- il metodo ha eseguito correttamente la sua funzione. Ma non riesco a smontare né ad entrare nel metodo.

Nel punto immediatamente precedente alla chiamata, RAX contiene il valore 00000000025C67A8h. Quando viene aggiunto 18 ore, l'indirizzo per l'indiretto diventa 00000000025C67C0h. QWORD a questo indirizzo è 000000001b64dc48h.

Se provo a smontare questo indirizzo (000000001b64dc48h), il debugger ritorna con "L'indirizzo specificato non può essere visualizzato. Non c'è codice nel percorso fornito".

Come tentativo di Ave Maria, ho provato a smontare il codice in RAX senza l'indirezione, ma come mi aspettavo anche questo è fallito.

Qualcuno può dirmi come arrivare a qualunque codice sia all'indirizzo o se qualcosa di simile a LEA deve essere eseguito sull'indirizzo (RAX + 18h) prima di smontare il codice lì?

+3

https://msdn.microsoft.com/en-us/library/ms235286.aspx su x64 i primi due parametri di una chiamata di metodo sono in RCX e RDX. – xanatos

+1

VS rifiuta di mostrare alcune parti del runtime. Questa deve essere una chiamata helper di runtime. Non ho mai capito perché hanno fatto assolutamente che il debugger non riesca nemmeno a smontare il runtime. – usr

risposta

6

È necessario tenere presente che il debugger sta cercando di evitare di sprecare diverse ore della propria vita. methShort() è una chiamata delegata, deve ancora essere un lotto del lavoro svolto prima che la chiamata possa essere completata. Non vi godrete il single-step attraverso il jitter che compila il vostro metodo dinamico per il codice macchina, il CAS che controlla la richiesta di collegamento, il CLR che crea lo stub delegato e lo lega al sito di chiamata.

Risponderò alla domanda come postata, il debugger non ti mostrerà il codice di destinazione della chiamata perché è un codice non gestito. Puoi dire dall'indirizzo, lontano dalla posizione del tuo codice jitted. Convincere è che si vuole vedere richiede alcuni trucchi:

  • Progetto + Proprietà, scheda Debug, selezionare l'opzione "Attivare il debug di codice nativo"
  • Bisogna cambiare il debugger da riuscito a modalità non gestita. Non esiste un comando esplicito per questo, il modo più semplice che conosco come farlo è usare la finestra Call Stack. Fare doppio clic sul frame inferiore (__RtlUserThreadStart @ 8).
  • Fare clic sul collegamento "visualizza il disassemblaggio" nel popup Sorgente non disponibile per tornare nella finestra Disassembly. Il debugger è ora in modalità non gestita. Fai attenzione che non puoi facilmente dire più con il nuovo motore di debug poiché ora visualizza gli indirizzi di codice corretti.
  • Ora puoi inserire l'indirizzo che hai scoperto nella casella Indirizzo. Assicurati di mettere "0x" davanti ad esso.

Non altrimenti probabile che sia utile per eseguire il debug di un metodo dinamico, anche se ho abbastanza rapidamente gettato l'asciugamano quando l'ho provato.Probabilmente sei in anticipo chiamando il metodo due volte in modo da poter ignorare tutto il sovraccarico della seconda chiamata. Considera di mettere una chiamata a Debugger.Break() nel tuo metodo.