]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
x86: print which shared library/executable faulted in segfault etc. messages v3
authorAndi Kleen <ak@suse.de>
Wed, 30 Jan 2008 12:33:18 +0000 (13:33 +0100)
committerIngo Molnar <mingo@elte.hu>
Wed, 30 Jan 2008 12:33:18 +0000 (13:33 +0100)
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>
arch/x86/kernel/signal_32.c
arch/x86/kernel/signal_64.c
arch/x86/kernel/traps_32.c
arch/x86/kernel/traps_64.c
arch/x86/mm/fault_32.c
arch/x86/mm/fault_64.c
include/linux/mm.h
mm/memory.c

index 74df55895c8ce8aa3496b7b783ddc88e1191d0f4..89a690edf999b783f8fb1e6588954002f2024524 100644 (file)
@@ -198,12 +198,15 @@ asmlinkage int sys_sigreturn(unsigned long __unused)
        return ax;
 
 badframe:
-       if (show_unhandled_signals && printk_ratelimit())
+       if (show_unhandled_signals && printk_ratelimit()) {
                printk("%s%s[%d] bad frame in sigreturn frame:%p ip:%lx"
-                      " sp:%lx oeax:%lx\n",
+                      " sp:%lx oeax:%lx",
                    task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG,
                    current->comm, task_pid_nr(current), frame, regs->ip,
                    regs->sp, regs->orig_ax);
+               print_vma_addr(" in ", regs->ip);
+               printk("\n");
+       }
 
        force_sig(SIGSEGV, current);
        return 0;
index 4eb751c603900f90694b9fd97a346b7d9263934e..7347bb14e306bb3ff66385beee9cc1e5c6a15113 100644 (file)
@@ -484,9 +484,12 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
 void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
 { 
        struct task_struct *me = current; 
-       if (show_unhandled_signals && printk_ratelimit())
-               printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx\n",
+       if (show_unhandled_signals && printk_ratelimit()) {
+               printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx",
               me->comm,me->pid,where,frame,regs->ip,regs->sp,regs->orig_ax);
+               print_vma_addr(" in ", regs->ip);
+               printk("\n");
+       }
 
        force_sig(SIGSEGV, me); 
 } 
index 6f3bb287c7026064246617df58baed21a340fe86..270cfd483160e96834569fa6fe8845c24ac71d80 100644 (file)
@@ -609,11 +609,14 @@ void __kprobes do_general_protection(struct pt_regs * regs,
        current->thread.error_code = error_code;
        current->thread.trap_no = 13;
        if (show_unhandled_signals && unhandled_signal(current, SIGSEGV) &&
-           printk_ratelimit())
+           printk_ratelimit()) {
                printk(KERN_INFO
-                   "%s[%d] general protection ip:%lx sp:%lx error:%lx\n",
+                   "%s[%d] general protection ip:%lx sp:%lx error:%lx",
                    current->comm, task_pid_nr(current),
                    regs->ip, regs->sp, error_code);
+               print_vma_addr(" in ", regs->ip);
+               printk("\n");
+       }
 
        force_sig(SIGSEGV, current);
        return;
index 814801f4eb9e73d0d22dedeb93319a22cfcd8975..911ed28afff86d7ba4936871f2536868e3e3ba2b 100644 (file)
@@ -642,11 +642,14 @@ static void __kprobes do_trap(int trapnr, int signr, char *str,
                tsk->thread.trap_no = trapnr;
 
                if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
-                   printk_ratelimit())
+                   printk_ratelimit()) {
                        printk(KERN_INFO
-                              "%s[%d] trap %s ip:%lx sp:%lx error:%lx\n",
+                              "%s[%d] trap %s ip:%lx sp:%lx error:%lx",
                               tsk->comm, tsk->pid, str,
                               regs->ip, regs->sp, error_code);
+                       print_vma_addr(" in ", regs->ip);
+                       printk("\n");
+               }
 
                if (info)
                        force_sig_info(signr, info, tsk);
@@ -741,11 +744,14 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
                tsk->thread.trap_no = 13;
 
                if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
-                   printk_ratelimit())
+                   printk_ratelimit()) {
                        printk(KERN_INFO
-                      "%s[%d] general protection ip:%lx sp:%lx error:%lx\n",
+                      "%s[%d] general protection ip:%lx sp:%lx error:%lx",
                               tsk->comm, tsk->pid,
                               regs->ip, regs->sp, error_code);
+                       print_vma_addr(" in ", regs->ip);
+                       printk("\n");
+               }
 
                force_sig(SIGSEGV, tsk);
                return;
index 13d295506a1764ce7ec8a2aaca2246678de0dc5e..276863dc4bdd45b88ee266b96f0046d98ea875af 100644 (file)
@@ -514,11 +514,13 @@ bad_area_nosemaphore:
 #ifdef CONFIG_X86_32
                        "%s%s[%d]: segfault at %lx ip %08lx sp %08lx error %lx",
 #else
-                       "%s%s[%d]: segfault at %lx ip %lx sp %lx error %lx\n",
+                       "%s%s[%d]: segfault at %lx ip %lx sp %lx error %lx",
 #endif
                        task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
                        tsk->comm, task_pid_nr(tsk), address, regs->ip,
                        regs->sp, error_code);
+                       print_vma_addr(" in ", regs->ip);
+                       printk("\n");
                }
                tsk->thread.cr2 = address;
                /* Kernel addresses are always protection faults */
index b606bdefbb7295233db7e763770989988e0c3c8b..9ef0306efe9ef0023383525da351805b8dc575d0 100644 (file)
@@ -552,11 +552,13 @@ bad_area_nosemaphore:
 #ifdef CONFIG_X86_32
                        "%s%s[%d]: segfault at %lx ip %08lx sp %08lx error %lx",
 #else
-                       "%s%s[%d]: segfault at %lx ip %lx sp %lx error %lx\n",
+                       "%s%s[%d]: segfault at %lx ip %lx sp %lx error %lx",
 #endif
                        task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
                        tsk->comm, task_pid_nr(tsk), address, regs->ip,
                        regs->sp, error_code);
+                       print_vma_addr(" in ", regs->ip);
+                       printk("\n");
                }
 
                tsk->thread.cr2 = address;
index 1897ca223eca99c402523994c04e64287b769cbd..3c22d971afa78576db7a96597fe518a33b07e985 100644 (file)
@@ -1146,6 +1146,7 @@ extern int randomize_va_space;
 #endif
 
 const char * arch_vma_name(struct vm_area_struct *vma);
+void print_vma_addr(char *prefix, unsigned long rip);
 
 struct page *sparse_mem_map_populate(unsigned long pnum, int nid);
 pgd_t *vmemmap_pgd_populate(unsigned long addr, int node);
index 673ebbf499c75860286c107bb20406d952524aad..d902d0e25edc564862605d2c8c93209602e797cc 100644 (file)
@@ -2754,3 +2754,34 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
 
        return buf - old_buf;
 }
+
+/*
+ * Print the name of a VMA.
+ */
+void print_vma_addr(char *prefix, unsigned long ip)
+{
+       struct mm_struct *mm = current->mm;
+       struct vm_area_struct *vma;
+
+       down_read(&mm->mmap_sem);
+       vma = find_vma(mm, ip);
+       if (vma && vma->vm_file) {
+               struct file *f = vma->vm_file;
+               char *buf = (char *)__get_free_page(GFP_KERNEL);
+               if (buf) {
+                       char *p, *s;
+
+                       p = d_path(f->f_dentry, f->f_vfsmnt, buf, PAGE_SIZE);
+                       if (IS_ERR(p))
+                               p = "?";
+                       s = strrchr(p, '/');
+                       if (s)
+                               p = s+1;
+                       printk("%s%s[%lx+%lx]", prefix, p,
+                                       vma->vm_start,
+                                       vma->vm_end - vma->vm_start);
+                       free_page((unsigned long)buf);
+               }
+       }
+       up_read(&current->mm->mmap_sem);
+}