summaryrefslogtreecommitdiffstats
path: root/tapset/s390
diff options
context:
space:
mode:
Diffstat (limited to 'tapset/s390')
-rw-r--r--tapset/s390/nd_syscalls.stp187
-rw-r--r--tapset/s390/registers.stp221
-rw-r--r--tapset/s390/syscalls.stp169
3 files changed, 577 insertions, 0 deletions
diff --git a/tapset/s390/nd_syscalls.stp b/tapset/s390/nd_syscalls.stp
new file mode 100644
index 00000000..bd5f5c32
--- /dev/null
+++ b/tapset/s390/nd_syscalls.stp
@@ -0,0 +1,187 @@
+# S390-specific system calls
+
+%(arch == "s390" %?
+
+# getresgid __________________________________________________
+# long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid)
+#
+probe nd_syscall.getresgid16 = kprobe.function("sys32_getresgid16") ?
+{
+ name = "getresgid"
+ // argstr = sprintf("%p, %p, %p", $rgid, $egid, $sgid)
+ asmlinkage()
+ argstr = sprintf("%p, %p, %p", pointer_arg(1), pointer_arg(2), pointer_arg(3))
+}
+probe nd_syscall.getresgid16.return = kprobe.function("sys32_getresgid16").return ?
+{
+ name = "getresgid"
+ retstr = returnstr(1)
+}
+
+# getresuid __________________________________________________
+# long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid)
+#
+probe nd_syscall.getresuid16 = kprobe.function("sys32_getresuid16") ?
+{
+ name = "getresuid"
+ // argstr = sprintf("%p, %p, %p", $ruid, $euid, $suid)
+ asmlinkage()
+ argstr = sprintf("%p, %p, %p", pointer_arg(1), pointer_arg(2), pointer_arg(3))
+}
+probe nd_syscall.getresuid16.return = kprobe.function("sys32_getresuid16").return ?
+{
+ name = "getresuid"
+ retstr = returnstr(1)
+}
+
+# ipc _________________________________________________
+# long sys32_ipc(u32 call, int first, int second, int third, u32 ptr)
+#
+probe nd_syscall.ipc = kprobe.function("sys32_ipc") ?
+{
+ name = "ipc"
+ // argstr = sprintf("%d, %d, %d, %d, %p", $call, $first, $second, $third, $ptr)
+ asmlinkage()
+ argstr = sprintf("%d, %d, %d, %d, %p", uint_arg(1), int_arg(2), int_arg(3), int_arg(4), uint_arg(5))
+}
+probe nd_syscall.ipc.return = kprobe.function("sys_ipc").return ?
+{
+ name = "ipc"
+ retstr = returnstr(1)
+}
+
+# mmap _________________________________________________
+# long old_mmap(struct mmap_arg_struct __user *arg)
+# long old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
+#
+probe nd_syscall.mmap = kprobe.function("old_mmap") ?,
+ kprobe.function("old32_mmap") ?,
+ kprobe.function("SyS_s390_old_mmap") ?
+{
+ name = "mmap"
+
+ // if ((probefunc() == "old_mmap") || (probefunc() == "SyS_s390_old_mmap"))
+ // argstr = get_mmap_args($arg)
+ // else
+ // argstr = get_32mmap_args($arg)
+
+ asmlinkage()
+ if ((probefunc() == "old_mmap") || (probefunc() == "SyS_s390_old_mmap"))
+ argstr = get_mmap_args(pointer_arg(1))
+ else
+ argstr = get_32mmap_args(pointer_arg(1))
+}
+probe nd_syscall.mmap.return = kprobe.function("old_mmap").return ?,
+ kprobe.function("old32_mmap").return ?,
+ kprobe.function("SyS_s390_old_mmap").return ?
+{
+ name = "mmap"
+ retstr = returnstr(2)
+}
+
+# mmap2 _________________________________________________
+#
+# long sys_mmap2(struct mmap_arg_struct __user *arg)
+# long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg)
+#
+probe nd_syscall.mmap2 = kprobe.function("sys_mmap2") ?,
+ kprobe.function("sys32_mmap2") ?,
+ kprobe.function("SyS_mmap2") ?
+{
+ name = "mmap2"
+
+ // if ((probefunc() == "sys_mmap2") || (probefunc() == "SyS_mmap2"))
+ // argstr = get_mmap_args($arg)
+ // else
+ // argstr = get_32mmap_args($arg)
+
+ asmlinkage()
+ if ((probefunc() == "sys_mmap2") || (probefunc() == "SyS_mmap2"))
+ argstr = get_mmap_args(pointer_arg(1))
+ else
+ argstr = get_32mmap_args(pointer_arg(1))
+}
+
+probe nd_syscall.mmap2.return = kprobe.function("sys_mmap2").return ?,
+ kprobe.function("sys32_mmap2").return ?,
+ kprobe.function("SyS_mmap2").return ?
+{
+ name = "mmap2"
+ retstr = returnstr(2)
+}
+
+# sysctl _____________________________________________________
+#
+# long sys32_sysctl(struct __sysctl_args32 __user *args)
+#
+probe nd_syscall.sysctl32 = kprobe.function("sys32_sysctl") ?
+{
+ name = "sysctl"
+ // argstr = sprintf("%p", $args)
+ asmlinkage()
+ argstr = sprintf("%p", pointer_arg(1))
+}
+probe nd_syscall.sysctl32.return = kprobe.function("sys32_sysctl").return ?
+{
+ name = "sysctl"
+ retstr = returnstr(1)
+}
+
+/* compat */
+function get_32mmap_args:string (args:long)
+%{ /* pure */
+ struct mmap_arg_struct_emu31 {
+ u32 addr;
+ u32 len;
+ u32 prot;
+ u32 flags;
+ u32 fd;
+ u32 offset;
+ }a;
+
+
+ char proto[60];
+ char flags[256];
+
+ if(_stp_copy_from_user((char *)&a,
+ (char *)THIS->args, sizeof(a))== 0){
+
+ /* _mprotect_prot_str */
+ proto[0] = '\0';
+ if(a.prot){
+ if(a.prot & 1) strcat (proto, "PROT_READ|");
+ if(a.prot & 2) strcat (proto, "PROT_WRITE|");
+ if(a.prot & 4) strcat (proto, "PROT_EXEC|");
+ } else {
+ strcat (proto, "PROT_NONE");
+ }
+ if (proto[0] != '\0') proto[strlen(proto)-1] = '\0';
+
+ /* _mmap_flags */
+ flags[0]='\0';
+ if (a.flags & 1) strcat (flags, "MAP_SHARED|");
+ if (a.flags & 2) strcat (flags, "MAP_PRIVATE|");
+ if (a.flags & 0x10) strcat (flags, "MAP_FIXED|");
+ if (a.flags & 0x20) strcat (flags, "MAP_ANONYMOUS|");
+ if (a.flags & 0x100) strcat (flags, "MAP_GROWSDOWN|");
+ if (a.flags & 0x800) strcat (flags, "MAP_DENYWRITE|");
+ if (a.flags & 0x1000) strcat (flags, "MAP_EXECUTABLE|");
+ if (a.flags & 0x2000) strcat (flags, "MAP_LOCKED|");
+ if (a.flags & 0x4000) strcat (flags, "MAP_NORESERVE|");
+ if (a.flags & 0x8000) strcat (flags, "MAP_POPULATE|");
+ if (a.flags & 0x10000) strcat (flags, "MAP_NONBLOCK|");
+ if (flags[0] != '\0') flags[strlen(flags)-1] = '\0';
+
+ sprintf(THIS->__retvalue,"0x%x, %d, %s, %s, %d, %d",
+ a.addr,
+ a.len,
+ proto,
+ flags,
+ a.fd,
+ a.offset);
+ }else{
+ strlcpy (THIS->__retvalue, "UNKNOWN", MAXSTRINGLEN);
+ }
+%}
+
+%)
diff --git a/tapset/s390/registers.stp b/tapset/s390/registers.stp
new file mode 100644
index 00000000..79482b73
--- /dev/null
+++ b/tapset/s390/registers.stp
@@ -0,0 +1,221 @@
+/* Dwarfless register access for s390x */
+
+global _reg_offsets, _stp_regs_registered
+
+function _stp_register_regs() {
+ /* Same order as pt_regs */
+ _reg_offsets["args"] = 0
+ _reg_offsets["psw.mask"] = 8
+ _reg_offsets["psw.addr"] = 16
+ _reg_offsets["r0"] = 24
+ _reg_offsets["r1"] = 32
+ _reg_offsets["r2"] = 40
+ _reg_offsets["r3"] = 48
+ _reg_offsets["r4"] = 56
+ _reg_offsets["r5"] = 64
+ _reg_offsets["r6"] = 72
+ _reg_offsets["r7"] = 80
+ _reg_offsets["r8"] = 88
+ _reg_offsets["r9"] = 96
+ _reg_offsets["r10"] = 104
+ _reg_offsets["r11"] = 112
+ _reg_offsets["r12"] = 120
+ _reg_offsets["r13"] = 128
+ _reg_offsets["r14"] = 136
+ _reg_offsets["r15"] = 144
+
+ _reg_offsets["orig_gpr2"] = 152
+ _reg_offsets["ilc"] = 160
+ _reg_offsets["trap"] = 162
+
+ /*
+ * If we ever need to support s390 (31-bit arch), we can
+ * get to the register offsets by using just a
+ * reg32_offset = _reg_offsets["reg"]/2
+ * or somesuch
+ */
+ _stp_regs_registered = 1
+}
+
+
+/*
+ * Though the flag says 31bit, asm-s390/thread_info.h comment
+ * says "32bit process"
+ */
+function probing_32bit_app() %{ /* pure */
+ if (CONTEXT->regs)
+ THIS->__retvalue = (user_mode(CONTEXT->regs) &&
+ test_tsk_thread_flag(current, TIF_31BIT));
+ else
+ THIS->__retvalue = 0;
+%}
+
+function _stp_probing_kernel: long () %{ /* pure */
+ THIS->__retvalue = !user_mode(CONTEXT->regs);
+%}
+
+function _stp_get_register_by_offset:long (offset:long) %{ /* pure */
+ long value;
+ if (!CONTEXT->regs) {
+ CONTEXT->last_error = "No registers available in this context";
+ return;
+ }
+ if (THIS->offset < 0 || THIS->offset > sizeof(struct pt_regs) - sizeof(unsigned short)) {
+ snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
+ "Bad register offset: %lld", THIS->offset);
+ CONTEXT->last_error = CONTEXT->error_buffer;
+ return;
+ }
+
+ if (THIS->offset < sizeof(struct pt_regs) - 2 * sizeof(unsigned short))
+ memcpy(&value, ((char *)CONTEXT->regs) + THIS->offset,
+ sizeof(value));
+ else {
+ /* ilc or trap */
+ unsigned short us_value;
+ memcpy(&us_value, ((char *)CONTEXT->regs) + THIS->offset,
+ sizeof(us_value));
+ value = us_value; // not sign-extended
+ }
+ THIS->__retvalue = value;
+%}
+
+function _stp_sign_extend32:long (value:long) {
+ if (value & 0x80000000)
+ value |= (0xffffffff << 32)
+ return value
+}
+
+function _stp_register:long (name:string, sign_extend:long) {
+ if (!registers_valid()) {
+ error("cannot access CPU registers in this context")
+ return 0
+ }
+ if (!_stp_regs_registered)
+ _stp_register_regs()
+ offset = _reg_offsets[name]
+ if (offset == 0 && !(name in _reg_offsets)) {
+ error("Unknown register: " . name)
+ return 0
+ }
+ value = _stp_get_register_by_offset(offset)
+ if (probing_32bit_app()) {
+ if (sign_extend)
+ value = _stp_sign_extend32(value)
+ else
+ value &= 0xffffffff
+ }
+ return value
+}
+
+/* Return the named register value as a signed value. */
+function register:long (name:string) {
+ return _stp_register(name, 1)
+}
+
+/*
+ * Return the named register value as an unsigned value. Specifically,
+ * don't sign-extend the register value when promoting it to 64 bits.
+ */
+function u_register:long (name:string) {
+ return _stp_register(name, 0)
+}
+
+/*
+ * Return the value of function arg #argnum (1=first arg).
+ * If truncate=1, mask off the top 32 bits.
+ * If sign_extend=1 and (truncate=1 or the probepoint we've hit is in a
+ * 32-bit app), sign-extend the 32-bit value.
+ *
+ * We don't yet support extracting arg #6 and beyond, which are passed
+ * on stack
+ */
+function _stp_arg:long (argnum:long, sign_extend:long, truncate:long) {
+ val = 0
+ if (argnum < 1 || argnum > 5) {
+ error(sprintf("Cannot access arg(%d)", argnum))
+ return 0
+ }
+
+ if (argnum == 1)
+ val = u_register("r2")
+ else if (argnum == 2)
+ val = u_register("r3")
+ else if (argnum == 3)
+ val = u_register("r4")
+ else if (argnum == 4)
+ val = u_register("r5")
+ else (argnum == 5)
+ val = u_register("r6")
+
+ if (truncate) {
+ if (sign_extend)
+ val = _stp_sign_extend32(val)
+ else
+ /* High bits may be garbage. */
+ val = (val & 0xffffffff);
+ }
+ return val;
+}
+
+/* Return the value of function arg #argnum (1=first arg) as a signed int. */
+function int_arg:long (argnum:long) {
+ return _stp_arg(argnum, 1, 1)
+}
+
+/* Return the value of function arg #argnum (1=first arg) as an unsigned int. */
+function uint_arg:long (argnum:long) {
+ return _stp_arg(argnum, 0, 1)
+}
+
+function long_arg:long (argnum:long) {
+ return _stp_arg(argnum, 1, 0)
+}
+
+function ulong_arg:long (argnum:long) {
+ return _stp_arg(argnum, 0, 0)
+}
+
+function longlong_arg:long (argnum:long) {
+ if (probing_32bit_app()) {
+ /* TODO verify if this is correct for 31bit apps */
+ highbits = _stp_arg(argnum, 0, 1)
+ lowbits = _stp_arg(argnum+1, 0, 1)
+ return ((highbits << 32) | lowbits)
+ } else
+ return _stp_arg(argnum, 0, 0)
+}
+
+function ulonglong_arg:long (argnum:long) {
+ return longlong_arg(argnum)
+}
+
+function pointer_arg:long (argnum:long) {
+ return _stp_arg(argnum, 0, 0)
+}
+
+function s32_arg:long (argnum:long) {
+ return int_arg(argnum)
+}
+
+function u32_arg:long (argnum:long) {
+ return uint_arg(argnum)
+}
+
+function s64_arg:long (argnum:long) {
+ return longlong_arg(argnum)
+}
+
+function u64_arg:long (argnum:long) {
+ return ulonglong_arg(argnum)
+}
+
+function asmlinkage() %{ /* pure */ %}
+
+function fastcall() %{ /* pure */ %}
+
+function regparm() %{
+ snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
+ "regparm is invalid on s390.");
+ CONTEXT->last_error = CONTEXT->error_buffer;
+%}
diff --git a/tapset/s390/syscalls.stp b/tapset/s390/syscalls.stp
new file mode 100644
index 00000000..aba7d6bf
--- /dev/null
+++ b/tapset/s390/syscalls.stp
@@ -0,0 +1,169 @@
+# S390-specific system calls
+
+%(arch == "s390" %?
+
+# getresgid __________________________________________________
+# long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid)
+#
+probe syscall.getresgid16 = kernel.function("sys32_getresgid16") ?
+{
+ name = "getresgid"
+ argstr = sprintf("%p, %p, %p", $rgid, $egid, $sgid)
+}
+probe syscall.getresgid16.return = kernel.function("sys32_getresgid16").return ?
+{
+ name = "getresgid"
+ retstr = returnstr(1)
+}
+# getresuid __________________________________________________
+# long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid)
+#
+probe syscall.getresuid16 = kernel.function("sys32_getresuid16") ?
+{
+ name = "getresuid"
+ argstr = sprintf("%p, %p, %p", $ruid, $euid, $suid)
+}
+probe syscall.getresuid16.return = kernel.function("sys32_getresuid16").return ?
+{
+ name = "getresuid"
+ retstr = returnstr(1)
+}
+
+# ipc _________________________________________________
+# long sys32_ipc(u32 call, int first, int second, int third, u32 ptr)
+#
+probe syscall.ipc = kernel.function("sys32_ipc") ?
+{
+ name = "ipc"
+ argstr = sprintf("%d, %d, %d, %d, %p", $call, $first, $second, $third, $ptr)
+}
+probe syscall.ipc.return = kernel.function("sys_ipc").return ?
+{
+ name = "ipc"
+ retstr = returnstr(1)
+}
+
+# mmap _________________________________________________
+# long old_mmap(struct mmap_arg_struct __user *arg)
+# long old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
+#
+probe syscall.mmap = kernel.function("old_mmap") ?,
+ kernel.function("old32_mmap") ?,
+ kernel.function("SyS_s390_old_mmap") ?
+{
+ name = "mmap"
+
+ if ((probefunc() == "old_mmap") || (probefunc() == "SyS_s390_old_mmap"))
+ argstr = get_mmap_args($arg)
+ else
+ argstr = get_32mmap_args($arg)
+}
+
+probe syscall.mmap.return = kernel.function("old_mmap").return ?,
+ kernel.function("old32_mmap").return ?,
+ kernel.function("SyS_s390_old_mmap").return ?
+{
+ name = "mmap"
+ retstr = returnstr(2)
+}
+
+
+# mmap2 _________________________________________________
+#
+# long sys_mmap2(struct mmap_arg_struct __user *arg)
+# long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg)
+#
+probe syscall.mmap2 = kernel.function("sys_mmap2") ?,
+ kernel.function("sys32_mmap2") ?,
+ kernel.function("SyS_mmap2") ?
+{
+ name = "mmap2"
+
+ if ((probefunc() == "sys_mmap2") || (probefunc() == "SyS_mmap2"))
+ argstr = get_mmap_args($arg)
+ else
+ argstr = get_32mmap_args($arg)
+}
+
+probe syscall.mmap2.return = kernel.function("sys_mmap2").return ?,
+ kernel.function("sys32_mmap2").return ?,
+ kernel.function("SyS_mmap2").return ?
+{
+ name = "mmap2"
+ retstr = returnstr(2)
+}
+
+# sysctl _____________________________________________________
+#
+# long sys32_sysctl(struct __sysctl_args32 __user *args)
+#
+probe syscall.sysctl32 = kernel.function("sys32_sysctl") ?
+{
+ name = "sysctl"
+ argstr = sprintf("%p", $args)
+}
+probe syscall.sysctl32.return = kernel.function("sys32_sysctl").return ?
+{
+ name = "sysctl"
+ retstr = returnstr(1)
+}
+
+
+/* compat */
+function get_32mmap_args:string (args:long)
+%{ /* pure */
+ struct mmap_arg_struct_emu31 {
+ u32 addr;
+ u32 len;
+ u32 prot;
+ u32 flags;
+ u32 fd;
+ u32 offset;
+ }a;
+
+
+ char proto[60];
+ char flags[256];
+
+ if(_stp_copy_from_user((char *)&a,
+ (char *)THIS->args, sizeof(a))== 0){
+
+ /* _mprotect_prot_str */
+ proto[0] = '\0';
+ if(a.prot){
+ if(a.prot & 1) strcat (proto, "PROT_READ|");
+ if(a.prot & 2) strcat (proto, "PROT_WRITE|");
+ if(a.prot & 4) strcat (proto, "PROT_EXEC|");
+ } else {
+ strcat (proto, "PROT_NONE");
+ }
+ if (proto[0] != '\0') proto[strlen(proto)-1] = '\0';
+
+ /* _mmap_flags */
+ flags[0]='\0';
+ if (a.flags & 1) strcat (flags, "MAP_SHARED|");
+ if (a.flags & 2) strcat (flags, "MAP_PRIVATE|");
+ if (a.flags & 0x10) strcat (flags, "MAP_FIXED|");
+ if (a.flags & 0x20) strcat (flags, "MAP_ANONYMOUS|");
+ if (a.flags & 0x100) strcat (flags, "MAP_GROWSDOWN|");
+ if (a.flags & 0x800) strcat (flags, "MAP_DENYWRITE|");
+ if (a.flags & 0x1000) strcat (flags, "MAP_EXECUTABLE|");
+ if (a.flags & 0x2000) strcat (flags, "MAP_LOCKED|");
+ if (a.flags & 0x4000) strcat (flags, "MAP_NORESERVE|");
+ if (a.flags & 0x8000) strcat (flags, "MAP_POPULATE|");
+ if (a.flags & 0x10000) strcat (flags, "MAP_NONBLOCK|");
+ if (flags[0] != '\0') flags[strlen(flags)-1] = '\0';
+
+ sprintf(THIS->__retvalue,"0x%x, %d, %s, %s, %d, %d",
+ a.addr,
+ a.len,
+ proto,
+ flags,
+ a.fd,
+ a.offset);
+ }else{
+ strlcpy (THIS->__retvalue, "UNKNOWN", MAXSTRINGLEN);
+ }
+%}
+
+%)