Пусть говорят, что я хотел бы сделать вид JIT компиляции в C. Я разборку функцию и вставьте его код в памяти прямо в моей программе:Выполнение кода из памяти
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
void* alloc_executable_memory(size_t size) {
void *ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
if (ptr == MAP_FAILED) {
fprintf(stderr, "%s\n", "mmap failed");
return NULL;
}
return ptr;
}
void push_code_into_memory(unsigned char *memory) {
unsigned char code[] = {
0x48, 0x89, 0xf8, // mov %rdi, %rax
0,48, 0x83, 0xc0, 0x04, // add $4, %rax
0xc3 // ret
};
memcpy(memory, code, sizeof(code));
}
int make_memory_executable(void* memory, size_t size) {
if (mprotect(memory, size, PROT_READ | PROT_EXEC) == -1) {
fprintf(stderr, "%s\n", "mprotect failed");
return -1;
}
return 0;
}
const size_t SIZE = 512;
typedef long (*jitFunc)(long);
int main(int argc, char const *argv[]) {
void *mem = alloc_executable_memory(SIZE);
push_code_into_memory((unsigned char *)mem);
make_memory_executable(mem, SIZE);
jitFunc foo = (jitFunc)mem;
int res = foo(2);
printf("%d\n", res);
return 0;
}
Однако, я всегда получаю выдаёт ошибку сегментации 11 (macOS) после вызова foo. Что не так с этим кодом? Во-первых, я думал, что проблема связана с правами доступа, но флаги, кажется, установлены правильно.
отладчик может быть полезным здесь. –
Кроме того, вы должны убедиться, что компилятор соблюдает соглашение о вызове, требуемое функцией jitted, то есть аргумент '2' должен находиться в' rdi', а не в стеке. –
@BlagovestBuyukliev Да ... Я бы также сделал соглашения о вызовах явным, проверьте, действительно ли вы работаете на x64 (а не на x86), а затем реальные ужасы построения собственного JIT действительно начинаются ... Я построил несколько JIT в прошлом, но в настоящее время просто рекомендуют использовать LLVM. – atlaste