aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2008-01-30 07:33:18 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:33:18 -0500
commit03252919b79891063cf99145612360efbdf9500b (patch)
treea80dc0c89448308d75d247446a5a04c84cb708a6
parentd3432896dae72ee97deb850ad7bbc30329d32c0d (diff)
x86: print which shared library/executable faulted in segfault etc. messages v3
They now look like: hal-resmgr[13791]: segfault at 3c rip 2b9c8caec182 rsp 7fff1e825d30 error 4 in libacl.so.1.1.0[2b9c8caea000+6000] This makes it easier to pinpoint bugs to specific libraries. And printing the offset into a mapping also always allows to find the correct fault point in a library even with randomized mappings. Previously there was no way to actually find the correct code address inside the randomized mapping. Relies on earlier patch to shorten the printk formats. They are often now longer than 80 characters, but I think that's worth it. [includes fix from Eric Dumazet to check d_path error value] Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/x86/kernel/signal_32.c7
-rw-r--r--arch/x86/kernel/signal_64.c7
-rw-r--r--arch/x86/kernel/traps_32.c7
-rw-r--r--arch/x86/kernel/traps_64.c14
-rw-r--r--arch/x86/mm/fault_32.c4
-rw-r--r--arch/x86/mm/fault_64.c4
-rw-r--r--include/linux/mm.h1
-rw-r--r--mm/memory.c31
8 files changed, 63 insertions, 12 deletions
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c
index 74df55895c8c..89a690edf999 100644
--- a/arch/x86/kernel/signal_32.c
+++ b/arch/x86/kernel/signal_32.c
@@ -198,12 +198,15 @@ asmlinkage int sys_sigreturn(unsigned long __unused)
198 return ax; 198 return ax;
199 199
200badframe: 200badframe:
201 if (show_unhandled_signals && printk_ratelimit()) 201 if (show_unhandled_signals && printk_ratelimit()) {
202 printk("%s%s[%d] bad frame in sigreturn frame:%p ip:%lx" 202 printk("%s%s[%d] bad frame in sigreturn frame:%p ip:%lx"
203 " sp:%lx oeax:%lx\n", 203 " sp:%lx oeax:%lx",
204 task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG, 204 task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG,
205 current->comm, task_pid_nr(current), frame, regs->ip, 205 current->comm, task_pid_nr(current), frame, regs->ip,
206 regs->sp, regs->orig_ax); 206 regs->sp, regs->orig_ax);
207 print_vma_addr(" in ", regs->ip);
208 printk("\n");
209 }
207 210
208 force_sig(SIGSEGV, current); 211 force_sig(SIGSEGV, current);
209 return 0; 212 return 0;
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
index 4eb751c60390..7347bb14e306 100644
--- a/arch/x86/kernel/signal_64.c
+++ b/arch/x86/kernel/signal_64.c
@@ -484,9 +484,12 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
484void signal_fault(struct pt_regs *regs, void __user *frame, char *where) 484void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
485{ 485{
486 struct task_struct *me = current; 486 struct task_struct *me = current;
487 if (show_unhandled_signals && printk_ratelimit()) 487 if (show_unhandled_signals && printk_ratelimit()) {
488 printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx\n", 488 printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx",
489 me->comm,me->pid,where,frame,regs->ip,regs->sp,regs->orig_ax); 489 me->comm,me->pid,where,frame,regs->ip,regs->sp,regs->orig_ax);
490 print_vma_addr(" in ", regs->ip);
491 printk("\n");
492 }
490 493
491 force_sig(SIGSEGV, me); 494 force_sig(SIGSEGV, me);
492} 495}
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
index 6f3bb287c702..270cfd483160 100644
--- a/arch/x86/kernel/traps_32.c
+++ b/arch/x86/kernel/traps_32.c
@@ -609,11 +609,14 @@ void __kprobes do_general_protection(struct pt_regs * regs,
609 current->thread.error_code = error_code; 609 current->thread.error_code = error_code;
610 current->thread.trap_no = 13; 610 current->thread.trap_no = 13;
611 if (show_unhandled_signals && unhandled_signal(current, SIGSEGV) && 611 if (show_unhandled_signals && unhandled_signal(current, SIGSEGV) &&
612 printk_ratelimit()) 612 printk_ratelimit()) {
613 printk(KERN_INFO 613 printk(KERN_INFO
614 "%s[%d] general protection ip:%lx sp:%lx error:%lx\n", 614 "%s[%d] general protection ip:%lx sp:%lx error:%lx",
615 current->comm, task_pid_nr(current), 615 current->comm, task_pid_nr(current),
616 regs->ip, regs->sp, error_code); 616 regs->ip, regs->sp, error_code);
617 print_vma_addr(" in ", regs->ip);
618 printk("\n");
619 }
617 620
618 force_sig(SIGSEGV, current); 621 force_sig(SIGSEGV, current);
619 return; 622 return;
diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c
index 814801f4eb9e..911ed28afff8 100644
--- a/arch/x86/kernel/traps_64.c
+++ b/arch/x86/kernel/traps_64.c
@@ -642,11 +642,14 @@ static void __kprobes do_trap(int trapnr, int signr, char *str,
642 tsk->thread.trap_no = trapnr; 642 tsk->thread.trap_no = trapnr;
643 643
644 if (show_unhandled_signals && unhandled_signal(tsk, signr) && 644 if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
645 printk_ratelimit()) 645 printk_ratelimit()) {
646 printk(KERN_INFO 646 printk(KERN_INFO
647 "%s[%d] trap %s ip:%lx sp:%lx error:%lx\n", 647 "%s[%d] trap %s ip:%lx sp:%lx error:%lx",
648 tsk->comm, tsk->pid, str, 648 tsk->comm, tsk->pid, str,
649 regs->ip, regs->sp, error_code); 649 regs->ip, regs->sp, error_code);
650 print_vma_addr(" in ", regs->ip);
651 printk("\n");
652 }
650 653
651 if (info) 654 if (info)
652 force_sig_info(signr, info, tsk); 655 force_sig_info(signr, info, tsk);
@@ -741,11 +744,14 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
741 tsk->thread.trap_no = 13; 744 tsk->thread.trap_no = 13;
742 745
743 if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) && 746 if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
744 printk_ratelimit()) 747 printk_ratelimit()) {
745 printk(KERN_INFO 748 printk(KERN_INFO
746 "%s[%d] general protection ip:%lx sp:%lx error:%lx\n", 749 "%s[%d] general protection ip:%lx sp:%lx error:%lx",
747 tsk->comm, tsk->pid, 750 tsk->comm, tsk->pid,
748 regs->ip, regs->sp, error_code); 751 regs->ip, regs->sp, error_code);
752 print_vma_addr(" in ", regs->ip);
753 printk("\n");
754 }
749 755
750 force_sig(SIGSEGV, tsk); 756 force_sig(SIGSEGV, tsk);
751 return; 757 return;
diff --git a/arch/x86/mm/fault_32.c b/arch/x86/mm/fault_32.c
index 13d295506a17..276863dc4bdd 100644
--- a/arch/x86/mm/fault_32.c
+++ b/arch/x86/mm/fault_32.c
@@ -514,11 +514,13 @@ bad_area_nosemaphore:
514#ifdef CONFIG_X86_32 514#ifdef CONFIG_X86_32
515 "%s%s[%d]: segfault at %lx ip %08lx sp %08lx error %lx", 515 "%s%s[%d]: segfault at %lx ip %08lx sp %08lx error %lx",
516#else 516#else
517 "%s%s[%d]: segfault at %lx ip %lx sp %lx error %lx\n", 517 "%s%s[%d]: segfault at %lx ip %lx sp %lx error %lx",
518#endif 518#endif
519 task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, 519 task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
520 tsk->comm, task_pid_nr(tsk), address, regs->ip, 520 tsk->comm, task_pid_nr(tsk), address, regs->ip,
521 regs->sp, error_code); 521 regs->sp, error_code);
522 print_vma_addr(" in ", regs->ip);
523 printk("\n");
522 } 524 }
523 tsk->thread.cr2 = address; 525 tsk->thread.cr2 = address;
524 /* Kernel addresses are always protection faults */ 526 /* Kernel addresses are always protection faults */
diff --git a/arch/x86/mm/fault_64.c b/arch/x86/mm/fault_64.c
index b606bdefbb72..9ef0306efe9e 100644
--- a/arch/x86/mm/fault_64.c
+++ b/arch/x86/mm/fault_64.c
@@ -552,11 +552,13 @@ bad_area_nosemaphore:
552#ifdef CONFIG_X86_32 552#ifdef CONFIG_X86_32
553 "%s%s[%d]: segfault at %lx ip %08lx sp %08lx error %lx", 553 "%s%s[%d]: segfault at %lx ip %08lx sp %08lx error %lx",
554#else 554#else
555 "%s%s[%d]: segfault at %lx ip %lx sp %lx error %lx\n", 555 "%s%s[%d]: segfault at %lx ip %lx sp %lx error %lx",
556#endif 556#endif
557 task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, 557 task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
558 tsk->comm, task_pid_nr(tsk), address, regs->ip, 558 tsk->comm, task_pid_nr(tsk), address, regs->ip,
559 regs->sp, error_code); 559 regs->sp, error_code);
560 print_vma_addr(" in ", regs->ip);
561 printk("\n");
560 } 562 }
561 563
562 tsk->thread.cr2 = address; 564 tsk->thread.cr2 = address;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 1897ca223eca..3c22d971afa7 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1146,6 +1146,7 @@ extern int randomize_va_space;
1146#endif 1146#endif
1147 1147
1148const char * arch_vma_name(struct vm_area_struct *vma); 1148const char * arch_vma_name(struct vm_area_struct *vma);
1149void print_vma_addr(char *prefix, unsigned long rip);
1149 1150
1150struct page *sparse_mem_map_populate(unsigned long pnum, int nid); 1151struct page *sparse_mem_map_populate(unsigned long pnum, int nid);
1151pgd_t *vmemmap_pgd_populate(unsigned long addr, int node); 1152pgd_t *vmemmap_pgd_populate(unsigned long addr, int node);
diff --git a/mm/memory.c b/mm/memory.c
index 673ebbf499c7..d902d0e25edc 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2754,3 +2754,34 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
2754 2754
2755 return buf - old_buf; 2755 return buf - old_buf;
2756} 2756}
2757
2758/*
2759 * Print the name of a VMA.
2760 */
2761void print_vma_addr(char *prefix, unsigned long ip)
2762{
2763 struct mm_struct *mm = current->mm;
2764 struct vm_area_struct *vma;
2765
2766 down_read(&mm->mmap_sem);
2767 vma = find_vma(mm, ip);
2768 if (vma && vma->vm_file) {
2769 struct file *f = vma->vm_file;
2770 char *buf = (char *)__get_free_page(GFP_KERNEL);
2771 if (buf) {
2772 char *p, *s;
2773
2774 p = d_path(f->f_dentry, f->f_vfsmnt, buf, PAGE_SIZE);
2775 if (IS_ERR(p))
2776 p = "?";
2777 s = strrchr(p, '/');
2778 if (s)
2779 p = s+1;
2780 printk("%s%s[%lx+%lx]", prefix, p,
2781 vma->vm_start,
2782 vma->vm_end - vma->vm_start);
2783 free_page((unsigned long)buf);
2784 }
2785 }
2786 up_read(&current->mm->mmap_sem);
2787}