--- lib/core-backtrace-oops.c | 53 +++++++++++ tests/Makefile.am | 2 +- tests/Makefile.in | 2 +- tests/atlocal.in | 2 +- tests/corebt-oops.at | 228 ++++++++++++++++++++++++++++++++++++++++++++++ tests/testsuite.at | 1 + 6 files changed, 285 insertions(+), 3 deletions(-) create mode 100644 tests/corebt-oops.at
diff --git a/lib/core-backtrace-oops.c b/lib/core-backtrace-oops.c index 98e79c9..58cb79d 100644 --- a/lib/core-backtrace-oops.c +++ b/lib/core-backtrace-oops.c @@ -61,6 +61,57 @@ Modules linked in: ----- END ----- */
+static GList * +normalize_kerneloops(GList *kerneloops) +{ + /* NULL-terminated array of function names to drop */ + const char *blacklist[] = { + "warn_slowpath_common", + "warn_slowpath_null", + "warn_slowpath_fmt", + "warn_slowpath_fmt_taint", + "do_softirq", + "flush_kthread_worker", + "system_call_fastpath", + "kernel_thread_helper", + "gs_change", + "worker_thread", + "do_vfs_ioctl", + "process_one_work", + "kthread", + "irq_exit", + NULL + }; + + GList *next = kerneloops; + + while (next) + { + bool drop = false; + struct backtrace_entry *frame = (struct backtrace_entry *)next->data; + const char **func_cur; + + for (func_cur = blacklist; *func_cur != NULL; func_cur++) + { + if (btp_strcmp0(*func_cur, frame->symbol) == 0) + { + drop = true; + break; + } + } + + next = g_list_next(next); + + if (drop) + { + kerneloops = g_list_remove(kerneloops, frame); + btp_backtrace_entry_free(frame); + } + } + + return kerneloops; +} + GList * btp_parse_kerneloops(char *text, const char *kernelver) { @@ -194,6 +245,8 @@ btp_parse_kerneloops(char *text, const char *kernelver) if (nextline) *(nextline - 1) = '\n';
+ result = normalize_kerneloops(result); + return result; }
diff --git a/tests/Makefile.am b/tests/Makefile.am index d138c84..9e695b7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,4 +1,4 @@ -EXTRA_DIST = backtraces +EXTRA_DIST = backtraces oopses
## ------------ ## ## package.m4. ## diff --git a/tests/Makefile.in b/tests/Makefile.in index 29ec3b2..16f6ae6 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -181,7 +181,7 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -EXTRA_DIST = backtraces package.m4 $(TESTSUITE_AT) $(TESTSUITE) \ +EXTRA_DIST = backtraces oopses package.m4 $(TESTSUITE_AT) $(TESTSUITE) \ atlocal.in TESTSUITE_AT = \ local.at \ diff --git a/tests/atlocal.in b/tests/atlocal.in index 856e5fe..3aaa34a 100644 --- a/tests/atlocal.in +++ b/tests/atlocal.in @@ -6,7 +6,7 @@ CC='@CC@' LIBTOOL="$abs_top_builddir/libtool"
# We want no optimization. -CFLAGS="@O0CFLAGS@ -I$abs_top_builddir -D_GNU_SOURCE" +CFLAGS="@O0CFLAGS@ -I$abs_top_builddir -D_GNU_SOURCE @GLIB_CFLAGS@"
# Are special link options needed? LDFLAGS="@LDFLAGS@ $abs_top_builddir/lib/libbtparser.la" diff --git a/tests/corebt-oops.at b/tests/corebt-oops.at new file mode 100644 index 0000000..2efa040 --- /dev/null +++ b/tests/corebt-oops.at @@ -0,0 +1,228 @@ +# Checking the btparser. -*- Autotest -*- + +AT_BANNER([Core-level backtrace for kerneloops]) + +## --------------------------- ## +## btp_parse_kerneloops_x86_64 ## +## --------------------------- ## + +AT_TESTFUN([btp_parse_kerneloops_x86_64], +[[ +#include <lib/core-backtrace-oops.h> +#include <lib/utils.h> +#include <glib.h> +#include <assert.h> + +char *kver = "3.2.2-1.fc16.x86_64"; +GList *oops = NULL; + +void t(uint64_t addr, char *sym, char *mod) +{ + assert(oops); + struct backtrace_entry *f = oops->data; + + assert(f->address == addr); + assert(strcmp(f->symbol, sym) == 0); + assert(strcmp(f->filename, mod) == 0); + oops = g_list_next(oops); +} + +int main(void) +{ + char *str = btp_file_to_string("../../oopses/oops.x86_64"); + assert(str); + oops = btp_parse_kerneloops(str, kver); + assert(oops); + + t(0xffffffffa03eb6b8, "ath_rc_get_highest_rix", "ath9k"); + t(0xffffffffa03eb88c, "ath_get_rate", "ath9k"); + t(0xffffffff81088610, "insert_work", "vmlinux"); + t(0xffffffffa04e7aa6, "rate_control_get_rate", "mac80211"); + t(0xffffffffa04f389f, "invoke_tx_handlers", "mac80211"); + t(0xffffffffa04d2dac, "sta_info_get", "mac80211"); + t(0xffffffffa04f46d0, "ieee80211_tx", "mac80211"); + t(0xffffffffa04f47b1, "ieee80211_xmit", "mac80211"); + t(0xffffffffa04f4e5f, "ieee80211_subif_start_xmit", "mac80211"); + t(0xffffffff810992f7, "getnstimeofday", "vmlinux"); + t(0xffffffff814d48a2, "dev_hard_start_xmit", "vmlinux"); + t(0xffffffff814f03af, "sch_direct_xmit", "vmlinux"); + t(0xffffffff814d4de4, "dev_queue_xmit", "vmlinux"); + t(0xffffffff814fdf85, "nf_hook_slow", "vmlinux"); + t(0xffffffff8150cec0, "ip_fragment", "vmlinux"); + t(0xffffffff8150d02b, "ip_finish_output", "vmlinux"); + t(0xffffffff8150db88, "ip_output", "vmlinux"); + t(0xffffffff8150d254, "ip_local_out", "vmlinux"); + t(0xffffffff8150d289, "ip_local_out", "vmlinux"); + t(0xffffffff8150d3df, "ip_queue_xmit", "vmlinux"); + t(0xffffffff81524804, "tcp_transmit_skb", "vmlinux"); + t(0xffffffff81525f31, "tcp_retransmit_skb", "vmlinux"); + t(0xffffffff81113056, "perf_event_task_tick", "vmlinux"); + t(0xffffffff8152789d, "tcp_retransmit_timer", "vmlinux"); + t(0xffffffff81527ed8, "tcp_write_timer", "vmlinux"); + t(0xffffffff8107d35b, "run_timer_softirq", "vmlinux"); + t(0xffffffff812bf1d4, "timerqueue_add", "vmlinux"); + t(0xffffffff81527d50, "tcp_retransmit_timer", "vmlinux"); + t(0xffffffff8101b8d3, "native_sched_clock", "vmlinux"); + t(0xffffffff8101b3b9, "read_tsc", "vmlinux"); + t(0xffffffff810a09d4, "tick_program_event", "vmlinux"); + t(0xffffffff815eba2c, "call_softirq", "vmlinux"); + t(0xffffffff815ec3ce, "smp_apic_timer_interrupt", "vmlinux"); + t(0xffffffff815ea29e, "apic_timer_interrupt", "vmlinux"); + t(0xffffffff8130fd2d, "intel_idle", "vmlinux"); + t(0xffffffff8130fd0f, "intel_idle", "vmlinux"); + t(0xffffffff814927f1, "cpuidle_idle_call", "vmlinux"); + t(0xffffffff8101322a, "cpu_idle", "vmlinux"); + t(0xffffffff815d01b6, "start_secondary", "vmlinux"); + assert(oops == NULL); + + return 0; +} +]]) + +## ------------------------- ## +## btp_parse_kerneloops_i386 ## +## ------------------------- ## + +AT_TESTFUN([btp_parse_kerneloops_i386], +[[ +#include <lib/core-backtrace-oops.h> +#include <lib/utils.h> +#include <glib.h> +#include <assert.h> + +char *kver = "3.3.1-3.fc16.i686.PAE"; +GList *oops = NULL; + +void t(uint64_t addr, char *sym) +{ + assert(oops); + struct backtrace_entry *f = oops->data; + + assert(f->address == addr); + assert(strcmp(f->symbol, sym) == 0); + assert(strcmp(f->filename, "vmlinux") == 0); + oops = g_list_next(oops); +} + +int main(void) +{ + char *str = btp_file_to_string("../../oopses/oops.i386"); + assert(str); + oops = btp_parse_kerneloops(str, kver); + assert(oops); + + t(0xc087237a, "dev_watchdog"); + t(0xc087237a, "dev_watchdog"); + t(0xc087237a, "dev_watchdog"); + t(0xc044d410, "tasklet_hi_schedule_first"); + t(0xc0454827, "run_timer_softirq"); + t(0xc0477a2f, "sched_clock_cpu"); + t(0xc08721a0, "qdisc_reset"); + t(0xc044d410, "tasklet_hi_schedule_first"); + t(0xc044d410, "tasklet_hi_schedule_first"); + t(0xc042ea79, "smp_apic_timer_interrupt"); + t(0xc094b865, "apic_timer_interrupt"); + t(0xc0437ee5, "native_safe_halt"); + t(0xc041975c, "default_idle"); + t(0xc0411308, "cpu_idle"); + t(0xc092ac05, "rest_init"); + t(0xc0be278b, "start_kernel"); + t(0xc0be21c5, "loglevel"); + t(0xc0be20ac, "i386_start_kernel"); + assert(oops == NULL); + + return 0; +} +]]) + +## -------------------------- ## +## btp_parse_kerneloops_s390x ## +## -------------------------- ## + +AT_TESTFUN([btp_parse_kerneloops_s390x], +[[ +#include <lib/core-backtrace-oops.h> +#include <lib/utils.h> +#include <glib.h> +#include <assert.h> + +char *kver = "2.6.41.4-1.fc15.s390x"; +GList *oops = NULL; + +void t(uint64_t addr, char *sym) +{ + assert(oops); + struct backtrace_entry *f = oops->data; + + assert(f->address == addr); + assert(strcmp(f->symbol, sym) == 0); + assert(strcmp(f->filename, "vmlinux") == 0); + oops = g_list_next(oops); +} + +int main(void) +{ + char *str = btp_file_to_string("../../oopses/oops.s390x"); + assert(str); + oops = btp_parse_kerneloops(str, kver); + assert(oops); + + t(0x000000000045400c, "list_add"); + t(0x000000000024798e, "anon_vma_fork"); + t(0x0000000000149786, "dup_mm"); + t(0x000000000014a860, "copy_process"); + t(0x000000000014b14c, "do_fork"); + t(0x0000000000106c16, "SyS_clone"); + t(0x0000000000631e08, "sysc_tracego"); + /* XXX: the rest is not parsed correctly? */ + + return 0; +} +]]) + +## -------------------------- ## +## btp_parse_kerneloops_armv7 ## +## -------------------------- ## + +AT_TESTFUN([btp_parse_kerneloops_armv7], +[[ +#include <lib/core-backtrace-oops.h> +#include <lib/utils.h> +#include <glib.h> +#include <assert.h> + +char *kver = "N/A"; +GList *oops = NULL; + +void t(uint64_t addr, char *sym) +{ + assert(oops); + struct backtrace_entry *f = oops->data; + + assert(f->address == addr); + assert(strcmp(f->symbol, sym) == 0); + assert(strcmp(f->filename, "vmlinux") == 0); + oops = g_list_next(oops); +} + +int main(void) +{ + char *str = btp_file_to_string("../../oopses/oops.armv7"); + assert(str); + oops = btp_parse_kerneloops(str, kver); + assert(oops); + + t(0xc0014210, "unwind_backtrace"); + t(0xc024c208, "dss_driver_probe"); + t(0xc0294520, "driver_probe_device"); + t(0xc02946b8, "driver_attach"); + t(0xc0293788, "bus_for_each_dev"); + t(0xc0293ef4, "bus_add_driver"); + t(0xc0294b64, "driver_register"); + t(0xc0008858, "do_one_initcall"); + t(0xc06c48bc, "kernel_init"); + assert(oops == NULL); + + return 0; +} +]]) diff --git a/tests/testsuite.at b/tests/testsuite.at index fbbd4a2..be2bac9 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -10,3 +10,4 @@ m4_include([normalize.at]) m4_include([metrics.at]) m4_include([cluster.at]) m4_include([sharedlib.at]) +m4_include([corebt-oops.at])