Buidl disabled for now.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
lttng-context-vtid.o lttng-context-ppid.o \
lttng-context-vppid.o lttng-calibrate.o
+#add for testing lttng-syscalls.o
+
ifneq ($(CONFIG_PERF_EVENTS),)
ltt-relay-objs += $(shell \
if [ $(VERSION) -ge 3 \
* We tolerate no failure path after event creation. It will stay
* invariant for the rest of the session.
*/
- event = ltt_event_create(channel, &metadata_params, NULL);
+ event = ltt_event_create(channel, &metadata_params, NULL, NULL);
if (!event) {
goto create_error;
}
* We tolerate no failure path after event creation. It
* will stay invariant for the rest of the session.
*/
- event = ltt_event_create(channel, &event_param, NULL);
+ event = ltt_event_create(channel, &event_param, NULL, NULL);
if (!event) {
ret = -EINVAL;
goto event_error;
*/
struct ltt_event *ltt_event_create(struct ltt_channel *chan,
struct lttng_kernel_event *event_param,
- void *filter)
+ void *filter,
+ const struct lttng_event_desc *internal_desc)
{
struct ltt_event *event;
int ret;
WARN_ON_ONCE(!ret);
break;
case LTTNG_KERNEL_NOOP:
+ event->desc = internal_desc;
+ if (!event->desc)
+ goto register_error;
break;
default:
WARN_ON_ONCE(1);
return event;
statedump_error:
- WARN_ON_ONCE(tracepoint_probe_unregister(event_param->name,
- event->desc->probe_callback,
- event));
- ltt_event_put(event->desc);
+ /* If a statedump error occurs, events will not be readable. */
register_error:
kmem_cache_free(event_cache, event);
cache_error:
lttng_ftrace_unregister(event);
ret = 0;
break;
+ case LTTNG_KERNEL_NOOP:
+ ret = 0;
+ break;
default:
WARN_ON_ONCE(1);
}
module_put(event->desc->owner);
lttng_ftrace_destroy_private(event);
break;
+ case LTTNG_KERNEL_NOOP:
+ break;
default:
WARN_ON_ONCE(1);
}
struct ltt_event *ltt_event_create(struct ltt_channel *chan,
struct lttng_kernel_event *event_param,
- void *filter);
+ void *filter,
+ const struct lttng_event_desc *internal_desc);
int ltt_channel_enable(struct ltt_channel *channel);
int ltt_channel_disable(struct ltt_channel *channel);
--- /dev/null
+/*
+ * lttng-syscalls.c
+ *
+ * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * LTTng sched probes.
+ *
+ * Dual LGPL v2.1/GPL v2 license.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/ptrace.h>
+#include <asm/syscall.h>
+
+#include "ltt-events.h"
+
+static void syscall_entry_probe(void *__data, struct pt_regs *regs, long id);
+
+/*
+ * Create LTTng tracepoint probes.
+ */
+#define LTTNG_PACKAGE_BUILD
+#define CREATE_TRACE_POINTS
+
+/* 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.h"
+
+#undef TP_MODULE_OVERRIDE
+#undef TP_PROBE_CB
+#undef LTTNG_PACKAGE_BUILD
+#undef CREATE_TRACE_POINTS
+
+struct trace_syscall_entry {
+ void *func;
+ const struct lttng_event_desc *desc; /* Set dynamically */
+ const struct lttng_event_field *fields;
+ unsigned int nrargs;
+};
+
+static int sc_table_desc_filled;
+
+#define CREATE_SYSCALL_TABLE
+
+#undef TRACE_SYSCALL_TABLE
+#define TRACE_SYSCALL_TABLE(_name, _nr, _nrargs) \
+ [ _nr ] = { \
+ .func = __event_probe__##_name, \
+ .nrargs = (_nrargs), \
+ .fields = __event_fields___##_name, \
+ },
+
+static struct trace_syscall_entry sc_table[] = {
+#include "instrumentation/syscalls/headers/syscalls.h"
+};
+
+#undef CREATE_SYSCALL_TABLE
+
+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))
+ return;
+ event = chan->sc_table[id];
+ WARN_ON_ONCE(!event);
+
+ switch (entry->nrargs) {
+ case 0:
+ {
+ void (*fptr)(void *__data) = entry->func;
+
+ fptr(event);
+ break;
+ }
+ case 1:
+ {
+ void (*fptr)(void *__data, unsigned long arg0) = entry->func;
+ unsigned long args[1];
+
+ syscall_get_arguments(current, regs, 0, entry->nrargs, args);
+ fptr(event, args[0]);
+ break;
+ }
+ case 2:
+ {
+ void (*fptr)(void *__data,
+ unsigned long arg0,
+ unsigned long arg1) = entry->func;
+ unsigned long args[2];
+
+ syscall_get_arguments(current, regs, 0, entry->nrargs, args);
+ fptr(event, args[0], args[1]);
+ break;
+ }
+ case 3:
+ {
+ void (*fptr)(void *__data,
+ unsigned long arg0,
+ unsigned long arg1,
+ unsigned long arg2) = entry->func;
+ unsigned long args[3];
+
+ syscall_get_arguments(current, regs, 0, entry->nrargs, args);
+ fptr(event, args[0], args[1], args[2]);
+ break;
+ }
+ case 4:
+ {
+ void (*fptr)(void *__data,
+ unsigned long arg0,
+ unsigned long arg1,
+ unsigned long arg2,
+ unsigned long arg3) = entry->func;
+ unsigned long args[4];
+
+ syscall_get_arguments(current, regs, 0, entry->nrargs, args);
+ fptr(event, args[0], args[1], args[2], args[3]);
+ break;
+ }
+ case 5:
+ {
+ void (*fptr)(void *__data,
+ unsigned long arg0,
+ unsigned long arg1,
+ unsigned long arg2,
+ unsigned long arg3,
+ unsigned long arg4) = entry->func;
+ unsigned long args[5];
+
+ syscall_get_arguments(current, regs, 0, entry->nrargs, args);
+ fptr(event, args[0], args[1], args[2], args[3], args[4]);
+ break;
+ }
+ case 6:
+ {
+ void (*fptr)(void *__data,
+ unsigned long arg0,
+ unsigned long arg1,
+ unsigned long arg2,
+ unsigned long arg3,
+ unsigned long arg4,
+ unsigned long arg5) = entry->func;
+ unsigned long args[6];
+
+ syscall_get_arguments(current, regs, 0, entry->nrargs, args);
+ fptr(event, args[0], args[1], args[2],
+ args[3], args[4], args[5]);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static const struct lttng_event_desc *find_syscall_desc(unsigned int id)
+{
+ unsigned int i;
+
+ for (i = 0; i < __probe_desc___syscalls.nr_events; i++) {
+ if (__probe_desc___syscalls.event_desc[i].fields
+ == sc_table[id].fields)
+ return &__probe_desc___syscalls.event_desc[i];
+ }
+ WARN_ON_ONCE(1);
+ return NULL;
+}
+
+static void fill_sc_table_desc(void)
+{
+ unsigned int i;
+
+ if (sc_table_desc_filled)
+ return;
+ /*
+ * This is O(n^2), but rare. Eventually get the TRACE_EVENT code
+ * to emit per-event symbols to skip this.
+ */
+ for (i = 0; i < ARRAY_SIZE(sc_table); i++) {
+ const struct lttng_event_desc **desc = &sc_table[i].desc;
+
+ if (!sc_table[i].func)
+ continue;
+ (*desc) = find_syscall_desc(i);
+ }
+ sc_table_desc_filled = 1;
+}
+
+
+int lttng_syscalls_register(struct ltt_channel *chan, void *filter)
+{
+ unsigned int i;
+ int ret;
+
+ wrapper_vmalloc_sync_all();
+ fill_sc_table_desc();
+
+ if (!chan->sc_table) {
+ /* create syscall table mapping syscall to events */
+ chan->sc_table = kzalloc(sizeof(struct ltt_event *)
+ * ARRAY_SIZE(sc_table), GFP_KERNEL);
+ if (!chan->sc_table)
+ return -ENOMEM;
+ }
+
+ /* 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)
+ continue;
+ /*
+ * Skip those already populated by previous failed
+ * register for this channel.
+ */
+ if (chan->sc_table[i])
+ continue;
+ 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_table[i] = ltt_event_create(chan, &ev, filter,
+ desc);
+ if (!chan->sc_table[i]) {
+ /*
+ * If something goes wrong in event registration
+ * after the first one, we have no choice but to
+ * leave the previous events in there, until
+ * deleted by session teardown.
+ */
+ return -EINVAL;
+ }
+ }
+ ret = tracepoint_probe_register("sys_enter",
+ (void *) syscall_entry_probe, chan);
+ return ret;
+}
+
+/*
+ * Only called at session destruction.
+ */
+int lttng_syscalls_unregister(struct ltt_channel *chan)
+{
+ int ret;
+
+ if (!chan->sc_table)
+ return 0;
+ ret = tracepoint_probe_unregister("sys_enter",
+ (void *) syscall_entry_probe, chan);
+ if (ret)
+ return ret;
+ /* ltt_event destroy will be performed by ltt_session_destroy() */
+ kfree(chan->sc_table);
+ return 0;
+}
#include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */
-/* Override for syscall tracing */
-#ifndef TP_REGISTER_OVERRIDE
-#define TP_REGISTER_OVERRIDE ltt_probe_register
-#endif
-
-#ifndef TP_UNREGISTER_OVERRIDE
-#define TP_UNREGISTER_OVERRIDE ltt_probe_unregister
-#endif
-
#define TP_ID1(_token, _system) _token##_system
#define TP_ID(_token, _system) TP_ID1(_token, _system)
#define module_init_eval1(_token, _system) module_init(_token##_system)
#define module_exit_eval1(_token, _system) module_exit(_token##_system)
#define module_exit_eval(_token, _system) module_exit_eval1(_token, _system)
+#ifndef TP_MODULE_OVERRIDE
static int TP_ID(__lttng_events_init__, TRACE_SYSTEM)(void)
{
wrapper_vmalloc_sync_all();
- return TP_REGISTER_OVERRIDE(&TP_ID(__probe_desc___, TRACE_SYSTEM));
+ return ltt_probe_register(&TP_ID(__probe_desc___, TRACE_SYSTEM));
}
module_init_eval(__lttng_events_init__, TRACE_SYSTEM);
static void TP_ID(__lttng_events_exit__, TRACE_SYSTEM)(void)
{
- TP_UNREGISTER_OVERRIDE(&TP_ID(__probe_desc___, TRACE_SYSTEM));
+ ltt_probe_unregister(&TP_ID(__probe_desc___, TRACE_SYSTEM));
}
module_exit_eval(__lttng_events_exit__, TRACE_SYSTEM);
+#endif
#undef module_init_eval
#undef module_exit_eval
/*
- * probes/lttng-probe-sched.c
+ * probes/lttng-probe-syscalls.c
*
* Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
*
- * LTTng sched probes.
+ * LTTng syscalls probes.
*
* Dual LGPL v2.1/GPL v2 license.
*/
#include <linux/module.h>
#include "../ltt-events.h"
-#ifndef SYSCALL_DETAIL
-
/*
* Create the tracepoint static inlines from the kernel to validate that our
* trace event macros match the kernel we run on.
#include "../instrumentation/events/lttng-module/syscalls.h"
-#else /* SYSCALL_DETAIL */
-
-#include <linux/slab.h>
-#include <asm/ptrace.h>
-#include <asm/syscall.h>
-
-static void syscall_entry_probe(void *__data, struct pt_regs *regs, long id);
-static int lttng_syscalls_register_probe(struct lttng_probe_desc *desc);
-static void lttng_syscalls_unregister_probe(struct lttng_probe_desc *desc);
-
-static struct lttng_probe_desc *syscall_probe_desc;
-
-/*
- * Create LTTng tracepoint probes.
- */
-#define LTTNG_PACKAGE_BUILD
-#define CREATE_TRACE_POINTS
-
-/* Hijack probe callback for system calls */
-#define TP_PROBE_CB(_template) &syscall_entry_probe
-#define TP_REGISTER_OVERRIDE lttng_syscalls_register_probe
-#define TP_UNREGISTER_OVERRIDE lttng_syscalls_unregister_probe
-
-#define TRACE_INCLUDE_PATH ../instrumentation/syscalls/headers
-
-#include "../instrumentation/syscalls/headers/syscalls.h"
-
-#undef TP_UNREGISTER_OVERRIDE
-#undef TP_REGISTER_OVERRIDE
-#undef TP_PROBE_CB
-#undef LTTNG_PACKAGE_BUILD
-#undef CREATE_TRACE_POINTS
-
-struct trace_syscall_entry {
- void *func;
- const struct lttng_event_desc *desc; /* Set dynamically */
- const struct lttng_event_field *fields;
- unsigned int nrargs;
-};
-
-static int sc_table_desc_filled;
-
-#define CREATE_SYSCALL_TABLE
-
-#undef TRACE_SYSCALL_TABLE
-#define TRACE_SYSCALL_TABLE(_name, _nr, _nrargs) \
- [ _nr ] = { \
- .func = __event_probe__##_name, \
- .nrargs = (_nrargs), \
- .fields = __event_fields___##_name, \
- },
-
-static struct trace_syscall_entry sc_table[] = {
-#include "../instrumentation/syscalls/headers/syscalls.h"
-};
-
-#undef CREATE_SYSCALL_TABLE
-
-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))
- return;
- event = chan->sc_table[id];
- WARN_ON_ONCE(!event);
-
- switch (entry->nrargs) {
- case 0:
- {
- void (*fptr)(void *__data) = entry->func;
-
- fptr(event);
- break;
- }
- case 1:
- {
- void (*fptr)(void *__data, unsigned long arg0) = entry->func;
- unsigned long args[1];
-
- syscall_get_arguments(current, regs, 0, entry->nrargs, args);
- fptr(event, args[0]);
- break;
- }
- case 2:
- {
- void (*fptr)(void *__data,
- unsigned long arg0,
- unsigned long arg1) = entry->func;
- unsigned long args[2];
-
- syscall_get_arguments(current, regs, 0, entry->nrargs, args);
- fptr(event, args[0], args[1]);
- break;
- }
- case 3:
- {
- void (*fptr)(void *__data,
- unsigned long arg0,
- unsigned long arg1,
- unsigned long arg2) = entry->func;
- unsigned long args[3];
-
- syscall_get_arguments(current, regs, 0, entry->nrargs, args);
- fptr(event, args[0], args[1], args[2]);
- break;
- }
- case 4:
- {
- void (*fptr)(void *__data,
- unsigned long arg0,
- unsigned long arg1,
- unsigned long arg2,
- unsigned long arg3) = entry->func;
- unsigned long args[4];
-
- syscall_get_arguments(current, regs, 0, entry->nrargs, args);
- fptr(event, args[0], args[1], args[2], args[3]);
- break;
- }
- case 5:
- {
- void (*fptr)(void *__data,
- unsigned long arg0,
- unsigned long arg1,
- unsigned long arg2,
- unsigned long arg3,
- unsigned long arg4) = entry->func;
- unsigned long args[5];
-
- syscall_get_arguments(current, regs, 0, entry->nrargs, args);
- fptr(event, args[0], args[1], args[2], args[3], args[4]);
- break;
- }
- case 6:
- {
- void (*fptr)(void *__data,
- unsigned long arg0,
- unsigned long arg1,
- unsigned long arg2,
- unsigned long arg3,
- unsigned long arg4,
- unsigned long arg5) = entry->func;
- unsigned long args[6];
-
- syscall_get_arguments(current, regs, 0, entry->nrargs, args);
- fptr(event, args[0], args[1], args[2],
- args[3], args[4], args[5]);
- break;
- }
- default:
- break;
- }
-}
-
-static const struct lttng_event_desc *find_syscall_desc(unsigned int id)
-{
- unsigned int i;
-
- for (i = 0; i < syscall_probe_desc->nr_events; i++) {
- if (syscall_probe_desc->event_desc[i].fields
- == sc_table[id].fields)
- return &syscall_probe_desc->event_desc[i];
- }
- WARN_ON_ONCE(1);
- return NULL;
-}
-
-static void fill_sc_table_desc(void)
-{
- unsigned int i;
-
- if (sc_table_desc_filled)
- return;
- /*
- * This is O(n^2), but rare. Eventually get the TRACE_EVENT code
- * to emit per-event symbols to skip this.
- */
- for (i = 0; i < ARRAY_SIZE(sc_table); i++) {
- const struct lttng_event_desc **desc = &sc_table[i].desc;
-
- if (!sc_table[i].func)
- continue;
- (*desc) = find_syscall_desc(i);
- }
- sc_table_desc_filled = 1;
-}
-
-
-int lttng_syscalls_register(struct ltt_channel *chan, void *filter)
-{
- unsigned int i;
- int ret;
-
- fill_sc_table_desc();
-
- if (!chan->sc_table) {
- /* create syscall table mapping syscall to events */
- chan->sc_table = kzalloc(sizeof(struct ltt_event *)
- * ARRAY_SIZE(sc_table), GFP_KERNEL);
- if (!chan->sc_table)
- return -ENOMEM;
- }
-
- /* 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;
-
- /*
- * Skip those already populated by previous failed
- * register for this channel.
- */
- if (chan->sc_table[i])
- continue;
- 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_table[i] = ltt_event_create(chan, &ev, filter);
- if (!chan->sc_table[i]) {
- /*
- * If something goes wrong in event registration
- * after the first one, we have no choice but to
- * leave the previous events in there, until
- * deleted by session teardown.
- */
- return -EINVAL;
- }
- }
- ret = tracepoint_probe_register("syscall_entry",
- (void *) syscall_entry_probe, chan);
- return ret;
-}
-
-/*
- * Only called at session destruction.
- */
-int lttng_syscalls_unregister(struct ltt_channel *chan)
-{
- int ret;
-
- if (!chan->sc_table)
- return 0;
- ret = tracepoint_probe_unregister("syscall_entry",
- (void *) syscall_entry_probe, chan);
- if (ret)
- return ret;
- /* ltt_event destroy will be performed by ltt_session_destroy() */
- kfree(chan->sc_table);
- return 0;
-}
-
-static int lttng_syscalls_register_probe(struct lttng_probe_desc *desc)
-{
- WARN_ON_ONCE(syscall_probe_desc);
- syscall_probe_desc = desc;
- return 0;
-}
-
-static void lttng_syscalls_unregister_probe(struct lttng_probe_desc *desc)
-{
- WARN_ON_ONCE(!syscall_probe_desc);
- syscall_probe_desc = NULL;
-}
-
-#endif /* SYSCALL_DETAIL */
-
MODULE_LICENSE("GPL and additional rights");
MODULE_AUTHOR("Mathieu Desnoyers <mathieu.desnoyers@efficios.com>");
-MODULE_DESCRIPTION("LTTng sched probes");
+MODULE_DESCRIPTION("LTTng generic syscall probes");