Xv6堆栈框架 - eip的返回值被破坏了吗?

时间:2016-03-11 00:13:18

标签: c assembly xv6

我有以下代码尝试在xv6中运行:

void handle_signal(siginfo_t info)
{
    printf(1, "Caught signal %d...\n", info.signum);
    if (info.signum == SIGFPE)
        printf(1, "TEST PASSED\n");
    else
        printf(1, "TEST FAILED: wrong signal sent.\n");
    return;
}

int main(int argc, char *argv[])
{
   int x = 5;
   int y = 0;
   //int z = 0;
   signal(SIGFPE, handle_signal);

   x = x / y;
   //x = x / z;
   printf(1, "TEST FAILED: no signal sent.\n");

   return 0;
}

信号处理程序被推送到堆栈上,如下所示:

void handle_signal(int signo, struct trapframe *tf){
     *((uint*)(tf->esp-4)) = tf->eip;
     *((uint*)(tf->esp-8)) = proc->tf->eax;
     *((uint*)(tf->esp-12)) = proc->tf->ecx;
     *((uint*)(tf->esp-16)) = proc->tf->edx;
     *((uint*)(tf->esp-20)) = signo;
     *((uint*)(tf->esp-24)) =(uint)proc->pop;
     tf->esp = tf->esp-24;
     tf->eip = (uint)(proc->sigHandlers[signo]);
}

所以我将堆栈的底部设置为旧的指令指针,在这种情况下应该是指令

 x = x / y;

然后我按下易失性寄存器,按下信号处理程序参数,按下将弹出寄存器的函数,然后最后设置eip(指令指针)等于信号处理程序的地址。 / p>

这是我的pop函数:

void popregs(void){
__asm__ (
"add $8, %esp;"
"pop %edx;"
"pop %ecx;"
"pop %eax;"
"ret");
}

通常,这段代码应该运行并陷入SIGFPE调用的无限循环中,因为我每次在处理程序运行时都将指令指针设置回x = x / y调用。但是,出于某种原因,它会向前跳过并完成程序,然后使用非常不准确的EIP值进行分段错误。

让我感到困惑的是,如果我添加另一条指令x = x / z,就在下面,它可以完美地运行。当我尝试打印出程序的EIP时,它正确地指向x = x / y,因此它甚至不执行x / z部分。

有人能帮助我理解这个吗?我很难理解堆栈中可能发生的事情

0 个答案:

没有答案