I'm not sure if the koops normalization should be performed in every call of
the btp_parse_kerneloops() function?
ABRT uses the btp_parse_kerneloops() function to create a core backtrace and
AFAIK we don't want to omit any function in a core backtrace.
Regards,
Jakub
On Tuesday 09 of October 2012 16:16:11 Martin Milata wrote:
---
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])