CPU异常与软件模拟异常调用流程与区别
本帖最后由 Print动 于 2021-1-25 20:50 编辑****************本帖为个人学习笔记,若有错误内容,请各位大佬指点***************异常与调试是紧密相连的。异常记录:1.要记录异常信息2.异常是什么类型3.异常是在什么位置发生的异常的分发:上面的信息记录下来以后,寻找处理异常的函数。这个过程为异常的分发异常处理:最后找到异常处理函数并调用(异常处理)异常记录,异常分发,异常处理。
异常的分类:(本质上大体的分类)1. CPU产生的异常一定是CPU发现的2. 软件模拟产生的异常高级语言模拟产生的异常CPU异常的产生:CPU指令检测到异常(例如:除0) --> 查IDT表,执行中断处理函数 --> CommonDispatchException(把异常相关的信息存到一个结构体) --> KIDispatchException(3环进0环,先保存现场)异常信息存储到了下面这个结构体里面:typedef struct _EXCEPTION_RECORD { DWORD ExceptionCode; //异常代码 DWORD ExceptionFlags; //异常状态 struct _EXCEPTION_RECORD *ExceptionRecord; //下一个异常 PVOID ExceptionAddress; //异常发生地址 DWORD NumberParameters; //附加参数个数 ULONG_PTR ExceptionInformation;//附加参数指针} EXCEPTION_RECORD;ExceptionFlags: CPU产生的异常,这个值是0,软件产生的异常,这里存的值是1_EXCEPTION_RECORD *ExceptionRecord: 通常是空的,出现嵌套异常的情况下,就是这个异常的处理程序执行的时候,又发生异常了,会通过这个指针指向下一个异常。DWORD NumberParameters; //附加参数个数ULONG_PTR ExceptionInformation;//附加参数指针用来进一步描述异常的信息,用的不多。
在上面那个除0异常例子中:CommonDispatchException(它要做的事就事把这些值存到在堆栈中构建的结构体)的反汇编中Mov ebx,:指向的是eip,eip记录的就是异常发生的地址ExceptionAddressMov eax,0C0000094h:0C0000094h代表的是异常的类型,不同的异常有不同的值,这个值是微软定义的。总结:CPU异常执行的流程:1. CPU指令检测到异常2. 查IDT表,执行中断处理程序(它并不会直接处理异常,把机会先留给程序员了)3. 调用CommonDispatchException(构建EXCEPTION_RECORD)4. KIDispatchException(分发异常:目的找到异常处理的函数)模拟异常的产生:CxxThrowException --> (KERNEL32.DLL)RaiseException(DWORD dwExceptionCode,DWORD dwExceptionFlags,DWORD nNumberOfArguments,const ULONG_PTR *lpArfuments) --> NTDLL.DLL!RtlRaiseException()-->NT!NtRaiseException -->NT!KiRaiseException
(KERNEL32.DLL)RaiseException分析:1.将参数中的值填充到EXCEPTION_RECORD这个结构体中typedef struct _EXCEPTION_RECORD { DWORD ExceptionCode; //异常代码 DWORD ExceptionFlags; //异常状态 struct _EXCEPTION_RECORD *ExceptionRecord; //下一个异常 PVOID ExceptionAddress; //异常发生地址 DWORD NumberParameters; //附加参数个数 ULONG_PTR ExceptionInformation;//附加参数指针} EXCEPTION_RECORD;与CPU异常产生流程的两点不同:1. CPU中ExceptionCode每种不同类型的异常,都对应不同的32位的值。软件模拟异常中的ExceptionCode 和当前的编译环境有关。相同编译环境下的值也是相同的。2. CPU中ExceptionAddress异常会记录异常的位置,记录的是真正的异常时哪里发生的。软件模拟异常中的ExceptionAddress 存储的是一个固定的值,而这个值是RaiseException 这个函数的地址。KiRaiseException分析:1.EXCEPTION_RECORD.ExceptionCode 最高位清0(目的是区分CPU异常与软件模拟异常)2.调用KIDispatchException ,开始分发异常 总结:异常类型不同,仅仅是异常记录过程不同,异常进入分发阶段,就完全相同了CPU异常 软件模拟异常 | |查IDT表,执行中断处理函数 CxxThrowException| |CommonDispatchException (KERNEL32.DLL)RaiseException(填充ExceptionRecord结构体) (填充ExceptionRecord结构体) | | | NTDLL.DLL!RtlRaiseException() | | | NT!NtRaiseException | | | NT!KiRaiseException | ExceptionCode 最高位清0 \ /-------------------------------------/ \ / \ / \ / \ / \ / \ / \/ KIDispatchException ,开始分发异常
每天都有1次免费给楼主评分送学币的机会!
页:
[1]