First, the difference between abnormalities and interruptions. Interrupts can occur at any time, which is independent of what instructions are performing with the CPU, and the interrupt is primarily triggered by hardware such as I / O devices, processor clocks, or timers, which can be allowed or canceled. An exception is due to the CPU executes some instructions, which may include memory access violations, except 0 or specific commissioning instructions, etc., the core also treats system services as an abnormality. Interrupt and abnormal more underlying differences When there is a generalized interrupt (including exception and hardware interrupt), if it is not set in the service register (using the command number 0xB to 8259-1 interrupt controller 0x20 port, used in service register 1) 0xB is read from the 8259-2 interrupt controller 0xA0 port in Service Register 2) related to the service bit (8 bits in the service register, a total of IRQ 0-15), which is an exception of the CPU, otherwise the hardware interrupt .
Below is the definition of the Windows 2000 according to the Intel X86 processor, which registers the previous items in the IDT (different operating systems are different, which gives it different from other materials. Because this is the specific implementation of Windows):
Interrupt number name
0x0 removal error 1, DIV and IDIV instructions except 0
2, division results overflow
0x1 debug trap 1, EFLAG TF position bit
2. Performed to the breakpoint set by the debug register (DR0-DR4)
3. Execute INT 1 instructions
0x2 NMI interrupt positions the NMI input pin of the CPU (this exception is not shielded from hardware)
0x3 breakpoint execution INT 3 instruction
0x4 integer overflow execution of the INTO directive and the position bit
0x5 bound boundary Check error Bound instruction comparison outside of a given range
0x6 invalid operation code instructions cannot be identified
0x7 Coprocessor does not perform any coprocessor instructions when 1, Cr0 EM position bits
2. Environment switching is performed when the coordinator works
0x8 Dual abnormality occurs in another abnormality
0x9 Coprocessor Section Overrower Floating Point Instruction Reference Memory exceeds section
0xA Invalid Task Segment Task Section The descriptor contains invalid (Windows does not use TSS to perform environmental switching, so this exception will have other issues)
The 0xB segment does not have a referenced section to be replaced by memory
0xC Stack error 1, the reference memory exceeds the stack segment limit
2. Add the present position of the descriptor of the SS register 0
0xD General Protection Error All other exception handling routines unable to handle exceptions
0xE page error 1, the address of the accessed is not swapped into memory
2, access operation violation of page protection rules
0x10 Coprocessor error When the EM position bit of CR0 is executed, WAIT or ESCAPE instructions
0x11 Alignment Check error Align check When the ON is open (EFLAG alignment location) Access unlined data
Other exceptions also include obtaining system start-up time services INT 0x2a, user callback int 0x2b, system service int 0x2e, debugging service int 0x2d, etc., is used to implement its own function, all through an abnormal mechanism, triggering method is to perform the corresponding INT instruction.
Here is an important structure in several exception processing:
Trap Frame TrapFrame Structure (The exception frame of the exception frame mentioned later is actually a KTRAP_FRAME structure):
Typedef struct _ktrap_frame {
Ulong DBGEBP;
Ulong dBGEIP;
Ulong dbgargmark;
Ulong DBGARGPOINTER;
Ulong Tempsegcs;
Ulong Tempesp;
Ulong DR0;
Ulong DR1;
Ulong DR2;
Ulong DR3;
Ulong DR6;
Ulong DR7;
Ulong seggs;
Ulong seges;
Ulong segds;
Ulong EDX;
Ulong ECX;
Ulong Eax;
Ulong previouspreviousmode;
PEXCEPTION_REGISTRATION_RECORD EXCEPTIONLIST; ULONG SEGFS;
Ulong EDI;
Ulong ESI;
Ulong EBX;
Ulong EBP;
Ulong errcode;
Ulong EIP;
Ulong segcs;
Ulong EFLAGS;
Ulong hardwareesp;
Ulong hardwaresegss;
Ulong v86es;
Ulong V86DS;
Ulong v86fs;
Ulong V86GS;
KTRAP_FRAME;
Environment Context Structure:
Typedef struct _Context {
Ulong contextflags;
Ulong DR0;
Ulong DR1;
Ulong DR2;
Ulong DR3;
Ulong DR6;
Ulong DR7;
FLOATING_SAVE_Area floatsave;
Ulong seggs;
Ulong segfs;
Ulong seges;
Ulong segds;
Ulong EDI;
Ulong ESI;
Ulong EBX;
Ulong EDX;
Ulong ECX;
Ulong Eax;
Ulong EBP;
Ulong EIP;
Ulong segcs;
Ulong EFLAGS;
Ulong ESP;
Ulong segss;
Uchar extendedRegisters [maximum_supported_extension];
CONTEXT;
Abnormal record ExceptionRecord structure:
Typedef struct _exception_record {
NTSTATUS EXCETIONCODE;
Ulong ExceptionFlags;
Struct_exception_record * exceptionRecord;
PVOID EXCEPTIONADDRESS;
Ulong Numberparameters;
Ulong_ptr exceptioninformatio [eXception_maximum_parameters];
EXCEPTION_RECORD;
When an abnormality occurs, the CPU records the current register state and establishes trap trapframe in the kernel stack, and then controls the control to the corresponding exception trap processing. When the trap handler can handle an exception, such as the page program MMAccessFault, when the page is swapped into physical memory, returns an exception by IRET. But most of them cannot handle exceptions, first call CommondispatChexception to establish exception records ExceptionRecord and exception frame ExceptionFrame in the kernel stack. ExceptionRecord is important, it records exception code, exception addresses, and some additional additional parameters. Then call KidispatChexception for exception assignment. This function is the core function of exception processing under Windows, responsible for abnormal distribution.
KidispatCHException process (whenever the routine processed when the exception is handled by a routine, returns false. When any one of the routines have returned TRUE, KidispatChexception is returned normally ):
Before performing an abnormal assignment of the user-state, the exception is first judged from the user mode. Yes, if the context.contextflags (this time the Context structure is still initialized, it does not assign the initial value) OR on conext_floating_point, means that the right The exception of user mode is always attempts to assign floating point status, which allows an exception handler or debugger to check and modify the status of the coprocessor. Then remove the register value from the trap frame to fill in the context structure, and determine if it is a breakpoint exception (INT 0x3 and INT 0x2D), if so, will first reduce the context.eip to point to int 0x3 instructions (whether it is int 0x3 Or an exception caused by INT 0x2D, since the previous trap handler has changed the EIP in TrapFrame). Then determine that the exception occurs in the kernel mode or user mode, take different processing procedures according to different modes. If an exception occurs in a kernel mode, the first opportunity to the kernel debugger and the second chance to deal with exceptions. When an exception is processed, the trap frame will be set and returned to the trap handler, where IRET returns an abnormal place to continue execution.
The kernel mode exception handling process is:
(First Opportunity) Judging whether kidebugroutine is empty, it is not empty to put context, trap frame, abnormal record, abnormal frame, an exception mode, etc., and will be handed over to KidebugRoutine.
|
|
|
If kidebugroutine is empty (normal system is not empty. Normal start-up system kidebugroutine is kdpstub, plus / debug in boot.ini) KidebugRoutine is kdptrap. If you are empty, you can't process DBGPRINT this type of INT 0x2D is abnormal and cause system crash) or kidebugroutine unpredicts an exception, then the Context structure and exception record ExceptionRecord stack and call RTLDispatChexception in the kernel mode to find a frame-based exception handling routine in the kernel stack.
|
|
|
RTLDISPATCHEXCEPTION Call RTLPGETREGISTRATIONHEAD Gets the current thread exception Processing Link Pointer from FS: [0] (0xFFDFF000), and call RTLPGETSTACKLIMITS from 0xffdff004 and 0xFFDFF008 to remove the current thread stack bottom and top. Then start the abnormal processing list pointer traversal chain table to find an exception handling routine (if the VEH processes the VEH again in XP and 2003), this is SEH, but there is a bit different from the user state that has neither a top abnormality processing routine ( Top Level SEH) also has no default exception handling routine. Then check for each current exception handling Lin table pointer to determine if the stack is valid (whether the stack range or is not aligned) and the stack are DPC stack. If DPCROUTINAACTIVE is TRUE, the dpcstack is removed to the True and the pile top and the bottom at the 0xFFDFF81C (a kernel stack size), if the renewal stack top and bottom is DPCSTACK and DPCSTACK-0X3000 and continue processing, otherwise the abnormality record structure ExceptionRecord.ExceptionFlags Setting_stack_INVALID is indicated as an invalid stack and returns false.
|
|
|
When you call an exception handling routine, insert a new node on the exception handling routine, the corresponding exception handling routine is used to handle nested abnormalities, that is, another exception occurs when processing an exception. After processing RTLDISPATCHEXCEPTION, the return value of the exception handling routine:
If ExceptionContinueexecution, if exceptionflags doptinuable does not set an Exception_nonContinuable unrecoverable execution, returns true to the upper layer, otherwise the RTLRAISEEXCEPTION is called RTLRaiseException to the second chance processing section of KidispatChexception. If you exceptionContinueSearch, you will continue to find an exception handling routine.
For ExceptionNestedException, nesting exceptions. Keep the current exception handling Link Pointer is the inner abnormality handling lin list and processes the exception handling routine. When the current exception handling linked list address is greater than the remaining inner abnormality, the current exception handling linked list is the more inner layer of the current exception, because the stack is expanded from high-directions, the higher the address, the more early, indicated In the inner layer), the value is given to the inner abnormality processing linked list pointer, except for the first end value, the inner abnormality processing linked list pointer, which represents the nesting, more than one exception. When searching for a new exception handling Lin table pointer and the reserved inner abnormality handling the linked list pointer, clear the nesting anomalous bit (& (~ Exception_NESTED_CALL)) of ExceptionRecord.exceptionFlags, indicating that the anomaly of the nested has been processed.
All other return values are considered invalid, call RTLRAISEEXCEPTION to return to KidispatChexception to the second chance processing section.
When an exception handling a linked list pointer is 0xffffffFFF, the exception handling routine is in the head.
|
|
|
If RTLDISPATCHEXCEPTION cannot handle exceptions, (Second opportunity) Judging whether kidebugroutine is empty, do not hand it over to KidebugRoutine processing for the flight.
|
|
|
When all the routines cannot handle an exception, call the kebugcheckex blue screen, the error code is kmode_exception_not_handled, and no one has handled an exception, and the system treats this unrecoverable fatal exception. It is completed until this kernel mode is completed.
If an abnormality occurs in user mode, the first opportunity to debug the first chance and the second chance will be debugged. Only because the debugger is a user status initiator, the message is sent to the session manager SMSS.exe via the LPC, and the message is forwarded to the debugger.
User mode exception processing process:
If kidebugroutine is not empty, it is not empty to press the context, trap frame, abnormality record, abnormal frame, an abnormal mode, etc., and hand it over to KidebugRoutine. When the processing is used to set the trap frame with Context and return to the previous routine. (First Opportunity) Otherwise, the exception record is stack and calls DBGKFORWARDEXCEPTION, and the HideFromDebugger member of the current thread Ethread structure is determined in DBGKFORWARDEXCEPTION If the current thread is (to true indicators to the user debugger), the debug port of the current process is (Debugport) Sends an LPC message.
|
|
|
When the last step is unable to handle an exception, set a trap frame in the stack, and the trap frame is set to Ke (i) UseRexceptionDisptcher ((i) means that the symbol of the KE and KI headers of this function is actually one Equal), then return the trap handler, returning a user-state execution by the trap handler IRET (i) UserexceptionDispatcher (this function is a KE (ki) head, but is not a function in the kernel. The same nature has Ke ( i) RaiseUseRexceptionDispatcher, ke (i) UserCallbackDispatcher, ke (i) UserApcdispatcher. Their common feature is not called, but the kernel routine sets trapframe.eip to this function after IRET is performed here). Ke (i) UsexceptionDisptcher calls RTLDISPATCHEXCEPTION (User state) Looking for frame-based exception processing routines in the stack (if the XP and 2003 processes the VEH and then processed SEH), this process should be very familiar, that is, Search SEH Link list If you do not process, you call the top Abnormally SEHS routine. When it is no longer processed, the default exception handling routine is called to terminate the process (which is changed here when there is VC). A bit different is that RTLDISPATCHEXCEPTION under the user state only judges that the return value is ExceptionContinueexecution or ExceptionContinuesearch. If RTLDISPATCHEXCEPTION is found to process an exception, call ZwContinue to continue executing according to the setup structure, otherwise call ZwraiseException, and set the third Boolean parameter to false, indicating that the second opportunity is handled. |
|
|
ZwraiseException passes through a series of calls to call KidispatChexception, since the Boolean firstchance is set to false, directly enter the second opportunity to process in KidispatChexception.
|
|
|
(Second Opportunity) Send a message to the process of DebugPort, if it is unable to process, the EXCEPTIONPORT message of the process (here the same is not visible to the user debugger, it will only be sent to ExceptionPort). The difference between DEBUGPORT and ExceptionPort is that if you send a message to an ExceptionPort, stop the execution of all threads in the target process until the thread returns to the response message, and the message is sent to the DEBUGPORT, and there is no need to stop the thread operation. There is also a message to the session manager, and ExceptionPort is sent to the Win32 subsystem. When sending a message to the ExceptionPort, it is no longer given any chance to the user status debugger :).
|
|
|
When an exception still does not process, terminate the current thread and call the kebugcheckex blue screen, the error code is kmode_exception_not_handled. The exception is completed in this user mode.
One thing to explain is that this only lists the operations of the operating system. If you look at the drive or an application now, join the __TRY / __EXCEPT code, but did not find the exception handling routine corresponding to the node on the SEH and the relationship with yourself. The reason is because the compiler of M is encapsulates SEH's mechanism in the system inside the system. The exception handling routine on the abnormal processing routine chain table node is actually _except_handler3, this function has implemented a mechanism similar to SEH internally, which is to establish a table for each function, including all in this function. The __TRY block corresponds to the corresponding function in the __TRY () parentheses, if the parentheses are exception_execute_handler, the filter exception routine is simply assigned to the corresponding 1, 0 or -1 Then return, corresponding to exception_execute_handler, exception_continue_search, and handption_continue_execute and handle routine pointer (__except {} and address of code in __final {}). Therefore, each called function is registered on the SEH linked list and establishes a table. Like such as Exception_execute_Handler, Exception_Continue_Search, Exception_Continue_execute is actually returned to the return value of _except_handler3 instead of returning to RTLDISPATCHEXCEPTION. It is a bit dizzy, huh, huh. Summarize the process (refer to the complete process of exceptions, if the abnormality is processed from the link from the link to the execution of the original normal program code):
Under core mode:
Kidispatchexception -> (first opportunity) KidebugRoutine-> RTLDISPATCHEXCEPTION Looking for SEH (VEH) -> (Second Opportunity) KidebugRoutine-> Kebugcheckex
User mode:
KidispatChexception-> kidebugroutine -> (first opportunity) Send a message to the process debug port -> RTLDISPATCHEXCEPTION Looking for SEH (VEH) -> ZwraiseException back to KidispatChexception -> (Second Opport) Send Message to Process Debugging or Unusual Port -> KebugCheckex.
It's so simple, huh, huh. For example, an example is to illustrate the abnormal process.
The program is debugged by joining int 0x3 in our program, how is the exception generated by INT 0x3?
If INT 0x3 occurs in kernel mode (in the driver), it is divided into kernel debugger whether it is loaded. When the kernel debugger is not loaded, kidebugroutine (kdpstub) does not process int 0x3 exception, then search for SEH registered by the driver writer in the stack, if there is no processing of INT 0x3 exception, then call the kebugCheckex blue screen, the error code is Kmode_exception_not_handled (no one is working, the system has only sorrowful and angry). If the kernel debugger is loaded, kidebugroutine (kdptrap) can handle int 0x3 exception, and the abnormality is processed to be returned normally. The processing method is to send the current processor status (such as various registers, etc.) to the kernel modulator on the host connected by the serial port, and has been waiting for the kernel debugger to respond, and the system calls a KD function in KDPTRAP. The KdpsendWaitContinue loop is waiting for data from the serial port (kernel debugger and the debugged system through serial port) until the kernel debugger will continue the command, the system can be done from INT 0x3 instructions.
If INT 0x3 occurs in user mode, it is also divided into user debugger loading. When the user debugger is not loaded, KidebugRoutine does not process int 0x3 exception, and the user process has no DEBUGPORT, copy the related structure of the recording exception to the user's stack, the RTLDispatChexception, the user's stack, the SEH in the user's stack. If there is no processing of INT 0x3 abnormalities, the default exception handling routine is called. By default, the process is terminated will occur. If there is a user debugger loading, send the abnormal LPC message to the process of the DEBUGPORT or ExceptionPort and determines the return status of the send function. If the user debugger continues to execute, return Status_Success, the kernel is considered to have resolved continued execution.
It also illustrates this, which is the same error, which occurs in the intra-nuclear state than being fatal under the user state. Other abnormal processing processes are basically the same. A small number of different exceptions are debugprint, debugprompt, load and uninstall Symbol, etc. By calling DebugService (this is actually generated by generating an exception INT 0x2D). It can be processed in KdpStub (the processing is simple, just add the EIP of the Context structure to the current INT 0x2D), and if it is processed in KDPTRAP, it is further interacting with the kernel debugger. For more detailed introduction to KDPSTUB, KDPTRAP, and DebugService, see another article "Analysis of the Principle of Windows Nuclear Trial".
postscript:
I found out that there was a half-year article for a few days ago. At that time, because there were still something that I didn't understand, I didn't finish it, and the result was half a year. Now, I will find a lot after I finish writing, and I also take the experience to give you a reference, it is a throwing jade :)