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"
};
#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:
}
}
-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 */
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;
- if (!desc)
+ if (!desc) {
+ /* Unknown syscall */
continue;
+ }
/*
* 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->sc_unknown);
+ 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->sc_unknown);
+ if (ret)
+ return ret;
ret = tracepoint_probe_unregister("sys_enter",
(void *) syscall_entry_probe, chan);
if (ret)