3 #include <linux/slab.h>
4 #include <linux/kernel.h>
5 #include <linux/module.h>
7 #include <linux/perf_event.h>
8 #include <asm/syscall.h>
14 static int sys_refcount_enter;
15 static int sys_refcount_exit;
45 .reg = syscall_enter_register,
46 .define_fields = syscall_enter_define_fields,
47 .get_fields = syscall_get_enter_fields,
53 .reg = syscall_exit_register,
54 .define_fields = syscall_exit_define_fields,
64 #ifndef ARCH_HAS_SYSCALL_MATCH_SYM_NAME
65 static inline bool arch_syscall_match_sym_name(
const char *sym,
const char *
name)
73 return !
strcmp(sym + 3, name + 3);
78 find_syscall_meta(
unsigned long syscall)
85 start = __start_syscalls_metadata;
86 stop = __stop_syscalls_metadata;
89 if (arch_syscall_match_sym_name(str,
"sys_ni_syscall"))
92 for ( ; start <
stop; start++) {
93 if ((*start)->name && arch_syscall_match_sym_name(str, (*start)->name))
101 if (!syscalls_metadata || nr >=
NR_syscalls || nr < 0)
104 return syscalls_metadata[
nr];
117 trace = (
typeof(trace))ent;
119 entry = syscall_nr_to_meta(syscall);
133 for (i = 0; i < entry->
nb_args; i++) {
143 i == entry->
nb_args - 1 ?
"" :
", ");
171 trace = (
typeof(trace))ent;
173 entry = syscall_nr_to_meta(syscall);
195 #define SYSCALL_FIELD(type, name) \
196 sizeof(type) != sizeof(trace.name) ? \
197 __bad_type_size() : \
198 #type, #name, offsetof(typeof(trace), name), \
199 sizeof(trace.name), is_signed_type(type)
208 #define LEN_OR_ZERO (len ? len - pos : 0)
211 for (i = 0; i < entry->
nb_args; i++) {
213 entry->
args[i],
sizeof(
unsigned long),
214 i == entry->
nb_args - 1 ?
"" :
", ");
218 for (i = 0; i < entry->
nb_args; i++) {
220 ", ((unsigned long)(REC->%s))", entry->
args[i]);
241 len = __set_enter_print_fmt(entry,
NULL, 0);
248 __set_enter_print_fmt(entry, print_fmt, len + 1);
274 for (i = 0; i < meta->
nb_args; i++) {
276 meta->
args[i], offset,
277 sizeof(
unsigned long), 0,
279 offset +=
sizeof(
unsigned long);
312 if (!
test_bit(syscall_nr, enabled_enter_syscalls))
315 sys_data = syscall_nr_to_meta(syscall_nr);
319 size =
sizeof(*entry) +
sizeof(
unsigned long) * sys_data->
nb_args;
327 entry->
nr = syscall_nr;
346 if (!
test_bit(syscall_nr, enabled_exit_syscalls))
349 sys_data = syscall_nr_to_meta(syscall_nr);
354 sys_data->
exit_event->event.type,
sizeof(*entry), 0, 0);
359 entry->
nr = syscall_nr;
376 if (!sys_refcount_enter)
379 set_bit(num, enabled_enter_syscalls);
380 sys_refcount_enter++;
394 sys_refcount_enter--;
396 if (!sys_refcount_enter)
410 if (!sys_refcount_exit)
413 set_bit(num, enabled_exit_syscalls);
430 if (!sys_refcount_exit)
442 pr_debug(
"syscall %s metadata not mapped, disabling ftrace event\n",
447 if (set_syscall_print_fmt(call) < 0)
453 free_syscall_print_fmt(call);
471 syscalls_metadata = kcalloc(
NR_syscalls,
sizeof(*syscalls_metadata),
473 if (!syscalls_metadata) {
480 meta = find_syscall_meta(addr);
485 syscalls_metadata[
i] =
meta;
492 #ifdef CONFIG_PERF_EVENTS
496 static int sys_perf_refcount_enter;
497 static int sys_perf_refcount_exit;
499 static void perf_syscall_enter(
void *ignore,
struct pt_regs *
regs,
long id)
511 if (!
test_bit(syscall_nr, enabled_perf_enter_syscalls))
514 sys_data = syscall_nr_to_meta(syscall_nr);
519 size =
sizeof(
unsigned long) * sys_data->
nb_args +
sizeof(*rec);
524 "perf buffer not large enough"))
532 rec->
nr = syscall_nr;
534 (
unsigned long *)&rec->
args);
537 perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head,
NULL);
548 if (!sys_perf_refcount_enter)
549 ret = register_trace_sys_enter(perf_syscall_enter,
NULL);
551 pr_info(
"event trace: Could not activate"
552 "syscall entry trace point");
554 set_bit(num, enabled_perf_enter_syscalls);
555 sys_perf_refcount_enter++;
568 sys_perf_refcount_enter--;
569 clear_bit(num, enabled_perf_enter_syscalls);
570 if (!sys_perf_refcount_enter)
571 unregister_trace_sys_enter(perf_syscall_enter,
NULL);
575 static void perf_syscall_exit(
void *ignore,
struct pt_regs *regs,
long ret)
587 if (!
test_bit(syscall_nr, enabled_perf_exit_syscalls))
590 sys_data = syscall_nr_to_meta(syscall_nr);
595 size =
ALIGN(
sizeof(*rec) +
sizeof(
u32),
sizeof(
u64));
603 "exit event has grown above perf buffer size"))
607 sys_data->
exit_event->event.type, regs, &rctx);
611 rec->
nr = syscall_nr;
615 perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head,
NULL);
626 if (!sys_perf_refcount_exit)
627 ret = register_trace_sys_exit(perf_syscall_exit,
NULL);
629 pr_info(
"event trace: Could not activate"
630 "syscall exit trace point");
632 set_bit(num, enabled_perf_exit_syscalls);
633 sys_perf_refcount_exit++;
646 sys_perf_refcount_exit--;
647 clear_bit(num, enabled_perf_exit_syscalls);
648 if (!sys_perf_refcount_exit)
649 unregister_trace_sys_exit(perf_syscall_exit,
NULL);
665 #ifdef CONFIG_PERF_EVENTS
666 case TRACE_REG_PERF_REGISTER:
667 return perf_sysenter_enable(event);
668 case TRACE_REG_PERF_UNREGISTER:
669 perf_sysenter_disable(event);
671 case TRACE_REG_PERF_OPEN:
672 case TRACE_REG_PERF_CLOSE:
673 case TRACE_REG_PERF_ADD:
674 case TRACE_REG_PERF_DEL:
691 #ifdef CONFIG_PERF_EVENTS
692 case TRACE_REG_PERF_REGISTER:
693 return perf_sysexit_enable(event);
694 case TRACE_REG_PERF_UNREGISTER:
695 perf_sysexit_disable(event);
697 case TRACE_REG_PERF_OPEN:
698 case TRACE_REG_PERF_CLOSE:
699 case TRACE_REG_PERF_ADD:
700 case TRACE_REG_PERF_DEL: