news 2026/8/4 16:34:09

Page Fault处理函数在汇编层面如何处理错误码

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Page Fault处理函数在汇编层面如何处理错误码

在 x86_64 架构下,#PF(Page Fault)处理函数的汇编层面,处理错误码主要分两个核心部分:保存现场时将它作为参数传递,以及恢复现场时在iretq之前正确地跳过它。此外,错误码本身包含了触发异常的关键信息。


第一部分:进入处理函数——保存错误码并传递

当 CPU 触发#PF时,它会自动完成以下操作:

  1. 压栈:将错误码压入当前栈中。此时栈顶布局为:

    [rsp] → 错误码 (Error Code) [rsp+8] → RIP [rsp+16] → CS [rsp+24] → RFLAGS [rsp+32] → RSP (如果发生了特权级切换) [rsp+40] → SS (如果发生了特权级切换)
  2. 跳转:通过 IDT(中断描述符表)中的#PF门描述符,跳转到内核注册的处理函数入口。

在汇编入口处,需要保存通用寄存器,并将错误码作为参数,传递给后续的 C 语言处理函数。

; 汇编入口:page_fault_handler_entry page_fault_handler_entry: ; 1. 保存所有通用寄存器,以便在 C 函数中恢复 push rax push rbx push rcx push rdx push rsi push rdi push rbp push r8 push r9 push r10 push r11 push r12 push r13 push r14 push r15 ; 2. 保存当前栈指针到 rbp,方便后续定位 mov rbp, rsp ; 3. 将错误码作为第一个参数传递给 C 函数 ; 注意:错误码此时位于 [rbp + 15*8] 处 ; (因为我们已经压入了 15 个 8 字节的通用寄存器) mov rdi, [rbp + 15*8] ; rdi = Error Code ; 4. 将出错的虚拟地址(CR2)作为第二个参数 mov rsi, cr2 ; rsi = Faulting Address push rsi ; 保存 CR2 到栈上(可选) ; 5. 调用 C 语言编写的核心处理函数 call do_page_fault ; void do_page_fault(unsigned long error_code, unsigned long address) ; 6. C 函数返回后,恢复之前保存的寄存器 ; 注意:此时 rsp 需要恢复到保存通用寄存器之后的位置 mov rsp, rbp pop r15 ; ... (按相反顺序弹出所有寄存器) pop rax ; 7. 跳过错误码并返回 add rsp, 8 iretq

第二部分:do_page_faultC 函数对错误码的解析

C 函数do_page_fault会收到错误码,并解析其位字段以决定处理方式:

错误码 Bit含义处理逻辑
Bit 0 (P)0 = 页不存在,1 = 权限违规若为 0,分配物理页并建立映射;若为 1,检查权限。
Bit 1 (W)0 = 读操作,1 = 写操作确定访问类型,用于 COW(写时复制)或只读页错误。
Bit 2 (U)0 = 内核态,1 = 用户态决定是内核错误(panic)还是用户态错误(SIGSEGV)。
Bit 3 (RSVD)1 = 使用了保留位通常意味着页表损坏,直接触发panic
Bit 4 (I/D)1 = 指令获取若为 1,表示 CPU 尝试从此地址执行指令,需特殊处理。

第三部分:返回前正确处理错误码

在汇编中,关键在于add rsp, 8指令的位置。它必须紧跟在iretq之前执行:

  • 为什么是add rsp, 8因为错误码是 CPU 在进入处理程序时压入的,它不属于iretq的正常返回栈帧。iretq期望栈顶是RIP,如果不跳过,iretq会尝试将错误码当作RIP使用,导致系统崩溃。

错误码的常见陷阱

  • 栈偏移计算错误:在多级栈帧中,如果你在通用寄存器压栈和call指令之间操作了栈,那么错误码在栈上的偏移量会发生改变。

  • 忘记处理CR2:在 64 位模式下,出错的地址存放在CR2寄存器中。在调用do_page_fault之前,必须将CR2的值也作为参数传递。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/4 16:33:59

YimMenu终极指南:如何在GTA5在线模式中安全增强游戏体验

YimMenu终极指南:如何在GTA5在线模式中安全增强游戏体验 【免费下载链接】YimMenu YimMenu, a GTA V menu protecting against a wide ranges of the public crashes and improving the overall experience. 项目地址: https://gitcode.com/GitHub_Trending/yi/Yi…

作者头像 李华
网站建设 2026/8/4 16:33:35

机械键盘打字出现重复字母?这个免费开源工具帮你精准修复

机械键盘打字出现重复字母?这个免费开源工具帮你精准修复 【免费下载链接】KeyboardChatterBlocker A handy quick tool for blocking mechanical keyboard chatter. 项目地址: https://gitcode.com/gh_mirrors/ke/KeyboardChatterBlocker 你是否曾经在打字时…

作者头像 李华
网站建设 2026/8/4 16:31:49

HDR全景图转Cubemap完整工具链配置与避坑指南

1. 项目概述:为什么我们需要一个“避坑指南”? 如果你正在处理高动态范围(HDR)的全景图,并且想把它们转换成用于游戏引擎、实时渲染或者离线渲染的Cubemap(立方体贴图),那你大概率已…

作者头像 李华
网站建设 2026/8/4 16:30:17

PWN技术解析:picoCTF 2018 Shellcode漏洞利用

1. 项目概述:PWN picoctf_2018_shellcode 技术解析 这个CTF题目来自picoCTF 2018赛事,属于二进制漏洞利用(PWN)方向的经典题型。题目提供了一个存在栈溢出漏洞的ELF可执行文件,要求选手通过构造特殊的机器指令序列&…

作者头像 李华
网站建设 2026/8/4 16:29:30

字体渲染投毒与AI安全防御:分层防线构建方案

字体渲染投毒与AI安全防御:分层防线构建方案下面用一张流程图总览从数据源到 AI 输出的五层防御架构,以及每一层对应的核心拦截点:flowchart TDsubgraph S1[数据源管控]A1[分级信任源]A2[静态文档优先]endsubgraph S2[网页抓取对抗]B1[双路抓…

作者头像 李华
网站建设 2026/8/4 16:29:01

浏览器端图像压缩技术痛点与Compressor.js解决方案深度解析

浏览器端图像压缩技术痛点与Compressor.js解决方案深度解析 【免费下载链接】compressorjs JavaScript image compressor. 项目地址: https://gitcode.com/gh_mirrors/co/compressorjs 在当今Web应用中,图像处理已成为性能优化的关键瓶颈。大尺寸图像不仅拖慢…

作者头像 李华