zoukankan      html  css  js  c++  java
  • 关于非本地跳转

    csapp p_795

    如下所述的问题经过讨论并未被解决……

    以下示例中未以ARM为例,因为我查到的ARM的ABI规范中,寄存器均由callee保存,或者callee与caller均不保存,因此很容易可以解决下列问题。以下以i386为例.


    关于非本地跳转存在的疑问(以setjmp、longjmp为例)
    函数调用之间需遵循ABI规范
        有些寄存器是由caller保存(以备被callee使用而修改原来的值),当从callee返回后恢复这些寄存器;
        有些寄存器是由callee保存(以备被callee使用而修改原来的值),当即将从callee返回时恢复这些寄存器;
        某些寄存器可以随便使用,即不需要caller保存恢复,也不需要callee保存恢复。

    问题:
        A函数调用setjmp函数而后返回到A函数继续执行,由于一些临时变量的存在因此A函数的栈空间中会继续填入新值,而后A函数调用了B函数,B函数调用了longjmp函数,此时会恢复在调用setjmp时保存的context,再次从setjmp返回,继而在A函数中继续执行。
        A函数在调用setjmp是会将caller save registers保存在自己的栈空间,而后传入实参到栈上(以x86为例,ARM通过寄存器传递),当从setjmp函数返回后A函数将从栈上恢复caller save registers,继续执行;无论是第一次从setjmp返回,还是由于在B函数调用了longjmp函数进而从setjmp返回,A函数都应从栈上恢复caller save registers.
        图示如下:
        A函数调用setjmp之前的栈:
        |-------------|
        |   %ecx    |
        |-------------|
        |   %edx    |
        |-------------|

        A函数传实参(由于是数组,演变成指针)
        |-------------|
        |   %ecx     |
        |-------------|
        |   %edx    |
        |-------------|
        | jmp_buf地址 |
        |-------------|
        | 下条指令地址| --------->弹出caller save registers
        |-------------|

        首次从setjmp返回后,A函数继续运行相应的指令,恢复caller save registers;
        由于已经恢复caller save registers已经恢复,因此原保存%ecx、%edx的栈空间可以被其它临时量继续占用,因此该部分栈空间内容已经不再是%ecx、%edx;
        第二次从setjmp返回后,A函数仍然会运行同样的指令,恢复所谓的"caller save registers",但是此时恢复出的值显然是不对的。

        这个问题讨论有些久了,可是没有得到很好的解答,对于mips而言应该也会遇到的同样的问题,ABI规范上已经说明有些寄存器须由caller保存与恢复。
        写了几个程序(x86与mips)均未出现图示中的类似情形,是不是自己哪里理解错了?!!

  • 相关阅读:
    mysql显示乱码
    aws常用命令
    Hive分析窗口函数(一) SUM,AVG,MIN,MAX
    Hive函数介绍
    Apache Drill 调研学习
    公有云与私有云对比分析报告
    python3 使用libvirt 相关安装
    libvirt虚拟库
    Reveal CocoaPods的使用
    AFNetworking 2.0 使用
  • 原文地址:https://www.cnblogs.com/openix/p/3229709.html
Copyright © 2011-2022 走看看