【问题标题】:Make Stack Pointer to a mmap returned pointer. (Linux, 32bit VM)使堆栈指针指向 mmap 返回的指针。 (Linux,32 位虚拟机)
【发布时间】:2011-08-24 17:33:26
【问题描述】:

我试图将堆栈指针移动到 mmap-ed 区域以模拟上下文切换,但不知何故,下面的代码总是给出分段错误:

C:

struct savectx {
    void *regs[JB_SIZE];
};

struct savectx* initctx=(struct savectx*)malloc(sizeof(savectx));
void *newsp;
if ((newsp=mmap(0,STACK_SIZE,PROT_READ|PROT_WRITE,
    MAP_PRIVATE|MAP_ANONYMOUS,0,0))==MAP_FAILED){
    perror("mmap failed");
}
initctx->regs[4]=newsp;
restorectx(initctx,0);

x86:

 restorectx:
 movl   4(%esp),%ecx        /*Move jump buffer addr to ecx */
 movl   8(%esp),%eax        /*Longjmp return value */
 movl   (JB_SP*4)(%ecx),%esp    /*JB_SP is defined to be 4,*/

程序在程序集的最后一行失败。

对于 malloc,我知道我可能必须将 0x000f0000 添加到指针,但是 mmap 呢?或者我们如何使堆栈调整到 mmapp-ed 位置。 (mmap 手册页:http://linux.die.net/man/3/mmap,在 ubuntu 上使用 GCC 编译)

【问题讨论】:

    标签: c linux pointers assembly stack


    【解决方案1】:

    Linux(或一般的 UN*X)已经具有函数来执行这种上下文替换:

    如果你使用它们,你可以通过设置一个合适的ucontext_t/struct sigcontextuc_mcontextucontext_t 成员)来替换整个初始寄存器集(包括堆栈指针)。调用 setcontext() 然后变成一种扩展的 longjmp()

    使用示例可以在Wikipedia article on setcontext().中找到

    ucontext_t的Linux定义见:

    【讨论】:

    • 嗨。谢谢你回答这个问题。这将以与我的 savectx 结构相同的方式运行。我的问题实际上是如何将基础和堆栈指针调整到映射区域,而不是真正的保存上下文部分。
    • 爱迪生:因为例如函数调用依赖于有效/一致的堆栈(用于返回地址等),您不能只替换堆栈指针,因为不可能从这样做的函数返回。替换堆栈指针是上下文切换的一部分,无论执行它的函数名称如何。
    • 我想说:让makecontext() / setcontext() 作为第一步为你工作。到了那里后,将它们的源代码视为第二步。一旦你理解了这一点,就可以自己进行实验,将其重新实现(部分)作为第三步。这样你更有可能成功(并且做得很好)。
    • 我明白了。感谢您的建议。我现在就试试。
    【解决方案2】:

    所以问题实际上是 mmap 在堆栈的相反方向增长(遗憾的是,我忘记了)。所以要分配指针,我只需要分配 (mmaped_stack+stack_size) 而不仅仅是指针。

    【讨论】:

      猜你喜欢
      • 2016-11-09
      • 1970-01-01
      • 2013-10-13
      • 1970-01-01
      • 1970-01-01
      • 2020-03-09
      • 2012-12-13
      • 1970-01-01
      • 2020-07-22
      相关资源
      最近更新 更多