Методы создания кода JIT
Как виртуальная машина генерирует собственный машинный код на лету и выполняет его?
Предполагая, что вы можете выяснить, каковы исходные коды операций на компьютере, которые вы хотите исправить, как вы это делаете?
Является ли это чем-то взломанным, как сопоставление мнемонических инструкций с двоичными кодами, наложение его на указатель char * и его литье как функцию и выполнение?
Или вы создадите временную общую библиотеку (DLL или .so или что-то еще) и загрузите ее в память с помощью стандартных функций, таких как LoadLibrary
?
Ответы
Ответ 1
Вы можете просто сделать счетчик программ указать код, который вы хотите выполнить. Помните, что данные могут быть данными или кодом. На x86 счетчик программ - это регистр EIP. IP-часть EIP обозначает указатель на инструкцию. Команда JMP вызывается для перехода к адресу. После перехода EIP будет содержать этот адрес.
Является ли это чем-то взломанным, как сопоставление мнемонических инструкций с двоичными кодами, наложение его на указатель char * и его литье как функцию и выполнение?
Да. Это один из способов сделать это. Полученный код будет переведен в указатель на функцию в C.
Ответ 2
Является ли это чем-то взломанным, как сопоставление мнемонических инструкций с двоичными кодами, наложение его на указатель char * и его литье как функцию и выполнение?
Да, если вы делали это на C или С++ (или что-то подобное), это именно то, что вы сделали.
Он кажется взломанным, но это фактически артефакт языкового дизайна. Помните, что фактический алгоритм, который вы хотите использовать, очень прост: определите, какие команды вы хотите использовать, загрузите их в буфер в памяти и перейдите к началу этого буфера.
Если вы действительно попытаетесь это сделать, убедитесь, что вы получили право на вызов, когда вы вернетесь в свою программу на C. Я думаю, что если бы я хотел создать код, я бы искал библиотеку, чтобы позаботиться об этом для меня. Недавно Наноит был в новостях; вы можете посмотреть на это.
Ответ 3
Угу. Вы просто создаете char * и выполняете его. Однако вам нужно отметить пару деталей. char * должен находиться в исполняемом разделе памяти и должен иметь правильное выравнивание.
В дополнение к nanojit вы также можете проверить LLVM, который представляет собой еще одну библиотеку, способную скомпилировать различные представления программ до указателя функции. Этот интерфейс чист, и сгенерированный код имеет тенденцию быть эффективным.
Ответ 4
Насколько я знаю, он компилирует все в памяти, потому что для оптимизации кода требуется выполнить некоторую эвристику (т.е. встраивание с течением времени), но вы можете взглянуть на Общая версия Common Language Infrastructure 2.0 ротора. Вся база кода идентична .NET, за исключением Jitter и GC.
Ответ 5
Как и Rotor 2.0, вы также можете взглянуть на виртуальную машину HotSpot в OpenJDK.
Ответ 6
О создании DLL: дополнительный требуемый ввод-вывод для этого, плюс связывание, а также сложность генерации DLL-формата сделали бы это намного более сложным, и прежде всего они убьют производительность; Кроме того, в конце вы все еще вызываете указатель на загруженный код, поэтому...
Кроме того, компиляция JIT может происходить по одному методу за раз, и если вы хотите сделать это, вы создадите большое количество небольших DLL.
О требовании "исполняемого раздела", вызов mprotect() в системах POSIX может исправить разрешения (там есть аналогичный API на Win32). Вам нужно сделать это для большого сегмента памяти, а не для одного метода, поскольку в противном случае он будет слишком медленным.
На простой x86 вы не заметите проблемы, на x86 с PAE или 64-разрядными 64-разрядными 64-разрядными машинами AMD64/Intel вы получите segfault.
Ответ 7
Это что-то вроде хакерства, как отображение мнемонические инструкции для двоичных коды, набирая его в char * указатель и отбрасывание его как функции и выполнение?
Да, это работает.
Чтобы сделать это в Windows, вы должны установить PAGE_EXECUTE_READWRITE в выделенный блок:
void (*MyFunc)() = (void (*)()) VirtualAlloc(NULL, sizeofblock, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
//Now fill up the block with executable code and issue-
MyFunc();