Support detailed syscalls with 0 arguments
[lttng-modules.git] / lttng-syscalls.c
1 /*
2 * lttng-syscalls.c
3 *
4 * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
6 * LTTng sched probes.
7 *
8 * Dual LGPL v2.1/GPL v2 license.
9 */
10
11 #include <linux/module.h>
12 #include <linux/slab.h>
13 #include <asm/ptrace.h>
14 #include <asm/syscall.h>
15
16 #include "ltt-events.h"
17
18 static void syscall_entry_probe(void *__data, struct pt_regs *regs, long id);
19
20 /*
21 * Take care of NOARGS not supported by mainline.
22 */
23 #define DECLARE_EVENT_CLASS_NOARGS(name, tstruct, assign, print)
24 #define DEFINE_EVENT_NOARGS(template, name)
25 #define TRACE_EVENT_NOARGS(name, struct, assign, print)
26
27 /*
28 * Create LTTng tracepoint probes.
29 */
30 #define LTTNG_PACKAGE_BUILD
31 #define CREATE_TRACE_POINTS
32
33 /* Hijack probe callback for system calls */
34 #define TP_PROBE_CB(_template) &syscall_entry_probe
35 #define TP_MODULE_OVERRIDE
36
37 #define TRACE_INCLUDE_PATH ../instrumentation/syscalls/headers
38
39 #include "instrumentation/syscalls/headers/syscalls.h"
40
41 #undef TP_MODULE_OVERRIDE
42 #undef TP_PROBE_CB
43 #undef LTTNG_PACKAGE_BUILD
44 #undef CREATE_TRACE_POINTS
45
46 struct trace_syscall_entry {
47 void *func;
48 const struct lttng_event_desc *desc;
49 const struct lttng_event_field *fields;
50 unsigned int nrargs;
51 };
52
53 static int sc_table_desc_filled;
54
55 #define CREATE_SYSCALL_TABLE
56
57 #undef TRACE_SYSCALL_TABLE
58 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
59 [ _nr ] = { \
60 .func = __event_probe__##_template, \
61 .nrargs = (_nrargs), \
62 .fields = __event_fields___##_template, \
63 .desc = &__event_desc___##_name, \
64 },
65
66 static struct trace_syscall_entry sc_table[] = {
67 #include "instrumentation/syscalls/headers/syscalls.h"
68 };
69
70 #undef CREATE_SYSCALL_TABLE
71
72 static void syscall_entry_probe(void *__data, struct pt_regs *regs, long id)
73 {
74 struct trace_syscall_entry *entry;
75 struct ltt_channel *chan = __data;
76 struct ltt_event *event;
77
78 if (unlikely(id >= ARRAY_SIZE(sc_table)))
79 return;
80 entry = &sc_table[id];
81 if (unlikely(!entry->func))
82 return;
83 event = chan->sc_table[id];
84 WARN_ON_ONCE(!event);
85
86 switch (entry->nrargs) {
87 case 0:
88 {
89 void (*fptr)(void *__data) = entry->func;
90
91 fptr(event);
92 break;
93 }
94 case 1:
95 {
96 void (*fptr)(void *__data, unsigned long arg0) = entry->func;
97 unsigned long args[1];
98
99 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
100 fptr(event, args[0]);
101 break;
102 }
103 case 2:
104 {
105 void (*fptr)(void *__data,
106 unsigned long arg0,
107 unsigned long arg1) = entry->func;
108 unsigned long args[2];
109
110 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
111 fptr(event, args[0], args[1]);
112 break;
113 }
114 case 3:
115 {
116 void (*fptr)(void *__data,
117 unsigned long arg0,
118 unsigned long arg1,
119 unsigned long arg2) = entry->func;
120 unsigned long args[3];
121
122 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
123 fptr(event, args[0], args[1], args[2]);
124 break;
125 }
126 case 4:
127 {
128 void (*fptr)(void *__data,
129 unsigned long arg0,
130 unsigned long arg1,
131 unsigned long arg2,
132 unsigned long arg3) = entry->func;
133 unsigned long args[4];
134
135 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
136 fptr(event, args[0], args[1], args[2], args[3]);
137 break;
138 }
139 case 5:
140 {
141 void (*fptr)(void *__data,
142 unsigned long arg0,
143 unsigned long arg1,
144 unsigned long arg2,
145 unsigned long arg3,
146 unsigned long arg4) = entry->func;
147 unsigned long args[5];
148
149 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
150 fptr(event, args[0], args[1], args[2], args[3], args[4]);
151 break;
152 }
153 case 6:
154 {
155 void (*fptr)(void *__data,
156 unsigned long arg0,
157 unsigned long arg1,
158 unsigned long arg2,
159 unsigned long arg3,
160 unsigned long arg4,
161 unsigned long arg5) = entry->func;
162 unsigned long args[6];
163
164 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
165 fptr(event, args[0], args[1], args[2],
166 args[3], args[4], args[5]);
167 break;
168 }
169 default:
170 break;
171 }
172 }
173
174 int lttng_syscalls_register(struct ltt_channel *chan, void *filter)
175 {
176 unsigned int i;
177 int ret;
178
179 wrapper_vmalloc_sync_all();
180
181 if (!chan->sc_table) {
182 /* create syscall table mapping syscall to events */
183 chan->sc_table = kzalloc(sizeof(struct ltt_event *)
184 * ARRAY_SIZE(sc_table), GFP_KERNEL);
185 if (!chan->sc_table)
186 return -ENOMEM;
187 }
188
189 /* Allocate events for each syscall, insert into table */
190 for (i = 0; i < ARRAY_SIZE(sc_table); i++) {
191 struct lttng_kernel_event ev;
192 const struct lttng_event_desc *desc = sc_table[i].desc;
193
194 if (!desc)
195 continue;
196 /*
197 * Skip those already populated by previous failed
198 * register for this channel.
199 */
200 if (chan->sc_table[i])
201 continue;
202 memset(&ev, 0, sizeof(ev));
203 strncpy(ev.name, desc->name, LTTNG_SYM_NAME_LEN);
204 ev.name[LTTNG_SYM_NAME_LEN - 1] = '\0';
205 ev.instrumentation = LTTNG_KERNEL_NOOP;
206 chan->sc_table[i] = ltt_event_create(chan, &ev, filter,
207 desc);
208 if (!chan->sc_table[i]) {
209 /*
210 * If something goes wrong in event registration
211 * after the first one, we have no choice but to
212 * leave the previous events in there, until
213 * deleted by session teardown.
214 */
215 return -EINVAL;
216 }
217 }
218 ret = tracepoint_probe_register("sys_enter",
219 (void *) syscall_entry_probe, chan);
220 return ret;
221 }
222
223 /*
224 * Only called at session destruction.
225 */
226 int lttng_syscalls_unregister(struct ltt_channel *chan)
227 {
228 int ret;
229
230 if (!chan->sc_table)
231 return 0;
232 ret = tracepoint_probe_unregister("sys_enter",
233 (void *) syscall_entry_probe, chan);
234 if (ret)
235 return ret;
236 /* ltt_event destroy will be performed by ltt_session_destroy() */
237 kfree(chan->sc_table);
238 return 0;
239 }
This page took 0.034487 seconds and 5 git commands to generate.