用户层异常与内核层异常
异常可以发生在用户空间,也可以发生在内核空间。
无论是CPU异常还是模拟异常,是用户层异常还是内核异常,都要通过 KiDispatchException函数进行分发,这个函数比较复杂。
VOID KiDispatchException
(
ExceptionRecord,
ExceptionFrame,
TrapFrame,
PreviousMode,
FirstChance //第几次调用
)
没有调试器或者内核调试器没有处理,跳转的地方都是一样的都是这。
RtIDispatchException执行流程
kpcr.ExceptionList结构
typedef struct _EXCEPTION_REGISTRATION_RECORD
{
struct EXCEPTION_REGISTRATION_RECORD* Next; //下一个节点,如过为-1就是没有下一个节点了
PEXCEPTION_ROUTINE Handler; //指向下一个异常处理函数
} EXCEPTION_REGISTRATION_RECORD;
- 遍历异常链表,调用异常处理函数,如果异常被正确处理了,该函数返回1
- 如果当前异常处理函数不能处理该异常,那么调用下一个,以此类推。
- 如果到最后也没有人处理这个异常,返回0。
如果RtIDispatchException返回是1,异常就处理掉了。
将原来的 CONTEXT 放回 Trap_Frame 结构中,异常已经处理掉了不需要返回3环。
如果RtIDispatchException返回是0,异常没有被处理
- _KeContextFromKframes将Trap_Frame备份到context为返回3环做准备
- 判断先前模式0是内核调用 1是用户层调
- 是否是第一次调用
- 是否有内核调试器
- 如果没有或者内核调试器不处理
- 调用 RtIDispatchException
- 如果返回TRUE这个分发结束了,异常解决了。
- 如果返回FALSE,再次判断是否有内核调试器 有就调用 没有直接蓝屏