繁体   English   中英

在x86-64处理器上的jmp_buf中需要什么软件可见的处理器状态?

[英]What software-visible processor state needs to go in a jmp_buf on an x86-64 processor?

如前所述,当调用setjmp(jmp_buf env)时,x86-64处理器上的jmp_buf需要进入什么软件可见的处理器状态? 什么处理器状态不?

我已经阅读了很多有关setjmplongjmp但是找不到我的问题的明确答案。 我知道它是依赖于实现的,但是我想知道x86_64体系结构。

下面的实现中 ,似乎在x86-64机器上,需要保存所有被调用方保存的寄存器( %r12-%r15%rbp%rbx )以及堆栈指针,程序计数器和所有已保存的参数当前环境。 但是我不确定,希望有人能为我澄清一下。

例如,需要保存哪些x86-64寄存器? 条件标记呢? 例如,我认为不需要保存浮点寄存器,因为它们不会影响程序的状态。

那是因为调用约定。 setjmp是一个函数调用,它可以返回多次(第一次是您实际调用它,而后一次是longjmp调用longjmp ),但这仍然是一个函数调用。 像任何函数调用一样,编译器假定所有被调用阻塞的寄存器都已被破坏,因此longjmp不需要还原它们。

是的,它们不是函数调用边界上“程序状态”的一部分,因为编译器生成的asm绝对不会在其中保留任何值。

您正在看x86-64 System V ABI的glibc实现,其中所有 vector / x87寄存器都被调用,因此不必保存。

在Windows x86-64调用约定中,xmm6-15是调用保留的(只是低128位,而不是y / zmm6-15的高部分),并且必须是jmp_buf一部分。

也就是说,与CPU架构无关的是软件调用约定。


除了保留调用的寄存器外,关键一点是,将longjmp到由父函数保存的jmp_buf仅是合法的,而不是在调用setjmp的函数返回后再从任意函数中获取。

如果setjmp必须支持它,则必须保存整个堆栈帧,或者实际上(为了函数可以返回,并且该父对象可以返回,等等)保存整个堆栈,直到到达最佳。 这显然是疯狂的,因此很清楚为什么longjmp只能限制跳转到父/(伟大的)祖父母函数,所以只需要还原堆栈指针以指向仍然存在的堆栈帧并还原任何内容即可。自setjmp以来,该函数中的局部变量可能已被修改。

(在使用普通调用堆栈以外的内容的体系结构/调用约定的C / C ++实现中,关于跳转目标函数能够返回的类似论点仍然适用。)

由于jmp_buf是可用于还原longjmp上的处理器状态的唯一位置,因此通常是还原setjmp时恢复机器的完整状态所需的一切。

显然,这很大程度上取决于处理器和编译器(它使用CPU的功能存储程序状态的确切含义):

  • 在理想的纯堆栈计算机上,它仅在堆栈上保存CPU状态信息,而堆栈仅是堆栈指针。 除了在非常古老或纯粹是学术上的实现之外,这种机器很少存在。 但是,您可以在x86之类的现代机器上编写一个编译器,该编译器仅使用堆栈来存储此类信息。 对于这种假设的编译器,仅保存堆栈指针就足以恢复程序状态。
  • 在更常见的实用计算机上,这可能是堆栈指针和用于存储程序状态的完整寄存器集。
  • 在某些将程序状态信息存储在其他地方(例如零页)的CPU上,以及使用此类CPU功能的编译器上, jmp_buff也需要存储该零页的副本(某些65xx CPU或ATmel AVR MCU)并且他们的编译器可能会使用此功能)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM