⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pgflt.c

📁 Linux下的类似softice的调试工具
💻 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}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -