【问题标题】:Executing code from memory从内存中执行代码
【发布时间】:2017-06-27 05:03:51
【问题描述】:

假设我想在 C 中进行某种 JIT 编译。我反汇编函数并将其代码插入到我的程序中的内存中:

#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;
}

但是,在调用 foo.这段代码有什么问题?首先,我认为问题出在访问权限上,但标志似乎设置正确。

【问题讨论】:

  • 调试器在这里可能会有所帮助。
  • 另外,您必须确保编译器遵守 jitted 函数所需的调用约定,即参数 2 必须在 rdi 中,而不是在堆栈上。
  • @BlagovestBuyukliev 是的......我也会明确调用约定,检查你是否真的在 x64(而不是 x86)上运行,然后真正构建自己的 JIT 的真正可怕之处开始吧...我过去构建了几个 JIT,但现在只推荐使用 LLVM。
  • @Jean-FrançoisFabre 调试器抛出异常:调用 foo 时出现 EXC_BAD_ACCESS。我已经发现了问题 - 汇编列表错误。
  • @NikitaRock:这当然是有问题的,但为了确保代码不会在其他 ABI/编译器下中断,您必须使用特殊属性限定 jitFunc 类型,该属性指定调用约定。

标签: c memory jit


【解决方案1】:

我认为我找到了它:

0,48, 0x83, 0xc0, 0x04

应该是

0x48, 0x83, 0xc0, 0x04

【讨论】:

  • 非常感谢,这么愚蠢的错误,浪费了很多时间。现在它可以正常工作了
猜你喜欢
  • 2021-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-02
  • 2021-02-09
  • 2013-03-08
  • 1970-01-01
  • 2017-03-12
相关资源
最近更新 更多