RSTORSSP
恢复已保存的阴影 栈指针
stableVMJITAOTinstruction
编码
| 操作码 | 指令 | Op/En | 64 位 | 兼容/传统 | 说明 |
|---|---|---|---|---|---|
F3 0F 01 /5 (mod!=11, /5, memory only) | RSTORSSP m64 | M | 有效 | 有效 | 还原 SSP 。 |
操作数编码
每个模式对应上表 Op/En 列的一个取值,说明各操作数按书写顺序分别编码在指令的哪个字段,以及指令对它是读、是写还是两者兼有。
M
modrm.rmlectura y escrituraModRM 字节的 r/m 字段(第 2-0 位);当 mod 字段要求时,还包括 SIB 字节和位移
实测开销
正在从 arch-data 加载实测数据...
涉及的标志位
CF进位PF奇偶AF辅助进位ZF零SF符号OF溢出
说明
从 m64 指向的阴影-stack-restore 符号中恢复 SSP. 如果 SSP 恢复成功,则指令会用前缀符号取代阴影存储符号. 指令设置了CF旗,以表示所处理的阴影-stack-restore符号中记录的SSP地址是否为4字节对齐,即当恢复-sshadow-stack符号被推到这个阴影堆栈时是否创建了对齐孔.
RSTORSSP之后,如果需要保存在上一个阴影堆栈上的还原-阴影-stack符号,则使用SAVEPREVSSP指令.
如果不需要在前一个阴影堆栈上按下还原-阴影-stack令牌,则前一个ssp令牌可以使用INCSSPQ指令弹出. 如果设定了CF旗以表示一个对齐孔的存在,则需要额外的INCSSPD指令来推进SSP通过对齐孔.
行动
IF CPL = 3
IF (CR4.CET & IA32_U_CET.SH_STK_EN) = 0
THEN #UD; FI;
ELSE
IF (CR4.CET & IA32_S_CET.SH_STK_EN) = 0
THEN #UD; FI;
FI;
SSP_LA = Linear_Address(mem operand)
IF SSP_LA not aligned to 8 bytes
THEN #GP(0); FI;
previous_ssp_token = SSP | (IA32_EFER.LMA AND CS.L) | 0x02
Start Atomic Execution
restore_ssp_token = Locked shadow_stack_load 8 bytes from SSP_LA
fault = 0
IF ((restore_ssp_token & 0x03) != (IA32_EFER.LMA & CS.L))
THEN fault = 1; FI; (* If L flag in token does not match IA32_EFER.LMA & CS.L or bit 1 is not 0 *)
IF ((IA32_EFER.LMA AND CS.L) = 0 AND restore_ssp_token[63:32] != 0)
THEN fault = 1; FI; (* If compatibility/legacy mode and SSP to be restored not below 4G *)
TMP = restore_ssp_token & ~0x01
TMP = (TMP - 8)
TMP = TMP & ~0x07
IF TMP != SSP_LA
THEN fault = 1; FI; (* If address in token does not match the requested top of stack *)
TMP = (fault == 0) ? previous_ssp_token : restore_ssp_token
shadow_stack_store 8 bytes of TMP to SSP_LA and release lock
End Atomic Execution
IF fault == 1
THEN #CP(RSTORSSP); FI;
SSP = SSP_LA
// Set the CF if the SSP in the restore token was 4 byte aligned, i.e., there is an alignment hole
RFLAGS.CF = (restore_ssp_token & 0x04) ? 1 : 0;
RFLAGS.ZF,PF,AF,OF,SF := 0;受影响的旗帜
CF被设定为表示恢复符中的阴影栈指针是否为4字节对齐,否则清除. ZF、PF、AF、OF和SF被清除。
C/C++ 编译器内置等效 RSTORSSP 空格 rstorssp(void *);
异常
保护模式
#UD | 如果使用 LOCK 前缀,如果使用 CR4.CET = 0. IF CPL = 3, IA32_U_CET.SH_STK_EN = 0. IF CPL < 3, IA32_S_CET.SH_STK_EN = 0. |
#GP(0) | 如果 内存操作数 的线性地址不是 8 字节对齐 。 如果 内存操作数 的有效地址位于 CS, DS, ES, FS, 或 GS 区段限制之外, 如果目的地位于不可写入区段内。 如果使用 DS, ES, FS, 或 GS 的寄存器来访问内存, 并包含 NULL 段选择子 。 |
#SS(0) | 如果 内存操作数 的有效地址在 SS 段限制之外。 |
#CP(rstorssp) | 如果符号中的 L 位不匹配( IA32_EFER.LMA & CS.L) 。 如果符号中的地址不匹配 内存操作数 的线性地址 。 如果在 32 位或兼容模式中, 符号中的地址不低于 4G. #PF(fault-code) 如果 页面错误 发生的话 。 |
实地址模式
#UD | RSTORSSP指令在实地址模式中不被识别. |
虚拟 8086 模式
#UD | RSTORSSP指令在虚拟 8086 模式中不被识别. |
兼容模式
| 与保护模式例外相同. |
64 位模式
#UD | 如果LOCK前缀被使用。如果CR4.CET=0. 如果CPL=3个和IA32_U_CET.SH_STK_EN=0. 如果CPL <联合国IA32_S_CET.SH_STK_EN = 0. |
#GP(0) | 如果 内存操作数 的线性地址不是 8 字节对齐。如果内存地址是非冠状的 。 |
#SS(0) | 如果引用SS部分的内存地址是非冠状的. |
#CP(rstorssp) | 如果符号中的 L 位不匹配( IA32_EFER.LMA & CS.L) 。 如果符号中的地址不匹配 内存操作数 的线性地址 。 #PF(fault-code) 如果 页面错误 发生 。 |