summaryrefslogtreecommitdiffstats
path: root/runtime/syscall.h
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/syscall.h')
-rw-r--r--runtime/syscall.h132
1 files changed, 132 insertions, 0 deletions
diff --git a/runtime/syscall.h b/runtime/syscall.h
new file mode 100644
index 00000000..3e37b550
--- /dev/null
+++ b/runtime/syscall.h
@@ -0,0 +1,132 @@
+/* syscall defines and inlines
+ * Copyright (C) 2008 Red Hat Inc.
+ *
+ * This file is part of systemtap, and is free software. You can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License (GPL); either version 2, or (at your option) any
+ * later version.
+ */
+
+#ifndef _SYSCALL_H_ /* -*- linux-c -*- */
+#define _SYSCALL_H_
+
+#if defined(__i386__) || defined(CONFIG_IA32_EMULATION)
+#define __MMAP_SYSCALL_NO_IA32 192 /* mmap2 */
+#define __MPROTECT_SYSCALL_NO_IA32 125
+#define __MUNMAP_SYSCALL_NO_IA32 91
+#define __MREMAP_SYSCALL_NO_IA32 163
+# if !defined(CONFIG_IA32_EMULATION)
+#define MMAP_SYSCALL_NO(tsk) __MMAP_SYSCALL_NO_IA32
+#define MPROTECT_SYSCALL_NO(tsk) __MPROTECT_SYSCALL_NO_IA32
+#define MUNMAP_SYSCALL_NO(tsk) __MUNMAP_SYSCALL_NO_IA32
+#define MREMAP_SYSCALL_NO(tsk) __MREMAP_SYSCALL_NO_IA32
+# endif
+#endif
+
+#if defined(__x86_64__)
+#define __MMAP_SYSCALL_NO_X86_64 9
+#define __MPROTECT_SYSCALL_NO_X86_64 10
+#define __MUNMAP_SYSCALL_NO_X86_64 11
+#define __MREMAP_SYSCALL_NO_X86_64 25
+# if defined(CONFIG_IA32_EMULATION)
+#define MMAP_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_IA32)) \
+ ? __MMAP_SYSCALL_NO_IA32 \
+ : __MMAP_SYSCALL_NO_X86_64)
+#define MPROTECT_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_IA32)) \
+ ? __MPROTECT_SYSCALL_NO_IA32 \
+ : __MPROTECT_SYSCALL_NO_X86_64)
+#define MUNMAP_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_IA32)) \
+ ? __MUNMAP_SYSCALL_NO_IA32 \
+ : __MUNMAP_SYSCALL_NO_X86_64)
+#define MREMAP_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_IA32)) \
+ ? __MREMAP_SYSCALL_NO_IA32 \
+ : __MREMAP_SYSCALL_NO_X86_64)
+# else
+#define MMAP_SYSCALL_NO(tsk) __MMAP_SYSCALL_NO_X86_64
+#define MPROTECT_SYSCALL_NO(tsk) __MPROTECT_SYSCALL_NO_X86_64
+#define MUNMAP_SYSCALL_NO(tsk) __MUNMAP_SYSCALL_NO_X86_64
+#define MREMAP_SYSCALL_NO(tsk) __MREMAP_SYSCALL_NO_X86_64
+# endif
+#endif
+
+#if !defined(MMAP_SYSCALL_NO) || !defined(MPROTECT_SYSCALL_NO) \
+ || !defined(MUNMAP_SYSCALL_NO) || !defined(MREMAP_SYSCALL_NO)
+#error "Unimplemented architecture"
+#endif
+
+#if defined(__i386__) || defined(__x86_64__)
+static inline unsigned long
+__stp_user_syscall_nr(struct pt_regs *regs)
+{
+#if defined(STAPCONF_X86_UNIREGS)
+ return regs->orig_ax;
+#elif defined(__x86_64__)
+ return regs->orig_rax;
+#elif defined (__i386__)
+ return regs->orig_eax;
+#endif
+}
+#endif
+
+#if defined(__i386__) || defined(__x86_64__)
+static inline long *
+__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
+{
+#ifdef CONFIG_IA32_EMULATION
+// This code works, but isn't what we need. Since
+// __stp_user_syscall_arg() doesn't sign-extend, a value passed in as
+// an argument and then returned won't compare correctly anymore. So,
+// for now, disable this code.
+# if 0
+ if (test_tsk_thread_flag(task, TIF_IA32))
+ // Sign-extend the value so (int)-EFOO becomes (long)-EFOO
+ // and will match correctly in comparisons.
+ regs->ax = (long) (int) regs->ax;
+# endif
+#endif
+ return &regs->ax;
+}
+#endif
+
+#if defined(__i386__) || defined(__x86_64__)
+static inline long *
+__stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
+ unsigned int n)
+{
+#if defined(CONFIG_X86_32)
+ if (n > 5) {
+ _stp_error("syscall arg > 5");
+ return NULL;
+ }
+ return &regs->bx + n;
+#elif defined(CONFIG_X86_64)
+#ifdef CONFIG_IA32_EMULATION
+ if (test_tsk_thread_flag(task, TIF_IA32))
+ switch (n) {
+ case 0: return &regs->bx;
+ case 1: return &regs->cx;
+ case 2: return &regs->dx;
+ case 3: return &regs->si;
+ case 4: return &regs->di;
+ case 5: return &regs->bp;
+ default:
+ _stp_error("syscall arg > 5");
+ return NULL;
+ }
+#endif /* CONFIG_IA32_EMULATION */
+ switch (n) {
+ case 0: return &regs->di;
+ case 1: return &regs->si;
+ case 2: return &regs->dx;
+ case 3: return &regs->r10;
+ case 4: return &regs->r8;
+ case 5: return &regs->r9;
+ default:
+ _stp_error("syscall arg > 5");
+ return NULL;
+ }
+#endif /* CONFIG_X86_32 */
+}
+#endif
+
+#endif /* _SYSCALL_H_ */