diff options
Diffstat (limited to 'tapset/s390')
-rw-r--r-- | tapset/s390/nd_syscalls.stp | 187 | ||||
-rw-r--r-- | tapset/s390/registers.stp | 221 | ||||
-rw-r--r-- | tapset/s390/syscalls.stp | 169 |
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); + } +%} + +%) |