Подтвердить что ты не робот

Методы создания кода JIT

Как виртуальная машина генерирует собственный машинный код на лету и выполняет его?

Предполагая, что вы можете выяснить, каковы исходные коды операций на компьютере, которые вы хотите исправить, как вы это делаете?

Является ли это чем-то взломанным, как сопоставление мнемонических инструкций с двоичными кодами, наложение его на указатель char * и его литье как функцию и выполнение?

Или вы создадите временную общую библиотеку (DLL или .so или что-то еще) и загрузите ее в память с помощью стандартных функций, таких как LoadLibrary?

4b9b3361

Ответ 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.

Ответ 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();