|
@@ -1,5 +1,6 @@
|
|
|
#include <trace/syscall.h>
|
|
|
#include <trace/events/syscalls.h>
|
|
|
+#include <linux/syscalls.h>
|
|
|
#include <linux/slab.h>
|
|
|
#include <linux/kernel.h>
|
|
|
#include <linux/module.h> /* for MODULE_NAME_LEN via KSYM_SYMBOL_LEN */
|
|
@@ -47,6 +48,38 @@ static inline bool arch_syscall_match_sym_name(const char *sym, const char *name
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+#ifdef ARCH_TRACE_IGNORE_COMPAT_SYSCALLS
|
|
|
+/*
|
|
|
+ * Some architectures that allow for 32bit applications
|
|
|
+ * to run on a 64bit kernel, do not map the syscalls for
|
|
|
+ * the 32bit tasks the same as they do for 64bit tasks.
|
|
|
+ *
|
|
|
+ * *cough*x86*cough*
|
|
|
+ *
|
|
|
+ * In such a case, instead of reporting the wrong syscalls,
|
|
|
+ * simply ignore them.
|
|
|
+ *
|
|
|
+ * For an arch to ignore the compat syscalls it needs to
|
|
|
+ * define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS as well as
|
|
|
+ * define the function arch_trace_is_compat_syscall() to let
|
|
|
+ * the tracing system know that it should ignore it.
|
|
|
+ */
|
|
|
+static int
|
|
|
+trace_get_syscall_nr(struct task_struct *task, struct pt_regs *regs)
|
|
|
+{
|
|
|
+ if (unlikely(arch_trace_is_compat_syscall(regs)))
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ return syscall_get_nr(task, regs);
|
|
|
+}
|
|
|
+#else
|
|
|
+static inline int
|
|
|
+trace_get_syscall_nr(struct task_struct *task, struct pt_regs *regs)
|
|
|
+{
|
|
|
+ return syscall_get_nr(task, regs);
|
|
|
+}
|
|
|
+#endif /* ARCH_TRACE_IGNORE_COMPAT_SYSCALLS */
|
|
|
+
|
|
|
static __init struct syscall_metadata *
|
|
|
find_syscall_meta(unsigned long syscall)
|
|
|
{
|
|
@@ -276,10 +309,10 @@ static void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id)
|
|
|
struct syscall_metadata *sys_data;
|
|
|
struct ring_buffer_event *event;
|
|
|
struct ring_buffer *buffer;
|
|
|
- int size;
|
|
|
int syscall_nr;
|
|
|
+ int size;
|
|
|
|
|
|
- syscall_nr = syscall_get_nr(current, regs);
|
|
|
+ syscall_nr = trace_get_syscall_nr(current, regs);
|
|
|
if (syscall_nr < 0)
|
|
|
return;
|
|
|
if (!test_bit(syscall_nr, enabled_enter_syscalls))
|
|
@@ -313,7 +346,7 @@ static void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
|
|
|
struct ring_buffer *buffer;
|
|
|
int syscall_nr;
|
|
|
|
|
|
- syscall_nr = syscall_get_nr(current, regs);
|
|
|
+ syscall_nr = trace_get_syscall_nr(current, regs);
|
|
|
if (syscall_nr < 0)
|
|
|
return;
|
|
|
if (!test_bit(syscall_nr, enabled_exit_syscalls))
|
|
@@ -502,7 +535,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id)
|
|
|
int rctx;
|
|
|
int size;
|
|
|
|
|
|
- syscall_nr = syscall_get_nr(current, regs);
|
|
|
+ syscall_nr = trace_get_syscall_nr(current, regs);
|
|
|
if (syscall_nr < 0)
|
|
|
return;
|
|
|
if (!test_bit(syscall_nr, enabled_perf_enter_syscalls))
|
|
@@ -578,7 +611,7 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
|
|
|
int rctx;
|
|
|
int size;
|
|
|
|
|
|
- syscall_nr = syscall_get_nr(current, regs);
|
|
|
+ syscall_nr = trace_get_syscall_nr(current, regs);
|
|
|
if (syscall_nr < 0)
|
|
|
return;
|
|
|
if (!test_bit(syscall_nr, enabled_perf_exit_syscalls))
|