?? pgflt.c
字號:
/****************************************************************************** * * Copyright (c) 2003 Gerhard W. Gruber * * PROJECT: pICE * $Source: /cvsroot/pice/pice/module/pgflt.c,v $ * $Revision: 1.5 $ * $Date: 2004/02/17 23:07:37 $ * $Author: lightweave $ * $Name: $ * * $Log: pgflt.c,v $ * Revision 1.5 2004/02/17 23:07:37 lightweave * * Improved the DEBUG facillity and replaced the configuration handler with a * new code which now can read MS Windows INI style files. See CHANGES.txt for * more details. * Also added a macro which prevents compiling for kernels before 2.4.19. * * Revision 1.4 2003/06/18 22:00:22 lightweave * DEBUG and DEBUG_SERIAL added * * *****************************************************************************/static char *ident = "$Header: /cvsroot/pice/pice/module/pgflt.c,v 1.5 2004/02/17 23:07:37 lightweave Exp $";/*++Copyright (c) 1998-2001 Klaus P. GerlicherModule Name: pgflt.cAbstract: page fault handling on x86Environment: Kernel mode onlyAuthor: Klaus P. GerlicherRevision History: 25-Nov-1999: created 15-Nov-2000: general cleanup of source filesCopyright notice: This file may be distributed under the terms of the GNU Public License.--*/////////////////////////////////////////////////////// INCLUDES////#include "remods.h"#include <asm/io.h>#include <asm/page.h>#include <asm/pgtable.h>#include <linux/fs.h>#include <linux/vmalloc.h>#include <asm/uaccess.h>#include <asm/delay.h>#include <linux/interrupt.h>#include "precomp.h"#include "compat.h"////////////////////////////////////////////////////// DEFINES////#define PAGE_FAULT_VECTOR (0x0E)#if LINUX_VERSION_CODE < 0x020400#define down_read down#define up_read up#endif // LINUX_VERSION_CODE ////////////////////////////////////////////////////// GLOBALS////ULONG ulOldPageFaultHandler=0;BOOLEAN bInPageFaultHandler = FALSE;ULONG (*pice_search_exception_table)(ULONG eip) = NULL;////////////////////////////////////////////////////// FUNCTIONS//////************************************************************************* // HandlePageFault() // // returns:// 0 = let the system handle it// 1 = call DebuggerShell()// 2 = FATAL error inside debugger//************************************************************************* ULONG HandlePageFault(EXCEPTION_FRAME* pFrame){ struct task_struct *tsk; struct mm_struct *mm; struct vm_area_struct * vma; unsigned long address; int write; // get the address touched __asm__("movl %%cr2,%0":"=r" (address)); tsk = current; DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "CR2 = %08lX error = %x (tsk = %p (%s) ulOldPageFaultHandler = %.8X)\n", address, pFrame->error_code, tsk, tsk->comm, ulOldPageFaultHandler);#if LINUX_VERSION_CODE < 0x020400#else if ((address >= TASK_SIZE) && !(pFrame->error_code&5)) { DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "goto vmalloc_fault\n"); goto vmalloc_fault; }#endif mm = tsk->mm; /* * If we're in an interrupt or have no user * context, we must not take the fault.. */ if (in_interrupt() || mm == my_init_mm) { DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "goto no_context\n"); goto no_context; } down_read(&mm->mmap_sem); vma = find_vma(mm, address); if (!vma) { DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "goto bad_area\n"); goto bad_area; } if (vma->vm_start <= address) { DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "goto good_area\n"); goto good_area; } if (!(vma->vm_flags & VM_GROWSDOWN)) { DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "vma doesn't grow down!\n"); goto bad_area; } if (pFrame->error_code & 4) { /* * accessing the stack below %esp is always a bug. * The "+ 32" is there due to some instructions (like * pusha) doing post-decrement on the stack and that * doesn't show up until later.. */ if (address + 32 < pFrame->ring3_esp) { DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "access outside of stack!\n"); goto bad_area; } } if(COMPAT_expand_stack(vma, address)) { DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "stack not expansible!\n"); goto bad_area; }/* * Ok, we have a good vm_area for this memory access, so * we can handle it.. */good_area: write = 0; switch (pFrame->error_code & 3) { default: /* 3: write, present */ /* fall through */ case 2: /* write, not present */ if (!(vma->vm_flags & VM_WRITE)) { DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "write, not present!\n"); goto bad_area; } write++; break; case 1: /* read, present */ DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "read, present!\n"); goto bad_area; case 0: /* read, not present */ if (!(vma->vm_flags & (VM_READ | VM_EXEC))) { DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "read, not present!\n"); goto bad_area; } } /* * If for any reason at all we couldn't handle the fault, * make sure we exit gracefully rather than endlessly redo * the fault. *///survive: DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "survive\n"); // check if there could be a breakpoint installed in the page // only if conditions are: // - usermode caused the fault // - it was a read // - it was due to a not present page if( (pFrame->error_code & 0xF) == 0xC) { DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "checking if page has a virtual SW breakpoint\n"); if(PageSwapInReInstallSWBreakpoints(address)) { DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "page has a virtual SW breakpoint\n"); // modify trace flag so we come back after page has been swapped in pFrame->eflags |= TF_FLAG; // set trace flag (TF) ulSingleStepCondition |= SINGLE_STEP_CONDITION_BREAKPOINT_REINSTALL; } } up_read(&mm->mmap_sem); return 0;/* * Something tried to access memory that isn't in our memory map.. * Fix it, but check if it's kernel or user first.. */bad_area: up_read(&mm->mmap_sem);bad_area_nosemaphore: /* User mode accesses just cause a SIGSEGV */ if (pFrame->error_code & 4) { DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "SIGSEGV!\n"); return 1; }no_context: if(pice_search_exception_table) { /* Are we prepared to handle this kernel fault? */ if (pice_search_exception_table(pFrame->eip) != 0) { return 0; } }/* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. * * First we check if it was the bootup rw-test, though.. */ if (address < PAGE_SIZE) DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "Unable to handle kernel NULL pointer dereference"); else DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "Unable to handle kernel paging request"); return 1;#if LINUX_VERSION_CODE < 0x020400#elsevmalloc_fault: { /* * Synchronize this task's top level page-table * with the 'reference' page table. */ int offset = __pgd_offset(address); pgd_t *pgd, *pgd_k; pmd_t *pmd, *pmd_k; pgd = tsk->active_mm->pgd + offset; pgd_k = init_mm.pgd + offset; if (!pgd_present(*pgd)) { if (!pgd_present(*pgd_k)) { DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "goto bad_area_nosemaphore\n"); goto bad_area_nosemaphore; } return 0; } pmd = pmd_offset(pgd, address); pmd_k = pmd_offset(pgd_k, address); if (pmd_present(*pmd) || !pmd_present(*pmd_k)) { DPRINT(PICE_DEBUG, DBT_PGFLT, DBL_INFO, "goto bad_area_nosemaphore\n"); goto bad_area_nosemaphore; } return 0; }#endif }//************************************************************************* // InstallPageFaultHook() // //************************************************************************* void InstallPageFaultHook(void){#ifdef ACTIVATE_PAGEFAULT_HOOK void DebuggerPageFault(void); ENTER_FUNC(); if(!ulOldPageFaultHandler) { HookInterruptVector(PAGE_FAULT_VECTOR,(PVOID)&DebuggerPageFault,(PVOID)&ulOldPageFaultHandler); } LEAVE_FUNC();#endif // ACTIVATE_PAGEFAULT_HOOK}//************************************************************************* // DeinstallPageFaultHook() // //************************************************************************* void DeinstallPageFaultHook(void){#ifdef ACTIVATE_PAGEFAULT_HOOK ENTER_FUNC(); if(ulOldPageFaultHandler) { HookInterruptVector(PAGE_FAULT_VECTOR,(PVOID)ulOldPageFaultHandler,NULL); } LEAVE_FUNC();#endif // ACTIVATE_PAGEFAULT_HOOK}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -