From 8f350826229717e3bd48dcd6a2f12f6a08b37100 Mon Sep 17 00:00:00 2001 From: Nikola Pajkovsky Date: Tue, 24 May 2011 16:09:46 +0200 Subject: rhzb#707074 abrt dupe detection needs to ignore some parts of kernel traces kernel bt looks like [] __might_sleep+0xeb/0xf0 [] __kmalloc+0x79/0x10d [] __kmalloc+0x79/0x10d [] ? alloc_ioapic_entries+0x27/0x87 [] alloc_ioapic_entries+0x27/0x87 [] lapic_resume+0x3a/0x24d [] ? cpufreq_resume+0x2d/0xac ^ memory skipped ^^^ ^ taken ^^^^^^^^^^ | skipped | skipped parser strip out only functions in the middle of bt and generates hash from top 6 functions Signed-off-by: Nikola Pajkovsky --- examples/oops-same-as-oops4.right | 20 ++++++ examples/oops4.right | 20 ++++++ src/plugins/abrt-action-analyze-oops.c | 128 ++++++++++++++------------------- 3 files changed, 93 insertions(+), 75 deletions(-) create mode 100644 examples/oops-same-as-oops4.right create mode 100644 examples/oops4.right diff --git a/examples/oops-same-as-oops4.right b/examples/oops-same-as-oops4.right new file mode 100644 index 00000000..584e014c --- /dev/null +++ b/examples/oops-same-as-oops4.right @@ -0,0 +1,20 @@ +BUG: sleeping function called from invalid context at mm/slub.c:795 +in_atomic(): 0, irqs_disabled(): 1, pid: 8811, name: pm-hibernate +Pid: 8811, comm: pm-hibernate Tainted: P 2.6.38.5-24.fc15.x86_64 #1 +Call Trace: + [] __might_sleep+0xeb/0xf0 + [] __kmalloc+0x79/0x10d + [] ? alloc_ioapic_entries+0x27/0x87 + [] alloc_ioapic_entries+0x27/0x87 + [] lapic_resume+0x3a/0x24d + [] ? cpufreq_resume+0x2d/0xac + [] __sysdev_resume+0x22/0xc2 + [] sysdev_resume+0xb3/0xf8 + [] hibernation_snapshot+0x182/0x23e + [] hibernate+0xc0/0x1b1 + [] state_store+0x5c/0xc5 + [] kobj_attr_store+0x17/0x19 + [] sysfs_write_file+0x111/0x14d + [] vfs_write+0xac/0xf3 + [] sys_write+0x4a/0x6e + [] system_call_fastpath+0x16/0x1b diff --git a/examples/oops4.right b/examples/oops4.right new file mode 100644 index 00000000..cb138c64 --- /dev/null +++ b/examples/oops4.right @@ -0,0 +1,20 @@ +BUG: sleeping function called from invalid context at mm/slub.c:795 +in_atomic(): 0, irqs_disabled(): 1, pid: 13398, name: pm-suspend +Pid: 13398, comm: pm-suspend Not tainted 2.6.38.6-27.fc15.x86_64 #1 +Call Trace: + [] __might_sleep+0xeb/0xf0 + [] __kmalloc+0x79/0x10d + [] ? alloc_ioapic_entries+0x27/0x87 + [] alloc_ioapic_entries+0x27/0x87 + [] lapic_resume+0x3a/0x24d + [] ? cpufreq_resume+0x2d/0xac + [] __sysdev_resume+0x22/0xc2 + [] sysdev_resume+0xb3/0xf8 + [] suspend_devices_and_enter+0x149/0x1d6 + [] enter_state+0xd7/0x129 + [] state_store+0xaf/0xc5 + [] kobj_attr_store+0x17/0x19 + [] sysfs_write_file+0x111/0x14d + [] vfs_write+0xac/0xf3 + [] sys_write+0x4a/0x6e + [] system_call_fastpath+0x16/0x1b diff --git a/src/plugins/abrt-action-analyze-oops.c b/src/plugins/abrt-action-analyze-oops.c index 02ba3e96..33c65000 100644 --- a/src/plugins/abrt-action-analyze-oops.c +++ b/src/plugins/abrt-action-analyze-oops.c @@ -21,10 +21,55 @@ static void hash_oops_str(char hash_str[SHA1_RESULT_LEN*2 + 1], char *oops_buf, const char *oops_ptr) { - unsigned char old_c; - unsigned char c = 0; + // Example of call trace part of oops: + // Call Trace: + // [] ? radeon_cp_resume+0x7d/0xbc [radeon] + // [] ? drm_ioctl+0x1b0/0x225 [drm] + // [] ? radeon_cp_resume+0x0/0xbc [radeon] + // [] ? vfs_ioctl+0x50/0x69 + // [] ? do_vfs_ioctl+0x23b/0x247 + // [] ? audit_syscall_entry+0xf9/0x123 + // [] ? sys_ioctl+0x40/0x5c + // [] ? syscall_call+0x7/0xb + struct strbuf *kernel_bt = strbuf_new(); + char *call_trace = strstr(oops_buf, "Call Trace"); + if (call_trace) + { + call_trace += sizeof("Call Trace\n"); + char *end_line = strchr(call_trace, '\n'); + int i = 0; + while (end_line) + { + char *line = xstrndup(call_trace, end_line - call_trace); + + char *p = skip_whitespace(line); + char *end_mem_block = strchr(p, ' '); + if (!end_mem_block) + error_msg_and_die("no [] mark"); + + end_mem_block = skip_whitespace(end_mem_block); - char *dst = oops_buf; + /* +1 for '?' and +1 for space after '?' == +2*/ + if (end_mem_block && *end_mem_block == '?') + end_mem_block += 2; + + /* strip out offset +off/len */ + char *begin_off_len = strchr(end_mem_block, '+'); + if (!begin_off_len) + error_msg_and_die("no +offset/len at the end of bt"); + + char *function = xstrndup(end_mem_block, begin_off_len - end_mem_block); + strbuf_append_strf(kernel_bt, "%s\n", function); + free(line); + if (i == 5) + break; + + ++i; + call_trace += end_line - call_trace + 1; + end_line = strchr(call_trace, '\n'); + } + goto gen_hash; + } /* Special-case: if the first line is of form: * WARNING: at net/wireless/core.c:614 wdev_cleanup_work+0xe9/0x120 [cfg80211]() (Not tainted) @@ -39,88 +84,21 @@ static void hash_oops_str(char hash_str[SHA1_RESULT_LEN*2 + 1], char *oops_buf, p = strchrnul(p + 1, ' '); /* skip function_name+0xNN/0xNNN */ oops_ptr += sizeof("WARNING: at ")-1; while (oops_ptr < p) - { - *dst++ = *oops_ptr++; - } - goto gen_hash; - } - } - - while (1) - { - old_c = c; - c = *oops_ptr++; - if (!c) - break; - if (c == '\n') - { - // Exclude some lines which have process name - in some oops classes - // process name is irrelevant and changes with every oops. - // Lines we filter out: - // Pid: 8003, comm: Xorg Not tainted (2.6.27.9-159.fc10.i686 #1) - // Process Xorg (pid: 8003, ti=f0a0c000 task=f2380000 task.ti=f0a0c000) - if (strncmp(oops_ptr, "Pid: ", 5) == 0 - || strncmp(oops_ptr, "Process ", 8) == 0 - ) { - while (*oops_ptr && *oops_ptr != '\n') - oops_ptr++; - continue; - } - } - if (!isalnum(old_c)) - { - if (c >= '0' && c <= '9') - { - // Convert all (possibly hex) numbers to just one '0' - if (c == '0' && *oops_ptr == 'x') // "0xSOMETHING" - oops_ptr++; - while (isxdigit(*oops_ptr)) - oops_ptr++; - c = '0'; - } - else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') - { - // This *may be* a hex number without 0x prefix: "f0a0c000" - // Check that it indeed is, and replace with '0' - const char *oops_ptr2 = oops_ptr; - while (isxdigit(*oops_ptr2)) - oops_ptr2++; - // Does it end in a letter which is not a hex digit? - // (Example: "abcw" is not a hex number, "abc " is) - if (!isalpha(*oops_ptr2)) - { - // It's "abc " case. Skip the "abc" string - oops_ptr = oops_ptr2; - c = '0'; - } - // else: hash the string as-is - } + strbuf_append_char(kernel_bt, *oops_ptr++); } - // TODO: Drop call trace tail - in interrupt-driven oopses, - // everything before interrupt is irrelevant. - // Example of call trace part of oops: - // Call Trace: - // [] ? radeon_cp_resume+0x7d/0xbc [radeon] - // [] ? drm_ioctl+0x1b0/0x225 [drm] - // [] ? radeon_cp_resume+0x0/0xbc [radeon] - // [] ? vfs_ioctl+0x50/0x69 - // [] ? do_vfs_ioctl+0x23b/0x247 - // [] ? audit_syscall_entry+0xf9/0x123 - // [] ? sys_ioctl+0x40/0x5c - // [] ? syscall_call+0x7/0xb - - *dst++ = c; } - gen_hash: ; +gen_hash: ; char hash_bytes[SHA1_RESULT_LEN]; sha1_ctx_t sha1ctx; sha1_begin(&sha1ctx); - sha1_hash(&sha1ctx, oops_buf, dst - oops_buf); + sha1_hash(&sha1ctx, kernel_bt->buf, kernel_bt->len); sha1_end(&sha1ctx, hash_bytes); + strbuf_free(kernel_bt); bin2hex(hash_str, hash_bytes, SHA1_RESULT_LEN)[0] = '\0'; + VERB3 log("hash: %s", hash_str); } int main(int argc, char **argv) -- cgit