You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86-64内核无效Opcode中断处理:跳转原处理器时保留GPR的问题

无效Opcode中断处理程序跳转问题解决

问题场景

课程要求实现自定义无效Opcode中断处理程序,当处理流程中调用的某函数返回0时,需将控制权交还给原处理程序,原处理程序地址已保存至全局变量void *old_ili_handler。

当前处理程序序言会压入所有通用寄存器以保护现场:

my_ili_handler:
    push %rax
    push %rbx
    ; ... 依次压入其余通用寄存器 ...
    push %r15

在尝试跳转原处理程序时,若先弹出所有寄存器恢复原始状态,再执行movq old_ili_handler(%rip), %r8 + jmp *%r8,会覆盖R8寄存器的原始值,破坏中断发生前的CPU状态,不符合要求。

问题根源

恢复通用寄存器后,再使用任意通用寄存器暂存原处理程序地址,必然会修改该寄存器的原始值,导致现场状态被破坏。

可行解决方案

最优方案:使用RIP相对间接跳转

64位模式下,直接通过RIP相对寻址完成间接跳转,无需借助任何通用寄存器,完全不会破坏已恢复的现场状态:

; 依次弹出所有通用寄存器恢复现场
pop %r15
pop %r14
; ... 弹出其余通用寄存器 ...
pop %rax
; 直接通过RIP相对寻址获取原处理程序地址并跳转,不修改任何寄存器
jmp *old_ili_handler(%rip)

备选方案:利用栈暂存地址(兼容特殊场景)

若因环境限制无法使用RIP相对寻址,可在恢复寄存器前将原处理程序地址压入栈,恢复完成后通过栈地址跳转:

; 先将原处理程序地址压入栈顶
movq old_ili_handler(%rip), %rax
push %rax
; 依次弹出所有通用寄存器恢复现场
pop %r15
pop %r14
; ... 弹出其余通用寄存器 ...
pop %rbx
pop %rax
; 跳转至栈顶存储的原处理程序地址
jmp *(%rsp)
; 跳转后原处理程序会自行处理栈帧,无需额外清理

内容的提问来源于stack exchange,提问作者FalleN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 21:43:09