Cleanup: lttng-abi.h coding style
[lttng-modules.git] / lttng-syscalls.c
CommitLineData
259b6cb3
MD
1/*
2 * lttng-syscalls.c
3 *
2faf7d1b 4 * LTTng syscall probes.
259b6cb3 5 *
886d51a3
MD
6 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
259b6cb3
MD
21 */
22
23#include <linux/module.h>
24#include <linux/slab.h>
6333ace3 25#include <linux/compat.h>
abc0446a 26#include <linux/err.h>
80f87dd2 27#include <linux/bitmap.h>
7ca580f8
MD
28#include <linux/in.h>
29#include <linux/in6.h>
2d2464bd 30#include <linux/seq_file.h>
259b6cb3
MD
31#include <asm/ptrace.h>
32#include <asm/syscall.h>
33
3a523f5b 34#include "wrapper/tracepoint.h"
a90917c3 35#include "lttng-events.h"
259b6cb3 36
6333ace3 37#ifndef CONFIG_COMPAT
bfa949bf
MD
38# ifndef is_compat_task
39# define is_compat_task() (0)
40# endif
6333ace3
MD
41#endif
42
5b7ac358
MD
43enum sc_type {
44 SC_TYPE_ENTRY,
45 SC_TYPE_EXIT,
46 SC_TYPE_COMPAT_ENTRY,
47 SC_TYPE_COMPAT_EXIT,
48};
49
50#define SYSCALL_ENTRY_STR "syscall_entry_"
51#define COMPAT_SYSCALL_ENTRY_STR "compat_syscall_entry_"
52#define SYSCALL_EXIT_STR "syscall_exit_"
53#define COMPAT_SYSCALL_EXIT_STR "compat_syscall_exit_"
54
a93244f8 55static
2faf7d1b 56void syscall_entry_probe(void *__data, struct pt_regs *regs, long id);
5b7ac358
MD
57static
58void syscall_exit_probe(void *__data, struct pt_regs *regs, long ret);
259b6cb3 59
3a523f5b
MD
60/*
61 * Forward declarations for old kernels.
62 */
63struct mmsghdr;
64struct rlimit64;
65struct oldold_utsname;
66struct old_utsname;
67struct sel_arg_struct;
68struct mmap_arg_struct;
69
80f87dd2
MD
70#ifdef IA32_NR_syscalls
71#define NR_compat_syscalls IA32_NR_syscalls
72#else
73#define NR_compat_syscalls NR_syscalls
74#endif
75
259b6cb3
MD
76/*
77 * Create LTTng tracepoint probes.
78 */
79#define LTTNG_PACKAGE_BUILD
80#define CREATE_TRACE_POINTS
2655f9ad 81#define TP_MODULE_NOINIT
2f804c0a 82#define TRACE_INCLUDE_PATH ../instrumentation/syscalls/headers
259b6cb3 83
a93244f8
MD
84#define PARAMS(args...) args
85
5b7ac358
MD
86/* Handle unknown syscalls */
87#define TRACE_SYSTEM syscalls_unknown
88#include "instrumentation/syscalls/headers/syscalls_unknown.h"
89#undef TRACE_SYSTEM
90
fc4f7161
MD
91#define SC_ENTER
92
fc4f7161
MD
93#undef sc_exit
94#define sc_exit(...)
b75d00c4
MD
95#undef sc_in
96#define sc_in(...) __VA_ARGS__
97#undef sc_out
98#define sc_out(...)
99#undef sc_inout
100#define sc_inout(...) __VA_ARGS__
5b7ac358
MD
101
102/* Hijack probe callback for system call enter */
a93244f8 103#undef TP_PROBE_CB
259b6cb3 104#define TP_PROBE_CB(_template) &syscall_entry_probe
cb3ef14c 105#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
3bc29f0a 106 LTTNG_TRACEPOINT_EVENT(syscall_enter_##_name, PARAMS(_proto), PARAMS(_args), \
a93244f8 107 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
cb3ef14c
MD
108#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
109 LTTNG_TRACEPOINT_EVENT_CODE(syscall_enter_##_name, PARAMS(_proto), PARAMS(_args), \
110 PARAMS(_locvar), PARAMS(_code), \
7ca580f8 111 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
cb3ef14c 112#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
3bc29f0a 113 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_enter_##_name, PARAMS(_struct), PARAMS(_assign), \
a93244f8 114 PARAMS(_printk))
cb3ef14c 115#define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
3bc29f0a 116 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_enter_##_template, syscall_enter_##_name)
a93244f8 117#undef TRACE_SYSTEM
5b7ac358
MD
118#define TRACE_SYSTEM syscall_enter_integers
119#define TRACE_INCLUDE_FILE syscalls_integers
177b3692 120#include "instrumentation/syscalls/headers/syscalls_integers.h"
5b7ac358 121#undef TRACE_INCLUDE_FILE
a93244f8 122#undef TRACE_SYSTEM
5b7ac358
MD
123#define TRACE_SYSTEM syscall_enter_pointers
124#define TRACE_INCLUDE_FILE syscalls_pointers
177b3692 125#include "instrumentation/syscalls/headers/syscalls_pointers.h"
5b7ac358 126#undef TRACE_INCLUDE_FILE
a93244f8 127#undef TRACE_SYSTEM
cb3ef14c
MD
128#undef SC_LTTNG_TRACEPOINT_EVENT_CODE
129#undef SC_LTTNG_TRACEPOINT_EVENT
130#undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
131#undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
5b7ac358 132#undef TP_PROBE_CB
3bc29f0a
MD
133#undef _TRACE_SYSCALLS_INTEGERS_H
134#undef _TRACE_SYSCALLS_POINTERS_H
5b7ac358
MD
135
136/* Hijack probe callback for compat system call enter */
a93244f8 137#define TP_PROBE_CB(_template) &syscall_entry_probe
cb3ef14c 138#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
3bc29f0a 139 LTTNG_TRACEPOINT_EVENT(compat_syscall_enter_##_name, PARAMS(_proto), PARAMS(_args), \
cb3ef14c 140 PARAMS(_struct), PARAMS(_assign), \
a93244f8 141 PARAMS(_printk))
cb3ef14c 142#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
3bc29f0a 143 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_enter_##_name, PARAMS(_proto), PARAMS(_args), \
cb3ef14c 144 PARAMS(_locvar), PARAMS(_code), \
7ca580f8 145 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
cb3ef14c 146#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
3bc29f0a 147 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_enter_##_name, PARAMS(_struct), \
5b7ac358 148 PARAMS(_assign), PARAMS(_printk))
cb3ef14c 149#define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
3bc29f0a 150 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_enter_##_template, \
5b7ac358
MD
151 compat_syscall_enter_##_name)
152#define TRACE_SYSTEM compat_syscall_enter_integers
153#define TRACE_INCLUDE_FILE compat_syscalls_integers
154#include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
155#undef TRACE_INCLUDE_FILE
156#undef TRACE_SYSTEM
157#define TRACE_SYSTEM compat_syscall_enter_pointers
158#define TRACE_INCLUDE_FILE compat_syscalls_pointers
159#include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
160#undef TRACE_INCLUDE_FILE
161#undef TRACE_SYSTEM
cb3ef14c
MD
162#undef SC_LTTNG_TRACEPOINT_EVENT_CODE
163#undef SC_LTTNG_TRACEPOINT_EVENT
164#undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
165#undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
5b7ac358 166#undef TP_PROBE_CB
3bc29f0a
MD
167#undef _TRACE_SYSCALLS_INTEGERS_H
168#undef _TRACE_SYSCALLS_POINTERS_H
5b7ac358 169
fc4f7161
MD
170#undef SC_ENTER
171
172#define SC_EXIT
173
fc4f7161
MD
174#undef sc_exit
175#define sc_exit(...) __VA_ARGS__
b75d00c4
MD
176#undef sc_in
177#define sc_in(...)
178#undef sc_out
179#define sc_out(...) __VA_ARGS__
180#undef sc_inout
181#define sc_inout(...) __VA_ARGS__
5b7ac358
MD
182
183/* Hijack probe callback for system call exit */
184#define TP_PROBE_CB(_template) &syscall_exit_probe
cb3ef14c 185#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
3bc29f0a 186 LTTNG_TRACEPOINT_EVENT(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
5b7ac358 187 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
cb3ef14c 188#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
3bc29f0a 189 LTTNG_TRACEPOINT_EVENT_CODE(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
cb3ef14c 190 PARAMS(_locvar), PARAMS(_code), \
7ca580f8 191 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
cb3ef14c 192#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
3bc29f0a 193 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_exit_##_name, PARAMS(_struct), \
5b7ac358 194 PARAMS(_assign), PARAMS(_printk))
cb3ef14c
MD
195#define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
196 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_exit_##_template, \
5b7ac358
MD
197 syscall_exit_##_name)
198#define TRACE_SYSTEM syscall_exit_integers
199#define TRACE_INCLUDE_FILE syscalls_integers
200#include "instrumentation/syscalls/headers/syscalls_integers.h"
201#undef TRACE_INCLUDE_FILE
202#undef TRACE_SYSTEM
203#define TRACE_SYSTEM syscall_exit_pointers
204#define TRACE_INCLUDE_FILE syscalls_pointers
205#include "instrumentation/syscalls/headers/syscalls_pointers.h"
206#undef TRACE_INCLUDE_FILE
207#undef TRACE_SYSTEM
cb3ef14c
MD
208#undef SC_LTTNG_TRACEPOINT_EVENT_CODE
209#undef SC_LTTNG_TRACEPOINT_EVENT
210#undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
211#undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
5b7ac358 212#undef TP_PROBE_CB
3bc29f0a
MD
213#undef _TRACE_SYSCALLS_INTEGERS_H
214#undef _TRACE_SYSCALLS_POINTERS_H
5b7ac358
MD
215
216
217/* Hijack probe callback for compat system call exit */
218#define TP_PROBE_CB(_template) &syscall_exit_probe
cb3ef14c 219#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
3bc29f0a 220 LTTNG_TRACEPOINT_EVENT(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
5b7ac358 221 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
cb3ef14c 222#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
3bc29f0a 223 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
cb3ef14c 224 PARAMS(_locvar), PARAMS(_code), \
7ca580f8 225 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
cb3ef14c 226#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
3bc29f0a 227 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_exit_##_name, PARAMS(_struct), \
a93244f8 228 PARAMS(_assign), PARAMS(_printk))
cb3ef14c 229#define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
3bc29f0a 230 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_exit_##_template, \
5b7ac358
MD
231 compat_syscall_exit_##_name)
232#define TRACE_SYSTEM compat_syscall_exit_integers
233#define TRACE_INCLUDE_FILE compat_syscalls_integers
a93244f8 234#include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
5b7ac358 235#undef TRACE_INCLUDE_FILE
a93244f8 236#undef TRACE_SYSTEM
5b7ac358
MD
237#define TRACE_SYSTEM compat_syscall_exit_pointers
238#define TRACE_INCLUDE_FILE compat_syscalls_pointers
a93244f8 239#include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
5b7ac358 240#undef TRACE_INCLUDE_FILE
a93244f8 241#undef TRACE_SYSTEM
cb3ef14c
MD
242#undef SC_LTTNG_TRACEPOINT_EVENT_CODE
243#undef SC_LTTNG_TRACEPOINT_EVENT
244#undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
245#undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
a93244f8 246#undef TP_PROBE_CB
3bc29f0a
MD
247#undef _TRACE_SYSCALLS_INTEGERS_H
248#undef _TRACE_SYSCALLS_POINTERS_H
5b7ac358 249
fc4f7161 250#undef SC_EXIT
259b6cb3 251
2655f9ad 252#undef TP_MODULE_NOINIT
259b6cb3
MD
253#undef LTTNG_PACKAGE_BUILD
254#undef CREATE_TRACE_POINTS
255
a93244f8
MD
256struct trace_syscall_entry {
257 void *func;
258 const struct lttng_event_desc *desc;
259 const struct lttng_event_field *fields;
260 unsigned int nrargs;
261};
262
263#define CREATE_SYSCALL_TABLE
264
fc4f7161
MD
265#define SC_ENTER
266
267#undef sc_exit
268#define sc_exit(...)
269
259b6cb3 270#undef TRACE_SYSCALL_TABLE
f7bdf4db 271#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
259b6cb3 272 [ _nr ] = { \
5b7ac358 273 .func = __event_probe__syscall_enter_##_template, \
259b6cb3 274 .nrargs = (_nrargs), \
5b7ac358
MD
275 .fields = __event_fields___syscall_enter_##_template, \
276 .desc = &__event_desc___syscall_enter_##_name, \
259b6cb3
MD
277 },
278
5b7ac358 279/* Syscall enter tracing table */
49c50022 280static const struct trace_syscall_entry sc_table[] = {
177b3692
MD
281#include "instrumentation/syscalls/headers/syscalls_integers.h"
282#include "instrumentation/syscalls/headers/syscalls_pointers.h"
259b6cb3
MD
283};
284
a93244f8
MD
285#undef TRACE_SYSCALL_TABLE
286#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
287 [ _nr ] = { \
5b7ac358 288 .func = __event_probe__compat_syscall_enter_##_template, \
a93244f8 289 .nrargs = (_nrargs), \
5b7ac358
MD
290 .fields = __event_fields___compat_syscall_enter_##_template, \
291 .desc = &__event_desc___compat_syscall_enter_##_name, \
a93244f8
MD
292 },
293
5b7ac358 294/* Compat syscall enter table */
a93244f8
MD
295const struct trace_syscall_entry compat_sc_table[] = {
296#include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
297#include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
298};
259b6cb3 299
fc4f7161
MD
300#undef SC_ENTER
301
302#define SC_EXIT
303
304#undef sc_exit
305#define sc_exit(...) __VA_ARGS__
306
5b7ac358
MD
307#undef TRACE_SYSCALL_TABLE
308#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
309 [ _nr ] = { \
310 .func = __event_probe__syscall_exit_##_template, \
311 .nrargs = (_nrargs), \
312 .fields = __event_fields___syscall_exit_##_template, \
313 .desc = &__event_desc___syscall_exit_##_name, \
314 },
315
316/* Syscall exit table */
317static const struct trace_syscall_entry sc_exit_table[] = {
318#include "instrumentation/syscalls/headers/syscalls_integers.h"
319#include "instrumentation/syscalls/headers/syscalls_pointers.h"
320};
321
322#undef TRACE_SYSCALL_TABLE
323#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
324 [ _nr ] = { \
325 .func = __event_probe__compat_syscall_exit_##_template, \
326 .nrargs = (_nrargs), \
327 .fields = __event_fields___compat_syscall_exit_##_template, \
328 .desc = &__event_desc___compat_syscall_exit_##_name, \
329 },
330
331/* Compat syscall exit table */
332const struct trace_syscall_entry compat_sc_exit_table[] = {
333#include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
334#include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
335};
336
fc4f7161
MD
337#undef SC_EXIT
338
a93244f8 339#undef CREATE_SYSCALL_TABLE
2faf7d1b 340
80f87dd2
MD
341struct lttng_syscall_filter {
342 DECLARE_BITMAP(sc, NR_syscalls);
343 DECLARE_BITMAP(sc_compat, NR_compat_syscalls);
344};
345
a90917c3 346static void syscall_entry_unknown(struct lttng_event *event,
f405cfce
MD
347 struct pt_regs *regs, unsigned int id)
348{
349 unsigned long args[UNKNOWN_SYSCALL_NRARGS];
f405cfce 350
f405cfce 351 syscall_get_arguments(current, regs, 0, UNKNOWN_SYSCALL_NRARGS, args);
a93244f8 352 if (unlikely(is_compat_task()))
5b7ac358 353 __event_probe__compat_syscall_enter_unknown(event, id, args);
a93244f8 354 else
5b7ac358 355 __event_probe__syscall_enter_unknown(event, id, args);
f405cfce
MD
356}
357
2faf7d1b 358void syscall_entry_probe(void *__data, struct pt_regs *regs, long id)
259b6cb3 359{
a90917c3
MD
360 struct lttng_channel *chan = __data;
361 struct lttng_event *event, *unknown_event;
49c50022
MD
362 const struct trace_syscall_entry *table, *entry;
363 size_t table_len;
259b6cb3 364
b76dc1a0 365 if (unlikely(is_compat_task())) {
80f87dd2
MD
366 struct lttng_syscall_filter *filter;
367
368 filter = rcu_dereference(chan->sc_filter);
369 if (filter) {
370 if (id >= NR_compat_syscalls
371 || !test_bit(id, filter->sc_compat)) {
372 /* System call filtered out. */
373 return;
374 }
375 }
49c50022 376 table = compat_sc_table;
a93244f8 377 table_len = ARRAY_SIZE(compat_sc_table);
49c50022
MD
378 unknown_event = chan->sc_compat_unknown;
379 } else {
80f87dd2
MD
380 struct lttng_syscall_filter *filter;
381
382 filter = rcu_dereference(chan->sc_filter);
383 if (filter) {
384 if (id >= NR_syscalls
385 || !test_bit(id, filter->sc)) {
386 /* System call filtered out. */
387 return;
388 }
389 }
49c50022
MD
390 table = sc_table;
391 table_len = ARRAY_SIZE(sc_table);
392 unknown_event = chan->sc_unknown;
b76dc1a0 393 }
49c50022
MD
394 if (unlikely(id >= table_len)) {
395 syscall_entry_unknown(unknown_event, regs, id);
259b6cb3 396 return;
f405cfce 397 }
49c50022
MD
398 if (unlikely(is_compat_task()))
399 event = chan->compat_sc_table[id];
400 else
401 event = chan->sc_table[id];
f405cfce 402 if (unlikely(!event)) {
49c50022 403 syscall_entry_unknown(unknown_event, regs, id);
f405cfce
MD
404 return;
405 }
49c50022 406 entry = &table[id];
f405cfce 407 WARN_ON_ONCE(!entry);
259b6cb3
MD
408
409 switch (entry->nrargs) {
410 case 0:
411 {
412 void (*fptr)(void *__data) = entry->func;
413
414 fptr(event);
415 break;
416 }
417 case 1:
418 {
419 void (*fptr)(void *__data, unsigned long arg0) = entry->func;
420 unsigned long args[1];
421
422 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
423 fptr(event, args[0]);
424 break;
425 }
426 case 2:
427 {
428 void (*fptr)(void *__data,
429 unsigned long arg0,
430 unsigned long arg1) = entry->func;
431 unsigned long args[2];
432
433 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
434 fptr(event, args[0], args[1]);
435 break;
436 }
437 case 3:
438 {
439 void (*fptr)(void *__data,
440 unsigned long arg0,
441 unsigned long arg1,
442 unsigned long arg2) = entry->func;
443 unsigned long args[3];
444
445 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
446 fptr(event, args[0], args[1], args[2]);
447 break;
448 }
449 case 4:
450 {
451 void (*fptr)(void *__data,
452 unsigned long arg0,
453 unsigned long arg1,
454 unsigned long arg2,
455 unsigned long arg3) = entry->func;
456 unsigned long args[4];
457
458 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
459 fptr(event, args[0], args[1], args[2], args[3]);
460 break;
461 }
462 case 5:
463 {
464 void (*fptr)(void *__data,
465 unsigned long arg0,
466 unsigned long arg1,
467 unsigned long arg2,
468 unsigned long arg3,
469 unsigned long arg4) = entry->func;
470 unsigned long args[5];
471
472 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
473 fptr(event, args[0], args[1], args[2], args[3], args[4]);
474 break;
475 }
476 case 6:
477 {
478 void (*fptr)(void *__data,
479 unsigned long arg0,
480 unsigned long arg1,
481 unsigned long arg2,
482 unsigned long arg3,
483 unsigned long arg4,
484 unsigned long arg5) = entry->func;
485 unsigned long args[6];
486
487 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
488 fptr(event, args[0], args[1], args[2],
489 args[3], args[4], args[5]);
490 break;
491 }
492 default:
493 break;
494 }
495}
496
5b7ac358
MD
497static void syscall_exit_unknown(struct lttng_event *event,
498 struct pt_regs *regs, unsigned int id, long ret)
499{
500 unsigned long args[UNKNOWN_SYSCALL_NRARGS];
501
502 syscall_get_arguments(current, regs, 0, UNKNOWN_SYSCALL_NRARGS, args);
503 if (unlikely(is_compat_task()))
504 __event_probe__compat_syscall_exit_unknown(event, id, ret,
505 args);
506 else
507 __event_probe__syscall_exit_unknown(event, id, ret, args);
508}
509
510void syscall_exit_probe(void *__data, struct pt_regs *regs, long ret)
511{
512 struct lttng_channel *chan = __data;
513 struct lttng_event *event, *unknown_event;
514 const struct trace_syscall_entry *table, *entry;
515 size_t table_len;
516 long id;
517
518 id = syscall_get_nr(current, regs);
519 if (unlikely(is_compat_task())) {
520 struct lttng_syscall_filter *filter;
521
522 filter = rcu_dereference(chan->sc_filter);
523 if (filter) {
524 if (id >= NR_compat_syscalls
525 || !test_bit(id, filter->sc_compat)) {
526 /* System call filtered out. */
527 return;
528 }
529 }
530 table = compat_sc_exit_table;
531 table_len = ARRAY_SIZE(compat_sc_exit_table);
532 unknown_event = chan->compat_sc_exit_unknown;
533 } else {
534 struct lttng_syscall_filter *filter;
535
536 filter = rcu_dereference(chan->sc_filter);
537 if (filter) {
538 if (id >= NR_syscalls
539 || !test_bit(id, filter->sc)) {
540 /* System call filtered out. */
541 return;
542 }
543 }
544 table = sc_exit_table;
545 table_len = ARRAY_SIZE(sc_exit_table);
546 unknown_event = chan->sc_exit_unknown;
547 }
548 if (unlikely(id >= table_len)) {
549 syscall_exit_unknown(unknown_event, regs, id, ret);
550 return;
551 }
552 if (unlikely(is_compat_task()))
553 event = chan->compat_sc_exit_table[id];
554 else
555 event = chan->sc_exit_table[id];
556 if (unlikely(!event)) {
557 syscall_exit_unknown(unknown_event, regs, id, ret);
558 return;
559 }
560 entry = &table[id];
561 WARN_ON_ONCE(!entry);
562
563 switch (entry->nrargs) {
564 case 0:
565 {
fc4f7161 566 void (*fptr)(void *__data, long ret) = entry->func;
5b7ac358 567
fc4f7161 568 fptr(event, ret);
5b7ac358
MD
569 break;
570 }
571 case 1:
572 {
573 void (*fptr)(void *__data,
fc4f7161 574 long ret,
5b7ac358
MD
575 unsigned long arg0) = entry->func;
576 unsigned long args[1];
577
578 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
fc4f7161 579 fptr(event, ret, args[0]);
5b7ac358
MD
580 break;
581 }
582 case 2:
583 {
584 void (*fptr)(void *__data,
fc4f7161 585 long ret,
5b7ac358
MD
586 unsigned long arg0,
587 unsigned long arg1) = entry->func;
588 unsigned long args[2];
589
590 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
fc4f7161 591 fptr(event, ret, args[0], args[1]);
5b7ac358
MD
592 break;
593 }
594 case 3:
595 {
596 void (*fptr)(void *__data,
fc4f7161 597 long ret,
5b7ac358
MD
598 unsigned long arg0,
599 unsigned long arg1,
600 unsigned long arg2) = entry->func;
601 unsigned long args[3];
602
603 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
fc4f7161 604 fptr(event, ret, args[0], args[1], args[2]);
5b7ac358
MD
605 break;
606 }
607 case 4:
608 {
609 void (*fptr)(void *__data,
fc4f7161 610 long ret,
5b7ac358
MD
611 unsigned long arg0,
612 unsigned long arg1,
613 unsigned long arg2,
614 unsigned long arg3) = entry->func;
615 unsigned long args[4];
616
617 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
fc4f7161 618 fptr(event, ret, args[0], args[1], args[2], args[3]);
5b7ac358
MD
619 break;
620 }
621 case 5:
622 {
623 void (*fptr)(void *__data,
fc4f7161 624 long ret,
5b7ac358
MD
625 unsigned long arg0,
626 unsigned long arg1,
627 unsigned long arg2,
628 unsigned long arg3,
629 unsigned long arg4) = entry->func;
630 unsigned long args[5];
631
632 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
fc4f7161 633 fptr(event, ret, args[0], args[1], args[2], args[3], args[4]);
5b7ac358
MD
634 break;
635 }
636 case 6:
637 {
638 void (*fptr)(void *__data,
fc4f7161 639 long ret,
5b7ac358
MD
640 unsigned long arg0,
641 unsigned long arg1,
642 unsigned long arg2,
643 unsigned long arg3,
644 unsigned long arg4,
645 unsigned long arg5) = entry->func;
646 unsigned long args[6];
647
648 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
fc4f7161 649 fptr(event, ret, args[0], args[1], args[2],
5b7ac358
MD
650 args[3], args[4], args[5]);
651 break;
652 }
653 default:
654 break;
655 }
656}
657
2a0c4816 658/* noinline to diminish caller stack size */
49c50022
MD
659static
660int fill_table(const struct trace_syscall_entry *table, size_t table_len,
5b7ac358
MD
661 struct lttng_event **chan_table, struct lttng_channel *chan,
662 void *filter, enum sc_type type)
259b6cb3 663{
2a0c4816 664 const struct lttng_event_desc *desc;
259b6cb3 665 unsigned int i;
49c50022
MD
666
667 /* Allocate events for each syscall, insert into table */
668 for (i = 0; i < table_len; i++) {
669 struct lttng_kernel_event ev;
2a0c4816 670 desc = table[i].desc;
49c50022
MD
671
672 if (!desc) {
673 /* Unknown syscall */
674 continue;
675 }
676 /*
677 * Skip those already populated by previous failed
678 * register for this channel.
679 */
680 if (chan_table[i])
681 continue;
682 memset(&ev, 0, sizeof(ev));
5b7ac358
MD
683 switch (type) {
684 case SC_TYPE_ENTRY:
685 strncpy(ev.name, SYSCALL_ENTRY_STR,
686 LTTNG_KERNEL_SYM_NAME_LEN);
687 break;
688 case SC_TYPE_EXIT:
689 strncpy(ev.name, SYSCALL_EXIT_STR,
690 LTTNG_KERNEL_SYM_NAME_LEN);
691 break;
692 case SC_TYPE_COMPAT_ENTRY:
693 strncpy(ev.name, COMPAT_SYSCALL_ENTRY_STR,
694 LTTNG_KERNEL_SYM_NAME_LEN);
695 break;
696 case SC_TYPE_COMPAT_EXIT:
697 strncpy(ev.name, COMPAT_SYSCALL_EXIT_STR,
698 LTTNG_KERNEL_SYM_NAME_LEN);
699 break;
700 default:
701 BUG_ON(1);
702 break;
703 }
704 strncat(ev.name, desc->name,
705 LTTNG_KERNEL_SYM_NAME_LEN - strlen(ev.name) - 1);
f8695253 706 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
49c50022 707 ev.instrumentation = LTTNG_KERNEL_NOOP;
a90917c3 708 chan_table[i] = lttng_event_create(chan, &ev, filter,
49c50022 709 desc);
abc0446a
MD
710 WARN_ON_ONCE(!chan_table[i]);
711 if (IS_ERR(chan_table[i])) {
49c50022
MD
712 /*
713 * If something goes wrong in event registration
714 * after the first one, we have no choice but to
715 * leave the previous events in there, until
716 * deleted by session teardown.
717 */
abc0446a 718 return PTR_ERR(chan_table[i]);
49c50022
MD
719 }
720 }
721 return 0;
722}
723
a90917c3 724int lttng_syscalls_register(struct lttng_channel *chan, void *filter)
49c50022 725{
2a0c4816 726 struct lttng_kernel_event ev;
259b6cb3
MD
727 int ret;
728
729 wrapper_vmalloc_sync_all();
259b6cb3
MD
730
731 if (!chan->sc_table) {
732 /* create syscall table mapping syscall to events */
a90917c3 733 chan->sc_table = kzalloc(sizeof(struct lttng_event *)
259b6cb3
MD
734 * ARRAY_SIZE(sc_table), GFP_KERNEL);
735 if (!chan->sc_table)
736 return -ENOMEM;
737 }
5b7ac358
MD
738 if (!chan->sc_exit_table) {
739 /* create syscall table mapping syscall to events */
740 chan->sc_exit_table = kzalloc(sizeof(struct lttng_event *)
741 * ARRAY_SIZE(sc_exit_table), GFP_KERNEL);
742 if (!chan->sc_exit_table)
743 return -ENOMEM;
744 }
745
259b6cb3 746
49c50022
MD
747#ifdef CONFIG_COMPAT
748 if (!chan->compat_sc_table) {
749 /* create syscall table mapping compat syscall to events */
a90917c3 750 chan->compat_sc_table = kzalloc(sizeof(struct lttng_event *)
a93244f8 751 * ARRAY_SIZE(compat_sc_table), GFP_KERNEL);
49c50022
MD
752 if (!chan->compat_sc_table)
753 return -ENOMEM;
754 }
5b7ac358
MD
755
756 if (!chan->compat_sc_exit_table) {
757 /* create syscall table mapping compat syscall to events */
758 chan->compat_sc_exit_table = kzalloc(sizeof(struct lttng_event *)
759 * ARRAY_SIZE(compat_sc_exit_table), GFP_KERNEL);
760 if (!chan->compat_sc_exit_table)
761 return -ENOMEM;
762 }
49c50022 763#endif
f405cfce 764 if (!chan->sc_unknown) {
f405cfce 765 const struct lttng_event_desc *desc =
5b7ac358 766 &__event_desc___syscall_enter_unknown;
2f804c0a 767
f405cfce 768 memset(&ev, 0, sizeof(ev));
f8695253
MD
769 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
770 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
f405cfce 771 ev.instrumentation = LTTNG_KERNEL_NOOP;
a90917c3 772 chan->sc_unknown = lttng_event_create(chan, &ev, filter,
f405cfce 773 desc);
abc0446a
MD
774 WARN_ON_ONCE(!chan->sc_unknown);
775 if (IS_ERR(chan->sc_unknown)) {
776 return PTR_ERR(chan->sc_unknown);
f405cfce
MD
777 }
778 }
779
b76dc1a0 780 if (!chan->sc_compat_unknown) {
b76dc1a0 781 const struct lttng_event_desc *desc =
5b7ac358 782 &__event_desc___compat_syscall_enter_unknown;
b76dc1a0
MD
783
784 memset(&ev, 0, sizeof(ev));
f8695253
MD
785 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
786 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
b76dc1a0 787 ev.instrumentation = LTTNG_KERNEL_NOOP;
a90917c3 788 chan->sc_compat_unknown = lttng_event_create(chan, &ev, filter,
b76dc1a0 789 desc);
abc0446a
MD
790 WARN_ON_ONCE(!chan->sc_unknown);
791 if (IS_ERR(chan->sc_compat_unknown)) {
792 return PTR_ERR(chan->sc_compat_unknown);
b76dc1a0
MD
793 }
794 }
795
5b7ac358 796 if (!chan->compat_sc_exit_unknown) {
2f804c0a 797 const struct lttng_event_desc *desc =
5b7ac358 798 &__event_desc___compat_syscall_exit_unknown;
2f804c0a
MD
799
800 memset(&ev, 0, sizeof(ev));
f8695253
MD
801 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
802 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
2f804c0a 803 ev.instrumentation = LTTNG_KERNEL_NOOP;
5b7ac358
MD
804 chan->compat_sc_exit_unknown = lttng_event_create(chan, &ev,
805 filter, desc);
806 WARN_ON_ONCE(!chan->compat_sc_exit_unknown);
807 if (IS_ERR(chan->compat_sc_exit_unknown)) {
808 return PTR_ERR(chan->compat_sc_exit_unknown);
809 }
810 }
811
812 if (!chan->sc_exit_unknown) {
813 const struct lttng_event_desc *desc =
814 &__event_desc___syscall_exit_unknown;
815
816 memset(&ev, 0, sizeof(ev));
817 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
818 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
819 ev.instrumentation = LTTNG_KERNEL_NOOP;
820 chan->sc_exit_unknown = lttng_event_create(chan, &ev, filter,
2f804c0a 821 desc);
5b7ac358
MD
822 WARN_ON_ONCE(!chan->sc_exit_unknown);
823 if (IS_ERR(chan->sc_exit_unknown)) {
824 return PTR_ERR(chan->sc_exit_unknown);
2f804c0a
MD
825 }
826 }
827
49c50022 828 ret = fill_table(sc_table, ARRAY_SIZE(sc_table),
5b7ac358
MD
829 chan->sc_table, chan, filter, SC_TYPE_ENTRY);
830 if (ret)
831 return ret;
832 ret = fill_table(sc_exit_table, ARRAY_SIZE(sc_exit_table),
833 chan->sc_exit_table, chan, filter, SC_TYPE_EXIT);
49c50022
MD
834 if (ret)
835 return ret;
5b7ac358 836
49c50022 837#ifdef CONFIG_COMPAT
a93244f8 838 ret = fill_table(compat_sc_table, ARRAY_SIZE(compat_sc_table),
5b7ac358
MD
839 chan->compat_sc_table, chan, filter,
840 SC_TYPE_COMPAT_ENTRY);
841 if (ret)
842 return ret;
843 ret = fill_table(compat_sc_exit_table, ARRAY_SIZE(compat_sc_exit_table),
844 chan->compat_sc_exit_table, chan, filter,
845 SC_TYPE_COMPAT_EXIT);
49c50022
MD
846 if (ret)
847 return ret;
848#endif
80f87dd2
MD
849 if (!chan->sys_enter_registered) {
850 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
851 (void *) syscall_entry_probe, chan);
852 if (ret)
853 return ret;
854 chan->sys_enter_registered = 1;
855 }
63728b02
MD
856 /*
857 * We change the name of sys_exit tracepoint due to namespace
858 * conflict with sys_exit syscall entry.
859 */
80f87dd2
MD
860 if (!chan->sys_exit_registered) {
861 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
5b7ac358 862 (void *) syscall_exit_probe, chan);
80f87dd2
MD
863 if (ret) {
864 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
865 (void *) syscall_entry_probe, chan));
866 return ret;
867 }
868 chan->sys_exit_registered = 1;
63728b02 869 }
259b6cb3
MD
870 return ret;
871}
872
873/*
874 * Only called at session destruction.
875 */
a90917c3 876int lttng_syscalls_unregister(struct lttng_channel *chan)
259b6cb3
MD
877{
878 int ret;
879
880 if (!chan->sc_table)
881 return 0;
80f87dd2
MD
882 if (chan->sys_enter_registered) {
883 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
5b7ac358 884 (void *) syscall_exit_probe, chan);
80f87dd2
MD
885 if (ret)
886 return ret;
887 chan->sys_enter_registered = 0;
888 }
889 if (chan->sys_exit_registered) {
890 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
891 (void *) syscall_entry_probe, chan);
892 if (ret)
893 return ret;
894 chan->sys_exit_registered = 0;
895 }
a90917c3 896 /* lttng_event destroy will be performed by lttng_session_destroy() */
259b6cb3 897 kfree(chan->sc_table);
5b7ac358 898 kfree(chan->sc_exit_table);
49c50022
MD
899#ifdef CONFIG_COMPAT
900 kfree(chan->compat_sc_table);
5b7ac358 901 kfree(chan->compat_sc_exit_table);
49c50022 902#endif
80f87dd2
MD
903 kfree(chan->sc_filter);
904 return 0;
905}
906
907static
908int get_syscall_nr(const char *syscall_name)
909{
910 int syscall_nr = -1;
911 int i;
912
913 for (i = 0; i < ARRAY_SIZE(sc_table); i++) {
914 const struct trace_syscall_entry *entry;
5b7ac358 915 const char *it_name;
80f87dd2
MD
916
917 entry = &sc_table[i];
918 if (!entry->desc)
919 continue;
5b7ac358
MD
920 it_name = entry->desc->name;
921 it_name += strlen(SYSCALL_ENTRY_STR);
922 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
923 syscall_nr = i;
924 break;
925 }
926 }
927 return syscall_nr;
928}
929
930static
931int get_compat_syscall_nr(const char *syscall_name)
932{
933 int syscall_nr = -1;
934 int i;
935
936 for (i = 0; i < ARRAY_SIZE(compat_sc_table); i++) {
937 const struct trace_syscall_entry *entry;
5b7ac358 938 const char *it_name;
80f87dd2
MD
939
940 entry = &compat_sc_table[i];
941 if (!entry->desc)
942 continue;
5b7ac358
MD
943 it_name = entry->desc->name;
944 it_name += strlen(COMPAT_SYSCALL_ENTRY_STR);
945 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
946 syscall_nr = i;
947 break;
948 }
949 }
950 return syscall_nr;
951}
952
953int lttng_syscall_filter_enable(struct lttng_channel *chan,
954 const char *name)
955{
956 int syscall_nr, compat_syscall_nr, ret;
957 struct lttng_syscall_filter *filter;
958
959 WARN_ON_ONCE(!chan->sc_table);
960
961 if (!name) {
962 /* Enable all system calls by removing filter */
963 if (chan->sc_filter) {
964 filter = chan->sc_filter;
965 rcu_assign_pointer(chan->sc_filter, NULL);
966 synchronize_trace();
967 kfree(filter);
968 }
969 chan->syscall_all = 1;
970 return 0;
971 }
972
973 if (!chan->sc_filter) {
974 if (chan->syscall_all) {
975 /*
976 * All syscalls are already enabled.
977 */
978 return -EEXIST;
979 }
980 filter = kzalloc(sizeof(struct lttng_syscall_filter),
981 GFP_KERNEL);
982 if (!filter)
983 return -ENOMEM;
984 } else {
985 filter = chan->sc_filter;
986 }
987 syscall_nr = get_syscall_nr(name);
988 compat_syscall_nr = get_compat_syscall_nr(name);
989 if (syscall_nr < 0 && compat_syscall_nr < 0) {
990 ret = -ENOENT;
991 goto error;
992 }
993 if (syscall_nr >= 0) {
994 if (test_bit(syscall_nr, filter->sc)) {
995 ret = -EEXIST;
996 goto error;
997 }
998 bitmap_set(filter->sc, syscall_nr, 1);
999 }
1000 if (compat_syscall_nr >= 0) {
1001 if (test_bit(compat_syscall_nr, filter->sc_compat)) {
1002 ret = -EEXIST;
1003 goto error;
1004 }
1005 bitmap_set(filter->sc_compat, compat_syscall_nr, 1);
1006 }
1007 if (!chan->sc_filter)
1008 rcu_assign_pointer(chan->sc_filter, filter);
1009 return 0;
1010
1011error:
1012 if (!chan->sc_filter)
1013 kfree(filter);
1014 return ret;
1015}
1016
1017int lttng_syscall_filter_disable(struct lttng_channel *chan,
1018 const char *name)
1019{
1020 int syscall_nr, compat_syscall_nr, ret;
1021 struct lttng_syscall_filter *filter;
1022
1023 WARN_ON_ONCE(!chan->sc_table);
1024
1025 if (!chan->sc_filter) {
1026 filter = kzalloc(sizeof(struct lttng_syscall_filter),
1027 GFP_KERNEL);
1028 if (!filter)
1029 return -ENOMEM;
1030 /* Trace all system calls, then apply disable. */
1031 bitmap_set(filter->sc, 0, NR_syscalls);
1032 bitmap_set(filter->sc_compat, 0, NR_compat_syscalls);
1033 } else {
1034 filter = chan->sc_filter;
1035 }
1036
72814741
MD
1037 if (!name) {
1038 /* Disable all system calls */
1039 bitmap_clear(filter->sc, 0, NR_syscalls);
1040 bitmap_clear(filter->sc_compat, 0, NR_compat_syscalls);
1041 goto apply_filter;
1042 }
80f87dd2
MD
1043 syscall_nr = get_syscall_nr(name);
1044 compat_syscall_nr = get_compat_syscall_nr(name);
1045 if (syscall_nr < 0 && compat_syscall_nr < 0) {
1046 ret = -ENOENT;
1047 goto error;
1048 }
1049 if (syscall_nr >= 0) {
1050 if (!test_bit(syscall_nr, chan->sc_filter->sc)) {
1051 ret = -EEXIST;
1052 goto error;
1053 }
1054 bitmap_clear(chan->sc_filter->sc, syscall_nr, 1);
1055 }
1056 if (compat_syscall_nr >= 0) {
1057 if (!test_bit(compat_syscall_nr, chan->sc_filter->sc_compat)) {
1058 ret = -EEXIST;
1059 goto error;
1060 }
1061 bitmap_clear(chan->sc_filter->sc_compat, compat_syscall_nr, 1);
1062 }
72814741 1063apply_filter:
80f87dd2
MD
1064 if (!chan->sc_filter)
1065 rcu_assign_pointer(chan->sc_filter, filter);
1066 chan->syscall_all = 0;
259b6cb3 1067 return 0;
80f87dd2
MD
1068
1069error:
1070 if (!chan->sc_filter)
1071 kfree(filter);
1072 return ret;
259b6cb3 1073}
2d2464bd
MD
1074
1075static
1076const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos)
1077{
1078 const struct trace_syscall_entry *entry;
1079 int iter = 0;
1080
1081 for (entry = sc_table;
1082 entry < sc_table + ARRAY_SIZE(sc_table);
1083 entry++) {
1084 if (iter++ >= *pos)
1085 return entry;
1086 }
1087 for (entry = compat_sc_table;
1088 entry < compat_sc_table + ARRAY_SIZE(compat_sc_table);
1089 entry++) {
1090 if (iter++ >= *pos)
1091 return entry;
1092 }
1093 /* End of list */
1094 return NULL;
1095}
1096
1097static
1098void *syscall_list_start(struct seq_file *m, loff_t *pos)
1099{
1100 return (void *) syscall_list_get_entry(pos);
1101}
1102
1103static
1104void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos)
1105{
1106 (*ppos)++;
1107 return (void *) syscall_list_get_entry(ppos);
1108}
1109
1110static
1111void syscall_list_stop(struct seq_file *m, void *p)
1112{
1113}
1114
1115static
1116int syscall_list_show(struct seq_file *m, void *p)
1117{
1118 const struct trace_syscall_entry *table, *entry = p;
1119 unsigned int bitness;
1120
1121 if (entry >= sc_table && entry < sc_table + ARRAY_SIZE(sc_table)) {
1122 bitness = BITS_PER_LONG;
1123 table = sc_table;
1124 } else {
1125 bitness = 32;
1126 table = compat_sc_table;
1127 WARN_ON_ONCE(!(entry >= compat_sc_table
1128 && entry < compat_sc_table + ARRAY_SIZE(compat_sc_table)));
1129 }
9f5226f0
MD
1130 seq_printf(m, "syscall { id = %u; name = %s; bitness = %u; };\n",
1131 entry - table,
2d2464bd
MD
1132 entry->desc->name,
1133 bitness);
1134 return 0;
1135}
1136
1137static
1138const struct seq_operations lttng_syscall_list_seq_ops = {
1139 .start = syscall_list_start,
1140 .next = syscall_list_next,
1141 .stop = syscall_list_stop,
1142 .show = syscall_list_show,
1143};
1144
1145static
1146int lttng_syscall_list_open(struct inode *inode, struct file *file)
1147{
1148 return seq_open(file, &lttng_syscall_list_seq_ops);
1149}
1150
1151const struct file_operations lttng_syscall_list_fops = {
1152 .owner = THIS_MODULE,
1153 .open = lttng_syscall_list_open,
1154 .read = seq_read,
1155 .llseek = seq_lseek,
1156 .release = seq_release,
1157};
This page took 0.077751 seconds and 4 git commands to generate.