Я собираюсь написать свой собственный JIT-интерпретатор как часть курса по виртуальным машинам. Я у меня много знаний о языках высокого уровня, компиляторах и интерпретаторах, но мало или совсем нет знаний о сборке x86 (или C, если на то пошло).
На самом деле я не знаю, как работает JIT, но вот мое мнение на нем: Прочтите программу на каком-то промежуточном языке. Скомпилируйте ее в инструкции x86. Убедитесь, что последняя инструкция вернулась куда-нибудь в разумное место обратно в код виртуальной машины. Сохраните инструкции где-нибудь в памяти. Выполните безусловный переход к первой инструкции. Вуаля !
Имея это в виду, у меня есть следующая небольшая программа на C:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main() {
int *m = malloc(sizeof(int));
*m = 0x90; // NOP instruction code
asm("jmp *%0"
: /* outputs: */ /* none */
: /* inputs: */ "d" (m)
: /* clobbers: */ "eax");
return 42;
}
Итак, я намерен, чтобы эта программа сохраняла инструкцию NOP где-нибудь в памяти, переходила в это место, а затем возможно, произойдет сбой (потому что я не настроил способ возврата программы к основному состоянию).
Вопрос: На правильном ли я пути?
Вопрос: Не могли бы вы показать мне модифицированную программу, которой удается вернуться куда-то внутри main?
Вопрос: Другие проблемы, которых я должен остерегаться ?
PS: Моя цель - понять, а не обязательно делать все правильно.
Спасибо за отзывы.Следующий код, кажется, является местом для начала и работает на моем Linux:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
unsigned char *m;
int main() {
unsigned int pagesize = getpagesize();
printf("pagesize: %u\n", pagesize);
m = malloc(1023+pagesize+1);
if(m==NULL) return(1);
printf("%p\n", m);
m = (unsigned char *)(((long)m + pagesize-1) & ~(pagesize-1));
printf("%p\n", m);
if(mprotect(m, 1024, PROT_READ|PROT_EXEC|PROT_WRITE)) {
printf("mprotect fail...\n");
return 0;
}
m[0] = 0xc9; //leave
m[1] = 0xc3; //ret
m[2] = 0x90; //nop
printf("%p\n", m);
asm("jmp *%0"
: /* outputs: */ /* none */
: /* inputs: */ "d" (m)
: /* clobbers: */ "ebx");
return 21;
}