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 --- src/plugins/abrt-action-analyze-oops.c | 128 ++++++++++++++------------------- 1 file changed, 53 insertions(+), 75 deletions(-) (limited to 'src/plugins') 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