On Mon, Aug 11, 2008 at 2:37 PM, Wang Yi <leonidwang@xxxxxxxxx> 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 ecartis@xxxxxxxxxxxx Please read the FAQ at http://kernelnewbies.org/FAQ