X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=lttng-syscalls.c;h=b712502b362d6f68942d57cfff5ce9928e344df1;hb=b76dc1a0b1f4eb9f7ae754d2b44a431d9a24b1a5;hp=2a63ad5213d653d7ad7c4b57bf2f95959bc257c5;hpb=25631135724387849b45eaed70d75e072c29e2f5;p=lttng-modules.git diff --git a/lttng-syscalls.c b/lttng-syscalls.c index 2a63ad52..b712502b 100644 --- a/lttng-syscalls.c +++ b/lttng-syscalls.c @@ -10,11 +10,19 @@ #include #include +#include #include #include #include "ltt-events.h" +#ifndef CONFIG_COMPAT +static inline int is_compat_task(void) +{ + return 0; +} +#endif + static void syscall_entry_probe(void *__data, struct pt_regs *regs, long id); /* @@ -29,17 +37,18 @@ static void syscall_entry_probe(void *__data, struct pt_regs *regs, long id); */ #define LTTNG_PACKAGE_BUILD #define CREATE_TRACE_POINTS +#define TP_MODULE_OVERRIDE +#define TRACE_INCLUDE_PATH ../instrumentation/syscalls/headers /* Hijack probe callback for system calls */ #define TP_PROBE_CB(_template) &syscall_entry_probe -#define TP_MODULE_OVERRIDE - -#define TRACE_INCLUDE_PATH ../instrumentation/syscalls/headers +#include "instrumentation/syscalls/headers/syscalls_integers.h" +#include "instrumentation/syscalls/headers/syscalls_pointers.h" +#undef TP_PROBE_CB -#include "instrumentation/syscalls/headers/syscalls.h" +#include "instrumentation/syscalls/headers/syscalls_unknown.h" #undef TP_MODULE_OVERRIDE -#undef TP_PROBE_CB #undef LTTNG_PACKAGE_BUILD #undef CREATE_TRACE_POINTS @@ -62,24 +71,47 @@ struct trace_syscall_entry { }, static struct trace_syscall_entry sc_table[] = { -#include "instrumentation/syscalls/headers/syscalls.h" +#include "instrumentation/syscalls/headers/syscalls_integers.h" +#include "instrumentation/syscalls/headers/syscalls_pointers.h" }; #undef CREATE_SYSCALL_TABLE +static void syscall_entry_unknown(struct ltt_event *event, + struct pt_regs *regs, unsigned int id) +{ + unsigned long args[UNKNOWN_SYSCALL_NRARGS]; + + syscall_get_arguments(current, regs, 0, UNKNOWN_SYSCALL_NRARGS, args); + __event_probe__sys_unknown(event, id, args); +} + +/* + * Currently, given that the kernel syscall metadata extraction only + * considers native system calls (not 32-bit compability ones), we + * fall-back on the "unknown" system call tracing for 32-bit compat. + */ 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))) + if (unlikely(is_compat_task())) { + syscall_entry_unknown(chan->sc_compat_unknown, regs, id); return; - entry = &sc_table[id]; - if (unlikely(!entry->func)) + } + if (unlikely(id >= ARRAY_SIZE(sc_table))) { + syscall_entry_unknown(chan->sc_unknown, regs, id); return; + } event = chan->sc_table[id]; - WARN_ON_ONCE(!event); + if (unlikely(!event)) { + syscall_entry_unknown(chan->sc_unknown, regs, id); + return; + } + entry = &sc_table[id]; + WARN_ON_ONCE(!entry); switch (entry->nrargs) { case 0: @@ -184,13 +216,63 @@ 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; + } + } + + if (!chan->sc_compat_unknown) { + struct lttng_kernel_event ev; + const struct lttng_event_desc *desc = + &__event_desc___compat_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_compat_unknown = ltt_event_create(chan, &ev, filter, + desc); + if (!chan->sc_compat_unknown) { + return -EINVAL; + } + } + + if (!chan->sc_exit) { + struct lttng_kernel_event ev; + const struct lttng_event_desc *desc = + &__event_desc___exit_syscall; + + 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_exit = ltt_event_create(chan, &ev, filter, + desc); + if (!chan->sc_exit) { + 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; - if (!desc) + if (!desc) { + /* Unknown syscall */ continue; + } /* * Skip those already populated by previous failed * register for this channel. @@ -215,6 +297,19 @@ int lttng_syscalls_register(struct ltt_channel *chan, void *filter) } ret = tracepoint_probe_register("sys_enter", (void *) syscall_entry_probe, chan); + if (ret) + return ret; + /* + * We change the name of sys_exit tracepoint due to namespace + * conflict with sys_exit syscall entry. + */ + ret = tracepoint_probe_register("sys_exit", + (void *) __event_probe__exit_syscall, + chan->sc_exit); + if (ret) { + WARN_ON_ONCE(tracepoint_probe_unregister("sys_enter", + (void *) syscall_entry_probe, chan)); + } return ret; } @@ -227,6 +322,11 @@ int lttng_syscalls_unregister(struct ltt_channel *chan) if (!chan->sc_table) return 0; + ret = tracepoint_probe_unregister("sys_exit", + (void *) __event_probe__exit_syscall, + chan->sc_exit); + if (ret) + return ret; ret = tracepoint_probe_unregister("sys_enter", (void *) syscall_entry_probe, chan); if (ret)