static void syscall_entry_probe(void *__data, struct pt_regs *regs, long id);
+/*
+ * Take care of NOARGS not supported by mainline.
+ */
+#define DECLARE_EVENT_CLASS_NOARGS(name, tstruct, assign, print)
+#define DEFINE_EVENT_NOARGS(template, name)
+#define TRACE_EVENT_NOARGS(name, struct, assign, print)
+
/*
* Create LTTng tracepoint probes.
*/
#define TP_MODULE_OVERRIDE
#define TRACE_INCLUDE_PATH ../instrumentation/syscalls/headers
-
-#include "instrumentation/syscalls/headers/syscalls.h"
+#include "instrumentation/syscalls/headers/syscalls_integers.h"
+#include "instrumentation/syscalls/headers/syscalls_pointers.h"
+#include "instrumentation/syscalls/headers/syscalls_unknown.h"
#undef TP_MODULE_OVERRIDE
#undef TP_PROBE_CB
struct trace_syscall_entry {
void *func;
- const struct lttng_event_desc *desc; /* Set dynamically */
+ const struct lttng_event_desc *desc;
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) \
+#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
[ _nr ] = { \
- .func = __event_probe__##_name, \
+ .func = __event_probe__##_template, \
.nrargs = (_nrargs), \
- .fields = __event_fields___##_name, \
+ .fields = __event_fields___##_template, \
+ .desc = &__event_desc___##_name, \
},
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"
};
+static int sc_table_filled;
+
#undef CREATE_SYSCALL_TABLE
static void syscall_entry_probe(void *__data, struct pt_regs *regs, long id)
}
}
-static const struct lttng_event_desc *find_syscall_desc(unsigned int id)
+static void fill_sc_table(void)
{
- unsigned int i;
+ 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];
+ if (sc_table_filled) {
+ smp_rmb(); /* read flag before table */
+ return;
}
- 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)
+ if (sc_table[i].func)
continue;
- (*desc) = find_syscall_desc(i);
+ 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;
}
- sc_table_desc_filled = 1;
+ 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;
int ret;
wrapper_vmalloc_sync_all();
- fill_sc_table_desc();
+
+ fill_sc_table();
if (!chan->sc_table) {
/* create syscall table mapping syscall to events */
struct lttng_kernel_event ev;
const struct lttng_event_desc *desc = sc_table[i].desc;
- if (!desc)
- continue;
+ WARN_ON_ONCE(!desc);
/*
* Skip those already populated by previous failed
* register for this channel.
}
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);
+ if (ret) {
+ WARN_ON_ONCE(tracepoint_probe_unregister("sys_enter",
+ (void *) syscall_entry_probe, chan));
+ }
return ret;
}
if (!chan->sc_table)
return 0;
+ ret = tracepoint_probe_unregister("sys_exit",
+ (void *) __event_probe__exit_syscall, chan);
+ if (ret)
+ return ret;
ret = tracepoint_probe_unregister("sys_enter",
(void *) syscall_entry_probe, chan);
if (ret)