Use perl for regexp
[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 #include "instrumentation/syscalls/headers/syscalls_integers.h"
39 #include "instrumentation/syscalls/headers/syscalls_pointers.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 #define CREATE_SYSCALL_TABLE
54
55 #undef TRACE_SYSCALL_TABLE
56 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
57 [ _nr ] = { \
58 .func = __event_probe__##_template, \
59 .nrargs = (_nrargs), \
60 .fields = __event_fields___##_template, \
61 .desc = &__event_desc___##_name, \
62 },
63
64 static struct trace_syscall_entry sc_table[] = {
65 #include "instrumentation/syscalls/headers/syscalls_integers.h"
66 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
67 };
68
69 #undef CREATE_SYSCALL_TABLE
70
71 static void syscall_entry_probe(void *__data, struct pt_regs *regs, long id)
72 {
73 struct trace_syscall_entry *entry;
74 struct ltt_channel *chan = __data;
75 struct ltt_event *event;
76
77 if (unlikely(id >= ARRAY_SIZE(sc_table)))
78 return;
79 entry = &sc_table[id];
80 if (unlikely(!entry->func))
81 return;
82 event = chan->sc_table[id];
83 WARN_ON_ONCE(!event);
84
85 switch (entry->nrargs) {
86 case 0:
87 {
88 void (*fptr)(void *__data) = entry->func;
89
90 fptr(event);
91 break;
92 }
93 case 1:
94 {
95 void (*fptr)(void *__data, unsigned long arg0) = entry->func;
96 unsigned long args[1];
97
98 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
99 fptr(event, args[0]);
100 break;
101 }
102 case 2:
103 {
104 void (*fptr)(void *__data,
105 unsigned long arg0,
106 unsigned long arg1) = entry->func;
107 unsigned long args[2];
108
109 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
110 fptr(event, args[0], args[1]);
111 break;
112 }
113 case 3:
114 {
115 void (*fptr)(void *__data,
116 unsigned long arg0,
117 unsigned long arg1,
118 unsigned long arg2) = entry->func;
119 unsigned long args[3];
120
121 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
122 fptr(event, args[0], args[1], args[2]);
123 break;
124 }
125 case 4:
126 {
127 void (*fptr)(void *__data,
128 unsigned long arg0,
129 unsigned long arg1,
130 unsigned long arg2,
131 unsigned long arg3) = entry->func;
132 unsigned long args[4];
133
134 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
135 fptr(event, args[0], args[1], args[2], args[3]);
136 break;
137 }
138 case 5:
139 {
140 void (*fptr)(void *__data,
141 unsigned long arg0,
142 unsigned long arg1,
143 unsigned long arg2,
144 unsigned long arg3,
145 unsigned long arg4) = entry->func;
146 unsigned long args[5];
147
148 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
149 fptr(event, args[0], args[1], args[2], args[3], args[4]);
150 break;
151 }
152 case 6:
153 {
154 void (*fptr)(void *__data,
155 unsigned long arg0,
156 unsigned long arg1,
157 unsigned long arg2,
158 unsigned long arg3,
159 unsigned long arg4,
160 unsigned long arg5) = entry->func;
161 unsigned long args[6];
162
163 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
164 fptr(event, args[0], args[1], args[2],
165 args[3], args[4], args[5]);
166 break;
167 }
168 default:
169 break;
170 }
171 }
172
173 int lttng_syscalls_register(struct ltt_channel *chan, void *filter)
174 {
175 unsigned int i;
176 int ret;
177
178 wrapper_vmalloc_sync_all();
179
180 if (!chan->sc_table) {
181 /* create syscall table mapping syscall to events */
182 chan->sc_table = kzalloc(sizeof(struct ltt_event *)
183 * ARRAY_SIZE(sc_table), GFP_KERNEL);
184 if (!chan->sc_table)
185 return -ENOMEM;
186 }
187
188 /* Allocate events for each syscall, insert into table */
189 for (i = 0; i < ARRAY_SIZE(sc_table); i++) {
190 struct lttng_kernel_event ev;
191 const struct lttng_event_desc *desc = sc_table[i].desc;
192
193 if (!desc)
194 continue;
195 /*
196 * Skip those already populated by previous failed
197 * register for this channel.
198 */
199 if (chan->sc_table[i])
200 continue;
201 memset(&ev, 0, sizeof(ev));
202 strncpy(ev.name, desc->name, LTTNG_SYM_NAME_LEN);
203 ev.name[LTTNG_SYM_NAME_LEN - 1] = '\0';
204 ev.instrumentation = LTTNG_KERNEL_NOOP;
205 chan->sc_table[i] = ltt_event_create(chan, &ev, filter,
206 desc);
207 if (!chan->sc_table[i]) {
208 /*
209 * If something goes wrong in event registration
210 * after the first one, we have no choice but to
211 * leave the previous events in there, until
212 * deleted by session teardown.
213 */
214 return -EINVAL;
215 }
216 }
217 ret = tracepoint_probe_register("sys_enter",
218 (void *) syscall_entry_probe, chan);
219 return ret;
220 }
221
222 /*
223 * Only called at session destruction.
224 */
225 int lttng_syscalls_unregister(struct ltt_channel *chan)
226 {
227 int ret;
228
229 if (!chan->sc_table)
230 return 0;
231 ret = tracepoint_probe_unregister("sys_enter",
232 (void *) syscall_entry_probe, chan);
233 if (ret)
234 return ret;
235 /* ltt_event destroy will be performed by ltt_session_destroy() */
236 kfree(chan->sc_table);
237 return 0;
238 }
This page took 0.036479 seconds and 5 git commands to generate.