From f405cfce5e339c7b4b5d44b99d43201d51ef6e4c Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Sat, 17 Sep 2011 09:47:24 -0400 Subject: [PATCH] Fix unknown syscall support Signed-off-by: Mathieu Desnoyers --- ltt-events.h | 1 + lttng-syscalls.c | 69 ++++++++++++++++++++++++++++-------------------- 2 files changed, 41 insertions(+), 29 deletions(-) diff --git a/ltt-events.h b/ltt-events.h index 2437e76e..a53e2e89 100644 --- a/ltt-events.h +++ b/ltt-events.h @@ -242,6 +242,7 @@ struct ltt_channel { struct ltt_channel_ops *ops; struct ltt_transport *transport; struct ltt_event **sc_table; /* for syscall tracing */ + struct ltt_event *sc_unknown; /* for unknown syscalls */ int header_type; /* 0: unset, 1: compact, 2: large */ int metadata_dumped:1; }; diff --git a/lttng-syscalls.c b/lttng-syscalls.c index 1872f161..48eaf160 100644 --- a/lttng-syscalls.c +++ b/lttng-syscalls.c @@ -71,19 +71,34 @@ static int sc_table_filled; #undef CREATE_SYSCALL_TABLE +static void syscall_entry_unknown(struct ltt_channel *chan, + struct pt_regs *regs, unsigned int id) +{ + unsigned long args[UNKNOWN_SYSCALL_NRARGS]; + struct ltt_event *event; + + event = chan->sc_unknown; + syscall_get_arguments(current, regs, 0, UNKNOWN_SYSCALL_NRARGS, args); + __event_probe__sys_unknown(event, id, args); +} + static void syscall_entry_probe(void *__data, struct pt_regs *regs, long id) { struct trace_syscall_entry *entry; struct ltt_channel *chan = __data; struct ltt_event *event; - if (unlikely(id >= ARRAY_SIZE(sc_table))) - return; - entry = &sc_table[id]; - if (unlikely(!entry->func)) + if (unlikely(id >= ARRAY_SIZE(sc_table))) { + syscall_entry_unknown(chan, regs, id); return; + } event = chan->sc_table[id]; - WARN_ON_ONCE(!event); + if (unlikely(!event)) { + syscall_entry_unknown(chan, regs, id); + return; + } + entry = &sc_table[id]; + WARN_ON_ONCE(!entry); switch (entry->nrargs) { case 0: @@ -173,27 +188,6 @@ static void syscall_entry_probe(void *__data, struct pt_regs *regs, long id) } } -static void fill_sc_table(void) -{ - int i; - - if (sc_table_filled) { - smp_rmb(); /* read flag before table */ - return; - } - - for (i = 0; i < ARRAY_SIZE(sc_table); i++) { - if (sc_table[i].func) - continue; - sc_table[i].func = __event_probe__sys_unknown; - sc_table[i].nrargs = UNKNOWN_SYSCALL_NRARGS; - sc_table[i].fields = __event_fields___sys_unknown; - sc_table[i].desc = &__event_desc___sys_unknown; - } - smp_wmb(); /* Fill sc table before set flag to 1 */ - sc_table_filled = 1; -} - int lttng_syscalls_register(struct ltt_channel *chan, void *filter) { unsigned int i; @@ -201,8 +195,6 @@ int lttng_syscalls_register(struct ltt_channel *chan, void *filter) wrapper_vmalloc_sync_all(); - fill_sc_table(); - if (!chan->sc_table) { /* create syscall table mapping syscall to events */ chan->sc_table = kzalloc(sizeof(struct ltt_event *) @@ -211,12 +203,31 @@ int lttng_syscalls_register(struct ltt_channel *chan, void *filter) return -ENOMEM; } + if (!chan->sc_unknown) { + struct lttng_kernel_event ev; + + const struct lttng_event_desc *desc = + &__event_desc___sys_unknown; + memset(&ev, 0, sizeof(ev)); + strncpy(ev.name, desc->name, LTTNG_SYM_NAME_LEN); + ev.name[LTTNG_SYM_NAME_LEN - 1] = '\0'; + ev.instrumentation = LTTNG_KERNEL_NOOP; + chan->sc_unknown = ltt_event_create(chan, &ev, filter, + desc); + if (!chan->sc_unknown) { + return -EINVAL; + } + } + /* Allocate events for each syscall, insert into table */ for (i = 0; i < ARRAY_SIZE(sc_table); i++) { struct lttng_kernel_event ev; const struct lttng_event_desc *desc = sc_table[i].desc; - WARN_ON_ONCE(!desc); + if (!desc) { + /* Unknown syscall */ + continue; + } /* * Skip those already populated by previous failed * register for this channel. -- 2.34.1