【问题标题】:mmap related segmentation faultmmap 相关的分段错误
【发布时间】:2012-03-05 23:37:09
【问题描述】:

我正在编写一个模拟器,我需要将机器代码直接写入内存,然后跳转到(调用)它。我用 mmap 分配内存,然后将代码写入它。除了“ret”或“nop”指令段错误之外的任何内容。我知道 mmap 返回时不会出错,并且我已经在一个示例中隔离了这个问题,以说明这个问题。

#include <stdio.h>
#include <sys/mman.h>
#include <stdint.h>

int main()
{
  uint8_t *data = mmap(NULL, 3 * sizeof(uint8_t), PROT_EXEC|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0), *p;
  p = data;
  if(data) {
    *p++ = 0xb8; //mov $1, %eax
    *p++ = 0x01;
    *p++ = 0xC3; //ret
  } else
    perror("mmap");

  uint8_t (*fp)();
  fp = (void*) (data);
  printf("%u\n",(uint8_t) fp());
  return 0;
}

这个例子产生了问题。帮忙?

编辑:我应该提到我在 Linux 2.6、x86 上。

【问题讨论】:

  • 你确定你的操作码是正确的吗? mov %1, eax 至少占用 5 个字节,立即数占用 4 个字节。
  • 在许多系统上,PROT_EXEC 不允许使用 PROT_WRITE。你需要先使内存读/写,然后使用mprotect将权限更改为读/执行。

标签: c assembly x86 segmentation-fault mmap


【解决方案1】:

您的操作码不正确,这可行:

if(data) {
    *p++ = 0xb8; //mov $1, %eax
    *p++ = 0x01;
    *p++ = 0x00;
    *p++ = 0x00;
    *p++ = 0x00;
    *p++ = 0xC3; //ret
}

0xb8 将 32 位立即数移动到 eax,因此您必须指定所有 4 个字节。

【讨论】:

  • 哇,我怎么没听懂。谢谢。这消除了实际模拟器代码中的一种可能性。
猜你喜欢
  • 2018-06-06
  • 1970-01-01
  • 2020-06-29
  • 2017-04-18
  • 1970-01-01
  • 1970-01-01
  • 2011-11-29
  • 2017-07-23
  • 1970-01-01
相关资源
最近更新 更多