Domanda

In che modo una macchina virtuale genera al volo il codice macchina nativo e lo esegue?

Supponendo che tu riesca a capire quali sono i codici operativi nativi della macchina che desideri emettere, come fai a eseguirlo effettivamente?

È qualcosa di così complicato come mappare le istruzioni mnemoniche in codici binari, inserirle in un puntatore char* e lanciarle come una funzione ed eseguirle?

Oppure genereresti una libreria condivisa temporanea (.dll o .so o altro) e la caricheresti in memoria utilizzando funzioni standard come LoadLibrary ?

È stato utile?

Soluzione

Puoi semplicemente fare il contatore di programma punta al codice che vuoi eseguire.Ricorda che i dati possono essere dati o codice.Su x86 il contatore del programma è il registro EIP.La parte IP di EIP sta per puntatore di istruzioni.L'istruzione JMP viene richiamata per passare a un indirizzo.Dopo il salto l'EIP conterrà questo indirizzo.

È qualcosa di così complicato come mappare le istruzioni mnemoniche in codici binari, inserirle in un puntatore char* e lanciarle come una funzione ed eseguirle?

SÌ.Questo è un modo per farlo.Il codice risultante verrebbe convertito in a puntatore alla funzione in C.

Altri suggerimenti

È qualcosa di così complicato come mappare le istruzioni mnemoniche in codici binari, inserirle in un puntatore char* e lanciarle come una funzione ed eseguirle?

Sì, se lo facessi in C o C++ (o qualcosa di simile), è esattamente quello che faresti.

Sembra complicato, ma in realtà è un artefatto della progettazione del linguaggio.Ricorda, l'algoritmo vero e proprio che desideri utilizzare è molto semplice:determina quali istruzioni desideri utilizzare, caricale in un buffer in memoria e salta all'inizio di quel buffer.

Se provi davvero a farlo, assicurati di ottenere la convenzione di chiamata corretta quando torni al tuo programma C.Penso che se volessi generare codice cercherei una libreria che si occupi di quell'aspetto per me.Nanojit è apparso nelle notizie di recente;potresti guardarlo.

Sì.Basta creare un char* ed eseguirlo.Tuttavia, è necessario notare un paio di dettagli.Il carattere* deve trovarsi in una sezione eseguibile della memoria e deve avere un allineamento corretto.

Oltre a nanojit puoi anche controllare LLVM che è un'altra libreria in grado di compilare varie rappresentazioni di programmi fino a un puntatore a funzione.La sua interfaccia è pulita e il codice generato tende ad essere efficiente.

Per quanto ne so compila tutto in memoria perché deve eseguire alcune euristiche per ottimizzare il codice (es.:inlining nel tempo) ma puoi dare un'occhiata a Infrastruttura linguistica comune di origine condivisa 2.0 rilascio del rotore.L'intero codebase è identico a .NET ad eccezione di Jitter e GC.

Oltre a Rotor 2.0, potresti anche dare un'occhiata a Macchina virtuale HotSpot nell'OpenJDK.

Informazioni sulla generazione di una DLL:l'I/O aggiuntivo richiesto per questo, oltre al collegamento, oltre alla complessità della generazione del formato DLL, renderebbe il tutto molto più complicato e, soprattutto, comprometterebbe le prestazioni;inoltre, alla fine chiami comunque un puntatore a funzione al codice caricato, quindi...Inoltre, la compilazione JIT può avvenire un metodo alla volta e, se lo desideri, genereresti molte piccole DLL.

Per quanto riguarda il requisito della "sezione eseguibile", chiamare mprotect() sui sistemi POSIX può correggere le autorizzazioni (esiste un'API simile su Win32).È necessario farlo per un segmento di memoria di grandi dimensioni invece che una volta per metodo poiché altrimenti sarebbe troppo lento.

Su x86 non noteresti il ​​problema, su x86 con PAE o macchine AMD64/Intel a 64 bit a 64 bit otterresti un segfault.

È qualcosa di così hacky come mappare le istruzioni mnemoniche ai codici binari, riempiendolo in un puntatore Char* e lanciandolo come funzione ed esecuzione?

Sì, funziona.

Per fare ciò in Windows è necessario impostare PAGE_EXECUTE_READWRITE sul blocco allocato:

void (*MyFunc)() = (void (*)()) VirtualAlloc(NULL, sizeofblock,  MEM_COMMIT, PAGE_EXECUTE_READWRITE);

//Now fill up the block with executable code and issue-

MyFunc();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top