관리-도구
편집 파일: syscalls.stpm
// syscalls tapset macros // Copyright (C) 2013-2018 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. @define __syscall_nr_gate(syscall_nr) %( # Here we don't care if we're in a compat task or not, we just # want to make sure we've got the correct syscall number. # # If _stp_syscall_nr() fails, that means we aren't in user # context. So, skip this call. try { if (_stp_syscall_nr() != @syscall_nr) next } catch { next } %) @define __syscall_gate(syscall_nr) %( # On some platforms (like s390x and ppc64), the 32-bit # syscalls use the same syscall number as the 64-bit # syscall. So, we have to check to see if this is a # 32-on-64-bit user task. @__syscall_gate_compat_simple # If _stp_syscall_nr() fails, that means we aren't in user # context. So, skip this call. try { if (_stp_syscall_nr() != @syscall_nr) next } catch { next } %) @define __syscall_gate2(syscall_nr1, syscall_nr2) %( # On some platforms (like s390x and ppc64), the 32-bit # syscalls use the same syscall number as the 64-bit # syscall. So, we have to check to see if this is a # 32-on-64-bit user task. @__syscall_gate_compat_simple try { __nr = _stp_syscall_nr() } catch { next } if ((__nr != @syscall_nr1) && (__nr != @syscall_nr2)) next %) @define __syscall_compat_gate(syscall_nr, compat_syscall_nr) %( %( CONFIG_COMPAT == "y" %? try { __nr = _stp_syscall_nr() } catch { next } if (@__compat_task) { if (__nr != @compat_syscall_nr) next } else if (__nr != @syscall_nr) next %: try { if (_stp_syscall_nr() != @syscall_nr) next } catch { next } %) %) @define __compat_syscall_gate(compat_syscall_nr) %( @__syscall_gate_noncompat_simple %( CONFIG_COMPAT == "y" %? try { __nr = _stp_syscall_nr() } catch { next } if (@__compat_task) { if (__nr != @compat_syscall_nr) next } %) %) @define __compat_syscall_gate_negative(compat_syscall_nr) %( %( CONFIG_COMPAT == "y" %? try { __nr = _stp_syscall_nr() } catch { next } if (@__compat_task) { if (__nr == @compat_syscall_nr) next } %) %) @define __syscall_gate_compat_simple %( %( CONFIG_COMPAT == "y" %? if (@__compat_task) next %) %) @define __syscall_gate_noncompat_simple %( %( CONFIG_COMPAT == "y" %? if (! @__compat_task) next %: next %) %) @define __pointer(val) %( %( CONFIG_64BIT == "y" %? %( CONFIG_COMPAT == "y" %? # If this is a compat task, the high bits of a pointer may be # garbage. (@__compat_task ? (@val & 0xffffffff) : @val) %: @val %) %: (@val & 0xffffffff) %) %) @define _af_inet_info_u(my_addr_uaddr, addrlen) %( %( systemtap_v >= "2.5" %? uaddr_af = _struct_sockaddr_u_sa_family(@my_addr_uaddr, @addrlen) if (_struct_sockaddr_u_sa_family(@my_addr_uaddr, @addrlen) =~ "AF_INET.*") { uaddr_ip = _struct_sockaddr_u_ip_addr(@my_addr_uaddr, @addrlen) uaddr_ip_port = _struct_sockaddr_u_tcp_port(@my_addr_uaddr, @addrlen) if (_struct_sockaddr_u_sa_family(@my_addr_uaddr, @addrlen) == "AF_INET6") { uaddr_ipv6_flowinfo = _struct_sockaddr_u_ipv6_flowinfo(@my_addr_uaddr, @addrlen) uaddr_ipv6_scope_id = _struct_sockaddr_u_ipv6_scope_id(@my_addr_uaddr, @addrlen) } } %) %) # The following argstr processing is modeled on strace's handling of # futex. Because it is so complicated and is used in 4 places # (syscall.futex, syscall.compat_futex, nd_syscall.futex, and # nd_syscall.compat_futex), a macro is used to handle all the # details. @define __futex_argstr(uaddr, op, val, utime, uaddr2, val3) %( if (@op == @const("FUTEX_WAKE_BITSET")) { argstr = sprintf("%p, %s, %d, %#x", @uaddr, _futex_op_str(@op), @val, @val3) } else if (@op == @const("FUTEX_WAIT")) { argstr = sprintf("%p, %s, %d, %s", @uaddr, _futex_op_str(@op), @val, (@__compat_task ? _struct_compat_timespec_u(@utime, 1) : _struct_timespec_u(@utime, 1))) } else if (@op == @const("FUTEX_WAIT_BITSET")) { argstr = sprintf("%p, %s, %d, %s, %#x", @uaddr, _futex_op_str(@op), @val, (@__compat_task ? _struct_compat_timespec_u(@utime, 1) : _struct_timespec_u(@utime, 1)), @val3) } else if (@op == @const("FUTEX_REQUEUE")) { argstr = sprintf("%p, %s, %d, %d, %p", @uaddr, _futex_op_str(@op), @val, @utime, @uaddr2) } else if (@op == @const("FUTEX_CMP_REQUEUE") || @op == @const("FUTEX_CMP_REQUEUE_PI")) { argstr = sprintf("%p, %s, %d, %u, %p, %d", @uaddr, _futex_op_str(@op), @val, @utime, @uaddr2, @val3) } else if (@op == @const("FUTEX_WAKE_OP")) { argstr = sprintf("%p, %s, %d, %u, %p, %s", @uaddr, _futex_op_str(@op), @val, @utime, @uaddr2, _futex_wake_op_str(@val3)) } else if (@op == @const("FUTEX_WAIT_REQUEUE_PI")) { argstr = sprintf("%p, %s, %d, %s, %p", @uaddr, _futex_op_str(@op), @val, (@__compat_task ? _struct_compat_timespec_u(@utime, 1) : _struct_timespec_u(@utime, 1)), @uaddr2) } else { argstr = sprintf("%p, %s, %d", @uaddr, _futex_op_str(@op), @val) } %) %( systemtap_v <= "2.9" %? @define __int32_compat(arg) %( %( CONFIG_64BIT == "y" %? (@__compat_task ? __int32(@arg) : @arg) %: (__int32(@arg)) %) %) %) @define __keyctl_argstr(option, arg2, arg3, arg4, arg5) %( if ((@option == @const("KEYCTL_READ")) || (@option == @const("KEYCTL_DESCRIBE")) || (@option == @const("KEYCTL_GET_SECURITY"))) { argstr = sprintf("%s, %s, %p, %d", _stp_keyctl_cmd_str(@option), _stp_keyctl_keyring_shortcut_str(@arg2), @arg3, @__compat_long(@arg4)) } else if (@option == @const("KEYCTL_UPDATE")) { argstr = sprintf("%s, %d, %s, %d", _stp_keyctl_cmd_str(@option), @__compat_long(@arg2), user_string_quoted(@arg3), @__compat_long(@arg4)) } else if ((@option == @const("KEYCTL_REVOKE")) || (@option == @const("KEYCTL_CLEAR")) || (@option == @const("KEYCTL_INVALIDATE")) || (@option == @const("KEYCTL_ASSUME_AUTHORITY"))) { argstr = sprintf("%s, %d", _stp_keyctl_cmd_str(@option), @__compat_long(@arg2)) } else if ((@option == @const("KEYCTL_LINK")) || (@option == @const("KEYCTL_UNLINK"))) { argstr = sprintf("%s, %d, %d", _stp_keyctl_cmd_str(@option), @__compat_long(@arg2), @__compat_long(@arg3)) } else if (@option == @const("KEYCTL_SEARCH")) { argstr = sprintf("%s, %d, %s, %s, %d", _stp_keyctl_cmd_str(@option), @__compat_long(@arg2), user_string_quoted(@arg3), user_string_quoted(@arg4), @__compat_long(@arg5)) } else if (@option == @const("KEYCTL_CHOWN")) { argstr = sprintf("%s, %d, %d, %d", _stp_keyctl_cmd_str(@option), @__compat_long(@arg2), @__compat_long(@arg3), @__compat_long(@arg4)) } else if (@option == @const("KEYCTL_SETPERM")) { argstr = sprintf("%s, %d, %s", _stp_keyctl_cmd_str(@option), @__compat_long(@arg2), _stp_keyctl_perm_str(@arg3)) } else if ((@option == @const("KEYCTL_INSTANTIATE"))) { argstr = sprintf("%s, %d, %s, %d, %d", _stp_keyctl_cmd_str(@option), @__compat_long(@arg2), user_string_quoted(@arg3), @__compat_long(@arg4), @__compat_long(@arg5)) } else if ((@option == @const("KEYCTL_INSTANTIATE_IOV"))) { argstr = sprintf("%s, %d, %p, %d, %d", _stp_keyctl_cmd_str(@option), @__compat_long(@arg2), @arg3, @__compat_long(@arg4), @__compat_long(@arg5)) } else if (@option == @const("KEYCTL_NEGATE")) { argstr = sprintf("%s, %d, %u, %d", _stp_keyctl_cmd_str(@option), @__compat_long(@arg2), @arg3, @__compat_long(@arg4)) } else if (@option == @const("KEYCTL_REJECT")) { argstr = sprintf("%s, %d, %u, %u, %d", _stp_keyctl_cmd_str(@option), @__compat_long(@arg2), @arg3, @arg4, @__compat_long(@arg5)) } else if (@option == @const("KEYCTL_SET_TIMEOUT")) { argstr = sprintf("%s, %d, %u", _stp_keyctl_cmd_str(@option), @__compat_long(@arg2), @arg3) } else if (@option == @const("KEYCTL_GET_KEYRING_ID")) { argstr = sprintf("%s, %s, %d", _stp_keyctl_cmd_str(@option), _stp_keyctl_keyring_shortcut_str(@arg2), @__compat_long(@arg3)) } else if (@option == @const("KEYCTL_SET_REQKEY_KEYRING")) { argstr = sprintf("%s, %s", _stp_keyctl_cmd_str(@option), _stp_keyctl_default_keyrings_str(@arg2)) } else if (@option == @const("KEYCTL_JOIN_SESSION_KEYRING")) { argstr = sprintf("%s, %p", _stp_keyctl_cmd_str(@option), @arg2) } else if (@option == @const("KEYCTL_GET_PERSISTENT")) { argstr = sprintf("%s, %d, %d", _stp_keyctl_cmd_str(@option), @__compat_long(@arg2), @__compat_long(@arg3)) } else { argstr = sprintf("%d, %d, %d, %d, %d", @option, @__compat_long(@arg2), @__compat_long(@arg3), @__compat_long(@arg4), @__compat_long(@arg5)) } %) @define __quotactl_argstr(subcmd, arg1, arg2, arg3, arg4) %( if (@subcmd == @const("Q_QUOTAON")) { argstr = sprintf("%s, %s, %s, %s", _quotactl_cmd_str(@arg1), user_string_quoted(@arg2), _quotactl_quota_type_str(@arg3), user_string_quoted(@arg4)) } else if ((@subcmd == @const("Q_GETQUOTA")) || (@subcmd == @const("Q_SETQUOTA"))) { argstr = sprintf("%s, %s, %d, %s", _quotactl_cmd_str(@arg1), user_string_quoted(@arg2), @arg3, _struct_dqblk_u(@arg4)) } else if ((@subcmd == @const("Q_GETINFO")) || (@subcmd == @const("Q_SETINFO"))) { argstr = sprintf("%s, %s, %d, %s", _quotactl_cmd_str(@arg1), user_string_quoted(@arg2), @arg3, _struct_dqinfo_u(@arg4)) } else if (@subcmd == @const("Q_GETFMT")) { argstr = sprintf("%s, %s, %d, %x", _quotactl_cmd_str(@arg1), user_string_quoted(@arg2), @arg3, @arg4) } else if ((@subcmd == @const("Q_SYNC")) || (@subcmd == @const("Q_QUOTAOFF"))) { argstr = sprintf("%s, %s, %d, %p", _quotactl_cmd_str(@arg1), user_string_quoted(@arg2), @arg3, @arg4) } else { argstr = sprintf("%s, %p, %d, %p", _quotactl_cmd_str(@arg1), @arg2, @arg3, @arg4) } %) # @__compat_ulong() macro adds the ability to distinguish between compat and non-compat # task to the __ulong() function making it full-featured couterpart to ulong_arg(). @define __compat_ulong(arg) %( %( CONFIG_COMPAT == "y" %? (@__compat_task ? __uint32(@arg) : __ulong(@arg)) %: __ulong(@arg) %) %) # @__compat_long() macro adds the ability to distinguish between compat and non-compat # task to the __long() function making it full-featured couterpart to long_arg(). @define __compat_long(arg) %( %( CONFIG_COMPAT == "y" %? (@__compat_task ? __int32(@arg) : __long(@arg)) %: __long(@arg) %) %) @define __BIG_ENDIAN %( %{ /* pure */ #ifdef __BIG_ENDIAN 1 #else 0 #endif %} %) # @__pos_from_hilo() is lifted straight from fs/read_write.c and only # used by preadv*/pwritev*. @define __pos_from_hilo(high, low) %( (((__ulong(@high) << (@const("BITS_PER_LONG") / 2)) << (@const("BITS_PER_LONG") / 2)) | __ulong(@low)) %) # Here's an explanation of the @cast() 3rd argument here. In RHEL6-era # kernels (2.6.32), the "ulong" and "unsigned int" definitions can be # found in <linux/types.h>. However, in newer kernels those # definitions have been moved to <uapi/linux/types.h>. But, we can't # do "kernel<linux/types.h><uapi/linux/types.h>" because the # <uapi/linux/types.h> doesn't exist on RHEL6-era kernels. So, we list # each header file separately. @define ulong_cast(val) %( @cast(@val, "ulong", "kernel<linux/types.h>:kernel<uapi/linux/types.h>") %) @define uint_cast(val) %( @cast(@val, "unsigned int", "kernel<linux/types.h>:kernel<uapi/linux/types.h>") %) // As other architectures adopt the 4.17 syscall wrapper mechanism, // these macros will have to be conditionalized on %( arch %). @define arch_syscall_prefix %( "__{ia32,x64}_" %) @define arch_syscall0_prefix %( "__x64_" %) %( arch == "ia64" %? @define SYSC_CLONE_CLONE_FLAGS_ARGNO %( 1 %) @define SYSC_CLONE_STACK_START_ARGNO %( 2 %) @define SYSC_CLONE_PARENT_TID_UADDR_ARGNO %( 4 %) @define SYSC_CLONE_CHILD_TID_UADDR_ARGNO %( 5 %) %) %( arch == "s390" %? @define SYSC_CLONE_CLONE_FLAGS_ARGNO %( 2 %) @define SYSC_CLONE_STACK_START_ARGNO %( 1 %) @define SYSC_CLONE_PARENT_TID_UADDR_ARGNO %( 3 %) @define SYSC_CLONE_CHILD_TID_UADDR_ARGNO %( 4 %) %) %( arch == "x86_64" %? @define SYSC_CLONE_CLONE_FLAGS_ARGNO %( 1 %) @define SYSC_CLONE_STACK_START_ARGNO %( 2 %) @define SYSC_CLONE_PARENT_TID_UADDR_ARGNO %( 3 %) @define SYSC_CLONE_CHILD_TID_UADDR_ARGNO %( @__compat_task ? 5 : 4 %) %) %( arch == "i386" || arch == "arm" || arch == "arm64" || arch == "powerpc" || arch == "mips" %? @define SYSC_CLONE_CLONE_FLAGS_ARGNO %( 1 %) @define SYSC_CLONE_STACK_START_ARGNO %( 2 %) @define SYSC_CLONE_PARENT_TID_UADDR_ARGNO %( 3 %) @define SYSC_CLONE_CHILD_TID_UADDR_ARGNO %( 5 %) %) @define SYSC_RETVALSTR(val) %( %( systemtap_v >= "4.0" %? retval = @val; %) %( systemtap_v <= "4.0" %? set_returnval(@val); %) retstr = return_str(1,@val); %) @define SYSC_RETVALSTR2(val) %( %( systemtap_v >= "4.0" %? retval = @val; %) %( systemtap_v <= "4.0" %? set_returnval(@val); %) retstr = return_str(2,@val); %) @define SYSC_RETVALSTR3(val) %( %( systemtap_v >= "4.0" %? retval = @val; %) %( systemtap_v <= "4.0" %? set_returnval(@val); %) retstr = return_str(3,@val); %)