On Mon, Aug 11, 2008 at 2:37 PM, Wang Yi <[EMAIL PROTECTED]> wrote:
> Hi, all!
> I'd like to know some details about segmentation fault.
> What I mean is when a program accesses invalid memory area, it will
> get a SIGSEGV signal from kernel, and a message "Segmentation fault".
> I also find that dmesg can show we some details like this:
> ProgramName[Pid]: segfault at xxxx eip xxxx esp xxxx error x
> It is useful and provides the first-step information for further
> debug/analysis.
> My question is how dmesg gets the information, and if there are any
> programmable interfaces we can call to get this. (e.g. we
> can write sig handler for a program to print this message and maybe do
> some auto analysis)
> Thank you.
> Leo
The decent ways u are looking for, is to look at how segmentation
fault is handled, ie do_page_fault() function:
(the following error_code documentation is fantastic - 2.6.20 kernel,
but the latest linus git tree for 2.6.26 is completely missing in this
aspect).
/*
* This routine handles page faults. It determines the address,
* and the problem, and then passes it off to one of the appropriate
* routines.
*
* error_code:
* bit 0 == 0 means no page found, 1 means protection fault
* bit 1 == 0 means read, 1 means write
* bit 2 == 0 means kernel, 1 means user-mode
* bit 3 == 1 means use of reserved bit detected
* bit 4 == 1 means fault was an instruction fetch
*/
fastcall void __kprobes do_page_fault(struct pt_regs *regs,
unsigned long error_code)
{
/* get the address */
address = read_cr2();====> from the CR2 register, u get the
address where it faulted. And then further down below the same
function:
printk(" at virtual address %08lx\n",address);
printk(KERN_ALERT " printing eip:\n");
printk("%08lx\n", regs->eip);
}
page = read_cr3();
page = ((unsigned long *) __va(page))[address >> 22];
if (oops_may_print())
printk(KERN_ALERT "*pde = %08lx\n", page);
here u can get the EIP (which is the currently to-be-executed
instruction) and page information from cr3 etc.
These information are arch-specific: register values etc.
And also looking at mm/page_alloc.c:bad_page() (which implement the
arch-independent part):
static void bad_page(struct page *page)
{
printk(KERN_EMERG "Bad page state in process '%s'\n"
KERN_EMERG "page:%p flags:0x%0*lx mapping:%p
mapcount:%d count:%d\n"
KERN_EMERG "Trying to fix it up, but a reboot is needed\n"
KERN_EMERG "Backtrace:\n",
current->comm, page, (int)(2*sizeof(unsigned long)),
(unsigned long)page->flags, page->mapping,
page_mapcount(page), page_count(page));
dump_stack();
page->flags &= ~(1 << PG_lru |
1 << PG_private |
1 << PG_locked |
1 << PG_active |
1 << PG_dirty |
1 << PG_reclaim |
1 << PG_slab |
1 << PG_swapcache |
1 << PG_writeback |
1 << PG_buddy );
set_page_count(page, 0);
reset_page_mapcount(page);
page->mapping = NULL;
add_taint(TAINT_BAD_PAGE);
}
as u can see, accessing global variable like "current" should solve
some of your queries....but there may be other global variables u can
use to get the info - just grep for LIST_HEAD in mm/*.c, or
EXPORT_SYMBOL mm/*.c. Many ways.....
--
Regards,
Peter Teoh
--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to [EMAIL PROTECTED]
Please read the FAQ at http://kernelnewbies.org/FAQ