Pergunta

Como uma máquina virtual gera código de máquina nativo dinamicamente e o executa?

Supondo que você possa descobrir quais são os códigos operacionais da máquina nativa que deseja emitir, como você realmente executará isso?

É algo tão hackeado quanto mapear as instruções mnemônicas para códigos binários, inseri-las em um ponteiro char* e convertê-las em uma função e executá-las?

Ou você geraria uma biblioteca compartilhada temporária (.dll ou .so ou qualquer outra coisa) e a carregaria na memória usando funções padrão como LoadLibrary ?

Foi útil?

Solução

Você pode simplesmente fazer o contador de programa aponte para o código que você deseja executar.Lembre-se de que os dados podem ser dados ou código.No x86, o contador do programa é o registro EIP.A parte IP do EIP significa ponteiro de instrução.A instrução JMP é chamada para saltar para um endereço.Após o salto, o EIP conterá este endereço.

É algo tão hackeado quanto mapear as instruções mnemônicas para códigos binários, inseri-las em um ponteiro char* e convertê-las em uma função e executá-las?

Sim.Esta é uma maneira de fazer isso.O código resultante seria convertido em um ponteiro para função em C.

Outras dicas

É algo tão hackeado quanto mapear as instruções mnemônicas para códigos binários, inseri-las em um ponteiro char* e convertê-las em uma função e executá-las?

Sim, se você estivesse fazendo isso em C ou C++ (ou algo semelhante), é exatamente isso que você faria.

Parece hacky, mas na verdade é um artefato do design da linguagem.Lembre-se de que o algoritmo real que você deseja usar é muito simples:determine quais instruções você deseja usar, carregue-as em um buffer na memória e pule para o início desse buffer.

Se você realmente tentar fazer isso, certifique-se de acertar a convenção de chamada quando retornar ao seu programa C.Acho que se eu quisesse gerar código procuraria uma biblioteca que cuidasse desse aspecto para mim.Nanojit tem sido notícia recentemente;você poderia olhar para isso.

Sim.Você apenas cria um char* e o executa.No entanto, você precisa observar alguns detalhes.O char* deve estar em uma seção executável da memória e deve ter alinhamento adequado.

Além do nanojit, você também pode conferir o LLVM, que é outra biblioteca capaz de compilar várias representações de programas até um ponteiro de função.Sua interface é limpa e o código gerado tende a ser eficiente.

Pelo que eu sei, ele compila tudo na memória porque precisa executar algumas heurísticas para otimizar o código (ou seja:inlining ao longo do tempo), mas você pode dar uma olhada no Infraestrutura de linguagem comum de fonte compartilhada 2.0 liberação do rotor.Toda a base de código é idêntica ao .NET, exceto pelo Jitter e pelo GC.

Assim como o Rotor 2.0 - você também pode dar uma olhada no Máquina virtual HotSpot no OpenJDK.

Sobre a geração de uma DLL:a E/S adicional necessária para isso, mais a vinculação, mais a complexidade de gerar o formato DLL, tornariam isso muito mais complicado e, acima de tudo, prejudicariam o desempenho;além disso, no final você ainda chama um ponteiro de função para o código carregado, então...Além disso, a compilação JIT pode acontecer com um método de cada vez e, se você quiser fazer isso, gerará muitas DLLs pequenas.

Sobre o requisito da "seção executável", chamar mprotect() em sistemas POSIX pode corrigir as permissões (há uma API semelhante no Win32).Você precisa fazer isso para um grande segmento de memória, em vez de uma vez por método, pois seria muito lento.

Em x86 simples você não notaria o problema, em x86 com máquinas PAE ou AMD64/Intel de 64 bits de 64 bits você obteria um segfault.

É algo tão hacky quanto mapear as instruções mnemônicas para códigos binários, enchendo -o em um ponteiro de char* e lançando -o como uma função e executando?

Sim, isso funciona.

Para fazer isso no Windows você deve definir PAGE_EXECUTE_READWRITE para o bloco alocado:

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

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

MyFunc();
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top