Fix unknown syscall support
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 17 Sep 2011 13:47:24 +0000 (09:47 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 17 Sep 2011 13:47:24 +0000 (09:47 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
ltt-events.h
lttng-syscalls.c

index 2437e76eab5296f8459869bbde249eec6e1f9edd..a53e2e8922c5b7c17264aa80dc10dd5e53091ad1 100644 (file)
@@ -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;
 };
index 1872f161faa22955587c609bbc8eb7013edebcde..48eaf16027074108a83abcf21116ec08f7499291 100644 (file)
@@ -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.
This page took 0.028264 seconds and 4 git commands to generate.