[英]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
需要进入什么软件可见的处理器状态? 什么处理器状态不?
我已经阅读了很多有关setjmp
和longjmp
但是找不到我的问题的明确答案。 我知道它是依赖于实现的,但是我想知道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的功能存储程序状态的确切含义):
jmp_buff
也需要存储该零页的副本(某些65xx CPU或ATmel AVR MCU)并且他们的编译器可能会使用此功能)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.