관리-도구
편집 파일: aux_syscalls.stp
%{ // Be sure we have the __NR_* defines. #include <asm/unistd.h> #include "linux/compat_unistd.h" // Be sure we have the SYS_* defines. #include <linux/net.h> #include "linux/compat_net.h" #ifdef CONFIG_COMPAT // Be sure we have 'SHMCTL', etc. defined. #include <linux/ipc.h> #ifndef SEMOP #define SEMOP 1 #endif #ifndef SEMCTL #define SEMCTL 3 #endif #ifndef SEMTIMEDOP #define SEMTIMEDOP 4 #endif #ifndef MSGSND #define MSGSND 11 #endif #ifndef MSGRCV #define MSGRCV 12 #endif #ifndef MSGCTL #define MSGCTL 14 #endif #ifndef SHMCTL #define SHMCTL 24 #endif #endif /* * Simple lookup functions for mapping values to names * using embedded C. Use these functions to create safe, * consistent lookups. */ // Get _stp_val_array and _stp_lookup_* definitions. #include "linux/syscalls-common.h" // Get _stp_syscall_get_nr() definitions. #include "syscall.h" static void _stp_lookup_str2(const _stp_val_array * const array, long val, char *ptr, int len, int base) { int i = 0, slen; while (array[i].name) { if (array[i].val == val) { strlcat (ptr, array[i].name, len); return; } i++; } slen = strlen(ptr); if (base == 10) _stp_snprintf(ptr + slen, len - slen, "%ld", val); else if (base == 8) _stp_snprintf(ptr + slen, len - slen, "%#lo", val); else _stp_snprintf(ptr + slen, len - slen, "0x%lx", val); } static inline void _stp_lookup_str(const _stp_val_array * const array, long val, char *ptr, int len) { _stp_lookup_str2(array, val, ptr, len, 16); } static void _stp_lookup_or_str2(const _stp_val_array * const array, long val, char *ptr, int len, int base) { int i = 0, flag = 0, slen; if (val == 0) { _stp_lookup_str2(array, val, ptr, len, base); return; } while (array[i].name) { if (array[i].val & val) { if (flag) strlcat(ptr, "|", len); strlcat(ptr, array[i].name, len); val &= (~array[i].val); flag = 1; } i++; } if (val) { if (flag) strlcat(ptr, "|", len); slen = strlen(ptr); if (base == 10) _stp_snprintf(ptr + slen, len - slen, "%ld", val); else if (base == 8) _stp_snprintf(ptr + slen, len - slen, "%#lo", val); else _stp_snprintf(ptr + slen, len - slen, "0x%lx", val); } } static inline void _stp_lookup_or_str(const _stp_val_array * const array, long val, char *ptr, int len) { _stp_lookup_or_str2(array, val, ptr, len, 16); } %} %{ #ifdef CONFIG_COMPAT #include <linux/compat.h> #ifndef STAPCONF_SIGSET_FROM_COMPAT_EXPORTED void sigset_from_compat(sigset_t *set, compat_sigset_t *compat) { switch (_NSIG_WORDS) { case 4: set->sig[3] = compat->sig[6] | (((long)compat->sig[7]) << 32 ); case 3: set->sig[2] = compat->sig[4] | (((long)compat->sig[5]) << 32 ); case 2: set->sig[1] = compat->sig[2] | (((long)compat->sig[3]) << 32 ); case 1: set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32 ); } } #endif /* STAPCONF_SIGSET_FROM_COMPAT_EXPORTED */ #endif /* CONFIG_COMPAT */ %} # # Given a userspace pointer to a timeval, # copy and decode it and return a string. # function _struct_timeval_u:string(uaddr:long, n:long) %{ /* pure */ int n = (int)STAP_ARG_n; struct timeval tv[n]; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL || n < 1 || n > 2) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char*)&tv, ptr, n*sizeof(struct timeval)) == 0) { if (n == 2) snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%ld.%06ld][%ld.%.06ld]", tv[0].tv_sec, tv[0].tv_usec, tv[1].tv_sec, tv[1].tv_usec); else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%ld.%06ld]", tv[0].tv_sec, tv[0].tv_usec); } else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); } %} function _struct_compat_timeval_u:string(uaddr:long, n:long) %{ /* pure */ #ifdef CONFIG_COMPAT int n = (int)STAP_ARG_n; struct compat_timeval tv[n]; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL || n < 1 || n > 2) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char*)&tv, ptr, n*sizeof(struct compat_timeval)) == 0) { if (n == 2) snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%ld.%06ld][%ld.%.06ld]", (long)tv[0].tv_sec, (long)tv[0].tv_usec, (long)tv[1].tv_sec, (long)tv[1].tv_usec); else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%ld.%06ld]", (long)tv[0].tv_sec, (long)tv[0].tv_usec); } else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); } #endif %} function _struct_timezone_u:string(uaddr:long) %{ /* pure */ struct timezone tz; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char*)&tz, ptr, sizeof(struct timezone)) == 0) snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%d, %d]", tz.tz_minuteswest, tz.tz_dsttime); else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); } %} %{ // Needed for the following four functions // _struct_utimbuf_actime, _struct_utimbuf_modtime, // _struct_compat_utimbuf_actime, _struct_compat_utimbuf_modtime #include <linux/utime.h> %} function _stp_clock_nanosleep_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ static const _stp_val_array nanosleep_flags_list[] = { V(TIMER_ABSTIME), {0, NULL} }; _stp_lookup_str(nanosleep_flags_list, (unsigned int)STAP_ARG_flags, STAP_RETVALUE, MAXSTRINGLEN); %} // Returns the value of the actime field of a utimbuf in user space // at the given address, or zero on when userspace data is not accessible. function _struct_utimbuf_actime:long(uaddr:long) %{ /* pure */ struct utimbuf ubuf; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL) STAP_RETVALUE = 0; else if(_stp_copy_from_user((char*)&ubuf,ptr,sizeof(ubuf)) == 0) STAP_RETVALUE = ubuf.actime; else STAP_RETVALUE = 0; %} // Returns the value of the modtime field of a utimbuf in user space // at the given address, or zero on when userspace data is not accessible. function _struct_utimbuf_modtime:long(uaddr:long) %{ /* pure */ struct utimbuf ubuf; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL) STAP_RETVALUE = 0; else if(_stp_copy_from_user((char*)&ubuf,ptr,sizeof(ubuf)) == 0) STAP_RETVALUE = ubuf.modtime; else STAP_RETVALUE = 0; %} // Returns the value of the actime field of a compat_utimbuf in user space // at the given address, or zero on when userspace data is not accessible. function _struct_compat_utimbuf_actime:long(uaddr:long) %{ /* pure */ #ifdef CONFIG_COMPAT struct compat_utimbuf ubuf; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL) STAP_RETVALUE = 0; else if(_stp_copy_from_user((char*)&ubuf,ptr,sizeof(ubuf)) == 0) STAP_RETVALUE = ubuf.actime; else STAP_RETVALUE = 0; #endif %} // Returns the value of the modtime field of a compat_utimbuf in user space // at the given address, or zero on when userspace data is not accessible. function _struct_compat_utimbuf_modtime:long(uaddr:long) %{ /* pure */ #ifdef CONFIG_COMPAT struct compat_utimbuf ubuf; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL) STAP_RETVALUE = 0; else if(_stp_copy_from_user((char*)&ubuf,ptr,sizeof(ubuf)) == 0) STAP_RETVALUE = ubuf.modtime; else STAP_RETVALUE = 0; #endif %} function _struct_timespec_u:string(uaddr:long, n:long) %{ /* pure */ #define STP_UTIME_NOW ((1l << 30) - 1l) #define STP_UTIME_OMIT ((1l << 30) - 2l) int n = (int)STAP_ARG_n; struct timespec ts[n]; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL || n < 1 || n > 2) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char *)&ts, ptr, n*sizeof(struct timespec))) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); } else { char *str; int len, i = 0; ptr = STAP_RETVALUE; while (i < n) { str = NULL; if (ts[i].tv_nsec == STP_UTIME_NOW) str = "UTIME_NOW"; else if (ts[i].tv_nsec == STP_UTIME_OMIT) str = "UTIME_OMIT"; if (str) len = snprintf(ptr, MAXSTRINGLEN, "[%s]", str); else len = snprintf(ptr, MAXSTRINGLEN, "[%ld.%09ld]", (long)ts[i].tv_sec, ts[i].tv_nsec); ptr += len; i++; } } } #undef STP_UTIME_NOW #undef STP_UTIME_OMIT %} function _struct_compat_timespec_u:string(uaddr:long, n:long) %{ /* pure */ #ifdef CONFIG_COMPAT #define STP_UTIME_NOW ((1l << 30) - 1l) #define STP_UTIME_OMIT ((1l << 30) - 2l) int n = (int)STAP_ARG_n; struct compat_timespec ts[n]; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL || n < 1 || n > 2) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char *)&ts, ptr, n*sizeof(struct compat_timespec))) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); } else { char *str; int len, i = 0; ptr = STAP_RETVALUE; while (i < n) { str = NULL; if (ts[i].tv_nsec == STP_UTIME_NOW) str = "UTIME_NOW"; else if (ts[i].tv_nsec == STP_UTIME_OMIT) str = "UTIME_OMIT"; if (str) len = snprintf(ptr, MAXSTRINGLEN, "[%s]", str); else len = snprintf(ptr, MAXSTRINGLEN, "[%ld.%09ld]", (long)ts[i].tv_sec, (long)ts[i].tv_nsec); ptr += len; i++; } } } #undef STP_UTIME_NOW #undef STP_UTIME_OMIT #endif %} function _struct_itimerspec_u:string(uaddr:long) %{ /* pure */ struct itimerspec its; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char *)&its, ptr,sizeof(struct itimerspec))) snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%d.%06d,%d.%06d]", (int)its.it_interval.tv_sec, (int)its.it_interval.tv_nsec, (int)its.it_value.tv_sec, (int)its.it_value.tv_nsec); } %} function _struct_compat_itimerspec_u:string(uaddr:long) %{ /* pure */ #ifdef CONFIG_COMPAT struct compat_itimerspec its; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char *)&its, ptr, sizeof(its))) snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%d.%06d,%d.%06d]", (int)its.it_interval.tv_sec, (int)its.it_interval.tv_nsec, (int)its.it_value.tv_sec, (int)its.it_value.tv_nsec); } #endif %} function _struct_itimerval_u:string(uaddr:long) %{ /* pure */ struct itimerval itv; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char *)&itv,ptr,sizeof(struct itimerval))) snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%d.%06d,%d.%06d]", (int)itv.it_interval.tv_sec, (int)itv.it_interval.tv_usec, (int)itv.it_value.tv_sec, (int)itv.it_value.tv_usec); } %} function _struct_compat_itimerval_u:string(uaddr:long) %{ /* pure */ #ifdef CONFIG_COMPAT struct compat_itimerval itv; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char *)&itv,ptr,sizeof(struct compat_itimerval))) snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%d.%06d,%d.%06d]", (int)itv.it_interval.tv_sec, (int)itv.it_interval.tv_usec, (int)itv.it_value.tv_sec, (int)itv.it_value.tv_usec); } #endif %} %{ // Needed for @__private30 function _struct_sockaddr_u_impl. Unfortunately cannot be // inlined into the function since these header files define static // functions themselves. #include <linux/socket.h> #include <linux/in.h> #include <linux/netlink.h> %} %{ // Enum for _struct_sockaddr_u_* functions. typedef enum { SA_PRETTY = 1, SA_IP_ADDR = 2, SA_TCP_PORT = 4, SA_FAMILY = 8, SA_IPV6_FLOWINFO = 16, SA_IPV6_SCOPE_ID = 32, } sa_dispatch; %} function _struct_sockaddr_u_ip_addr:string(uaddr:long, len:long) { return _struct_sockaddr_u_impl(uaddr, len, @const("SA_IP_ADDR")); } function _struct_sockaddr_u_tcp_port:string(uaddr:long, len:long) { return _struct_sockaddr_u_impl(uaddr, len, @const("SA_TCP_PORT")); } @__private30 function _struct_sockaddr_u_ip_addr_tcp_port:string(uaddr:long, len:long) { return _struct_sockaddr_u_impl(uaddr, len, @const("SA_IP_ADDR") | @const("SA_TCP_PORT")); } function _struct_sockaddr_u_sa_family:string(uaddr:long, len:long) { return _struct_sockaddr_u_impl(uaddr, len, @const("SA_FAMILY")); } function _struct_sockaddr_u_ipv6_flowinfo:string(uaddr:long, len:long) { return _struct_sockaddr_u_impl(uaddr, len, @const("SA_IPV6_FLOWINFO")); } function _struct_sockaddr_u_ipv6_scope_id:string(uaddr:long, len:long) { return _struct_sockaddr_u_impl(uaddr, len, @const("SA_IPV6_SCOPE_ID")); } function _struct_sockaddr_u:string(uaddr:long, len:long) { return _struct_sockaddr_u_impl(uaddr, len, @const("SA_PRETTY")); } %{ #define STAP_NEED_CONTEXT_SOCKADDR_BIG_BUFFERS 1 %} @__private30 function _struct_sockaddr_u_impl:string(uaddr:long, len:long, what:long) %{ /* pure */ #include <linux/version.h> #include <linux/in6.h> #include <linux/un.h> #include <linux/if_packet.h> sa_dispatch what = (sa_dispatch)STAP_ARG_what; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; size_t len = clamp_t(size_t, STAP_ARG_len, 0, 128); struct sockaddr *sa = (struct sockaddr *)CONTEXT->buf; char *stap_retvalue = (char *)(unsigned long)STAP_RETVALUE; int maxstringlen = MAXSTRINGLEN; size_t n; if (ptr == NULL) { strlcpy(STAP_RETVALUE, "NULL", MAXSTRINGLEN); return; } // This helps handle variable lenght sockaddr_un. // Some application - like systemd - sends path string // without ending null character. Kernel will handle this // but we need pretty output without random memory stuff. memset(CONTEXT->buf, 0, 128); if (_stp_copy_from_user(CONTEXT->buf, ptr, len)) { strlcpy(STAP_RETVALUE, "{...}", MAXSTRINGLEN); return; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) #define LPORT (inet->inet.num) #define DADDR (&inet->inet.daddr) #else #define LPORT (inet->num) #define DADDR (&inet->daddr) #endif // Use kernel builtin instead of picking up user space ntohs (function). #define _stp_ntohs be16_to_cpu if ((sa->sa_family == AF_INET) && (len == sizeof(struct sockaddr_in))) { struct sockaddr_in *sin = (struct sockaddr_in *)CONTEXT->buf; if (what & SA_PRETTY) { #ifndef NIPQUAD_FMT // kver >= 2.6.36 snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_INET, %pI4, %d}", &sin->sin_addr, _stp_ntohs(sin->sin_port)); #else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_INET, " NIPQUAD_FMT ", %d}", NIPQUAD(sin->sin_addr), _stp_ntohs(sin->sin_port)); #endif return; } if (what & SA_FAMILY) { n = strlcpy(stap_retvalue, "AF_INET", maxstringlen); // (n - 1) mean: cut of null char stap_retvalue += (n); maxstringlen -= (n - 1); } if (what & SA_IP_ADDR) { #ifndef NIPQUAD_FMT // kver >= 2.6.36 n = snprintf(stap_retvalue, maxstringlen, "%pI4", &sin->sin_addr); #else n = snprintf(stap_retvalue, maxstringlen, NIPQUAD_FMT, NIPQUAD(sin->sin_addr)); #endif // (n - 1) mean: cut of null char stap_retvalue += (n); maxstringlen -= (n - 1); } if (what & SA_TCP_PORT) { n = snprintf(stap_retvalue, maxstringlen, "%d", _stp_ntohs(sin->sin_port)); // (n - 1) mean: cut of null char stap_retvalue += (n); maxstringlen -= (n - 1); } } // Why 2 * sizeof (char) here? // Because I want to support abstract sockets with // at least one usable byte after initial \0 char. // Unnamed sockets aren't supported yet. else if ((sa->sa_family == AF_UNIX) && ((len == sizeof(struct sockaddr_un)) || (len >= ((sizeof(sa_family_t)) + (2 * sizeof(char)))))) { struct sockaddr_un *sun = (struct sockaddr_un *)CONTEXT->buf; if (what & SA_PRETTY) { // Support for abstract sockets if (sun->sun_path[0] == '\0') { // Abstract sockets aren't string oriented. // We need conversion on this place. // No check of ret value, because _stp_text_str returns // "<unknown>" if bad things happen. _stp_text_str(CONTEXT->out_str, &sun->sun_path[1], len - sizeof(sa_family_t), MAXSTRINGLEN - 1, 0, 0, 1); // Why a precision of (MAXSTRINGLEN - 18) here? To // make sure the formatted string doesn't get // truncated by a long out_str variable, we'll specify // the maximum number of characters to add from // out_str. That number is MAXSTRINGLEN - 17 (the // length of the 'static' part of the format string) - // 1 (for the formatted string's null character). snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_UNIX, \"\\000%.*s\"}", (MAXSTRINGLEN - 18), CONTEXT->out_str); } else { // Just cut path if is too long CONTEXT->buf[127] = '\0'; snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_UNIX, \"%s\"}", sun->sun_path); } } else if (what & SA_FAMILY) { strlcpy(STAP_RETVALUE, "AF_UNIX", MAXSTRINGLEN); } else { strlcpy(STAP_RETVALUE, "", MAXSTRINGLEN); } } else if ((sa->sa_family == AF_NETLINK) && (len == sizeof(struct sockaddr_nl))) { struct sockaddr_nl *nl = (struct sockaddr_nl *)CONTEXT->buf; if (what & SA_PRETTY) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_NETLINK, pid=%d, groups=%08x}", nl->nl_pid, nl->nl_groups); } else if (what & SA_FAMILY) { strlcpy(STAP_RETVALUE, "AF_NETLINK", MAXSTRINGLEN); } else { strlcpy(STAP_RETVALUE, "", MAXSTRINGLEN); } } else if ((sa->sa_family == AF_INET6) && (len == sizeof(struct sockaddr_in6))) { struct sockaddr_in6 *sin = (struct sockaddr_in6 *)CONTEXT->buf; if (what & SA_PRETTY) { #ifndef NIP6_FMT // kver >= 2.6.36 snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_INET6, %pI6, %d}", &sin->sin6_addr, _stp_ntohs(sin->sin6_port)); #else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_INET6, " NIP6_FMT ", %d}", NIP6(sin->sin6_addr), _stp_ntohs(sin->sin6_port)); #endif return; } if (what & SA_FAMILY) { n = strlcpy(stap_retvalue, "AF_INET6", maxstringlen); // (n - 1) mean: cut of null char stap_retvalue += (n); maxstringlen -= (n - 1); } if (what & SA_IP_ADDR) { #ifndef NIP6_FMT // kver >= 2.6.36 n = snprintf(stap_retvalue, maxstringlen, "%pI6", &sin->sin6_addr); #else n = snprintf(stap_retvalue, maxstringlen, NIP6_FMT, NIP6(sin->sin6_addr)); #endif // (n - 1) mean: cut of null char stap_retvalue += (n); maxstringlen -= (n - 1); } if (what & SA_TCP_PORT) { n = snprintf(stap_retvalue, maxstringlen, "%d", _stp_ntohs(sin->sin6_port)); // (n - 1) mean: cut of null char stap_retvalue += (n); maxstringlen -= (n - 1); } if (what & SA_IPV6_FLOWINFO) { n = snprintf(stap_retvalue, maxstringlen, "%d", sin->sin6_flowinfo); // (n - 1) mean: cut of null char stap_retvalue += (n); maxstringlen -= (n - 1); } if (what & SA_IPV6_SCOPE_ID) { n = snprintf(stap_retvalue, maxstringlen, "%d", sin->sin6_flowinfo); // (n - 1) mean: cut of null char stap_retvalue += (n); maxstringlen -= (n - 1); } } else if ((sa->sa_family == AF_PACKET) && (len == sizeof(struct sockaddr_ll))) { struct sockaddr_ll *sll = (struct sockaddr_ll *)CONTEXT->buf; if (what & SA_PRETTY) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_PACKET, proto=%d, ind=%d, hatype=%d, pkttype=%d, halen=%d, addr=0x%llx}", (int)sll->sll_protocol, sll->sll_ifindex, (int)sll->sll_hatype, (int)sll->sll_pkttype, (int)sll->sll_halen, (long long)(*(uint64_t *)sll->sll_addr)); } else if (what & SA_FAMILY) { strlcpy(STAP_RETVALUE, "AF_PACKET", MAXSTRINGLEN); } else { strlcpy(STAP_RETVALUE, "", MAXSTRINGLEN); } } else { if (len >= sizeof(sa_family_t)) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{unknown sockaddr with sa=%d, salen=%d}", sa->sa_family, (int) len); } else { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{unknown sockaddr with salen=%d}", (int)len); } } %} function _struct_rlimit_u:string(uaddr:long) %{ /* pure */ struct rlimit rl; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char *)&rl, ptr, sizeof(struct rlimit)) == 0) snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%ld,%ld]", rl.rlim_cur, rl.rlim_max); else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); } %} function _fildes_index_u:long (uaddr:long, index:long) %{ /* pure */ int fd[2]; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL || !(STAP_ARG_index == 0 || STAP_ARG_index == 1)) STAP_RETVALUE = 0; else { if (_stp_copy_from_user((char *)&fd, ptr, 2*sizeof(int)) == 0) STAP_RETVALUE = fd[STAP_ARG_index]; else STAP_RETVALUE = 0; } %} function __sem_flags:string(semflg:long) %{ /* pure */ /* unprivileged */ long semflg = STAP_ARG_semflg; char *str = STAP_RETVALUE; int mode; int len; int flag = 0; mode = semflg & S_IRWXUGO; semflg &= ~S_IRWXUGO; str[0] = '\0'; if (semflg & IPC_CREAT) { strlcat(str, "IPC_CREAT", MAXSTRINGLEN); semflg &= ~IPC_CREAT; flag = 1; } if (semflg & IPC_EXCL) { if (flag) strlcat(str, "|", MAXSTRINGLEN); strlcat(str, "IPC_EXCL", MAXSTRINGLEN); semflg &= ~IPC_EXCL; flag = 1; } if (semflg) { if (flag) strlcat(str, "|", MAXSTRINGLEN); len = strlen(str); _stp_snprintf(str + len, MAXSTRINGLEN - len, "0x%lx", semflg); flag = 1; } if (mode) { if (flag) strlcat(str, "|", MAXSTRINGLEN); len = strlen(str); _stp_snprintf(str + len, MAXSTRINGLEN - len, "%#o", mode); } %} %(systemtap_v <= "3.2" %? @__private30 function __user_pointer:long (addr:long) { return user_long_error(addr) } %) /* This function copies an argv from userspace. */ function __get_argv:string(argv:long, first:long) { %( CONFIG_64BIT == "y" %? str = "[" if (first && argv) # 8 == sizeof(long) on a 64-bit OS argv += (8 * first) while (argv) { try { vstr = user_long_error(argv) } catch { if (len) str .= ", " str .= sprintf("0x%x", argv) break } if (vstr == 0) break if (len) str .= ", " str .= user_string_quoted(vstr) newlen = strlen(str) if (newlen == len) break len = newlen # 8 == sizeof(long) on a 64-bit OS argv += 8 } str .= "]" return str %: return __get_compat_argv(argv, first) %) } /* This function copies an argv from userspace. */ function __get_compat_argv:string(argv:long, first:long) { str = "[" if (first && argv) # 4 == sizeof(long) on a 32-bit OS argv += (4 * first) while (argv) { try { vstr = user_long_error(argv) & 0xffffffff } catch { if (len) str .= ", " str .= sprintf("0x%x", argv) break } if (vstr == 0) break if (len) str .= ", " str .= user_string_quoted(vstr) newlen = strlen(str) if (newlen == len) break len = newlen # 4 == sizeof(long) on a 32-bit OS argv += 4 } str .= "]" return str } %( systemtap_v <= "3.2" %? /* * The __count_envp() and __count_compat_envp() functions aren't * used anywhere, so let's deprecate them. */ /* Count the number of environment variables. */ function __count_envp:string(envp:long) { %( CONFIG_64BIT == "y" %? __argc = 0 while (envp) { # We can call 'user_long(envp)' here because we don't # need to know the difference between a bad address # and just getting a 0. vstr = user_long(envp) if (vstr == 0) break __argc++ # 8 == sizeof(long) on a 64-bit OS envp += 8 } return sprintf("[/* %d var%s */]", __argc, __argc != 1 ? "s" : "") %: return __count_compat_envp(envp) %) } function __count_compat_envp:string(envp:long) { __argc = 0 while (envp) { # We can call 'user_long(envp)' here because we don't # need to know the difference between a bad address # and just getting a 0. vstr = user_long(envp) if (vstr == 0) break __argc++ # 4 == sizeof(long) on a 32-bit OS envp += 4 } return sprintf("[/* %d var%s */]", __argc, __argc != 1 ? "s" : "") } %) %(systemtap_v <= "2.7" %? /* * This function isn't actually used anywhere, so let's deprecate it. * * Return the symbolic string representation * of the struct timex.mode member of adjtimex * consult `man adjtimex` for more information * CALLERS: * syscall.adjtimex */ function _adjtx_mode_str(f) { if((f & 32769) == 32769) bs="ADJ_OFFSET_SINGLESHOT|".bs if(f & 16384) bs="ADJ_TICK|".bs if(f & 32) bs="ADJ_TIMECONST|".bs if(f & 16) bs="ADJ_STATUS|".bs if(f & 8) bs="ADJ_ESTERROR|".bs if(f & 4) bs="ADJ_MAXERROR|".bs if(f & 2) bs="ADJ_FREQUENCY|".bs if(f & 1 && ((f & 32769) != 32769)) bs="ADJ_OFFSET|".bs return substr(bs,0,strlen(bs)-1) } %) %{ #include <linux/random.h> static const _stp_val_array _stp_getrandom_list[] = { #ifdef GRND_NONBLOCK V(GRND_NONBLOCK), #endif #ifdef GRND_RANDOM V(GRND_RANDOM), #endif {0, NULL} }; %} function _getrandom_flags_str:string(flag:long) %{ /* pure */ /* unprivileged */ unsigned int grflag = (unsigned int)STAP_ARG_flag; _stp_lookup_or_str(_stp_getrandom_list, grflag, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #if (defined(CONFIG_INOTIFY) || defined(CONFIG_INOTIFY_USER)) #include <linux/inotify.h> #endif /* Ignore helper events IN_CLOSE and IN_MOVE, which are just * combinations of other events. */ static const _stp_val_array _stp_inotify_watch_mask_list[] = { V(IN_ACCESS), V(IN_MODIFY), V(IN_ATTRIB), V(IN_CLOSE_WRITE), V(IN_CLOSE_NOWRITE), V(IN_OPEN), V(IN_MOVED_FROM), V(IN_MOVED_TO), V(IN_CREATE), V(IN_DELETE), V(IN_DELETE_SELF), V(IN_MOVE_SELF), V(IN_UNMOUNT), V(IN_Q_OVERFLOW), V(IN_IGNORED), V(IN_ONLYDIR), V(IN_DONT_FOLLOW), #ifdef IN_EXCL_UNLINK V(IN_EXCL_UNLINK), #endif V(IN_MASK_ADD), V(IN_ISDIR), V(IN_ONESHOT), {0, NULL} }; %} function _inotify_watch_mask_str:string(mask:long) %{ /* pure */ /* unprivileged */ uint32_t mask = (uint32_t)STAP_ARG_mask; _stp_lookup_or_str(_stp_inotify_watch_mask_list, mask, STAP_RETVALUE, MAXSTRINGLEN); %} /* * Return the symbolic string representation * of the how argument given in *sigprocmask * consult `man sigprocmask` for more info * CALLERS: * syscall.sigprocmask * syscall.rt_sigprocmask */ function _sigprocmask_how_str:string(how:long) %{ /* pure */ /* unprivileged */ int len; char *str = STAP_RETVALUE; switch (STAP_ARG_how) { case SIG_BLOCK: strlcpy(str, "SIG_BLOCK", MAXSTRINGLEN); break; case SIG_UNBLOCK: strlcpy(str, "SIG_UNBLOCK", MAXSTRINGLEN); break; case SIG_SETMASK: strlcpy(str, "SIG_SETMASK", MAXSTRINGLEN); break; default: snprintf(str, MAXSTRINGLEN, "0x%lx", (long)STAP_ARG_how); } %} /* * Return the symbolic string representation * of the which argument given to setitimer * consult `man setitimer` for more info * CALLERS: * syscall.getitimer * syscall.setitimer * INCLUDE: <linux/time.h> */ %{ #include <linux/time.h> static const _stp_val_array _stp_itimer_which_list[] = { V(ITIMER_REAL), V(ITIMER_VIRTUAL), V(ITIMER_PROF), {0, NULL} }; %} function _itimer_which_str:string(which:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_itimer_which_list, (unsigned int)STAP_ARG_which, STAP_RETVALUE, MAXSTRINGLEN); %} /* * Return the command name for nfsservctl() * nfsservctl was removed in kernel 3.0/2.6.40. */ %( kernel_v < "2.6.40" && CONFIG_NFSD == "[ym]" %? %{ #include <linux/sunrpc/svc.h> #include <linux/nfsd/nfsfh.h> #include <linux/nfsd/syscall.h> static const _stp_val_array _stp_nfsctl_cmd_list[] = { V(NFSCTL_SVC), V(NFSCTL_ADDCLIENT), V(NFSCTL_DELCLIENT), V(NFSCTL_EXPORT), V(NFSCTL_UNEXPORT), #ifdef NFSCTL_UGIDUPDATE V(NFSCTL_UGIDUPDATE), #endif #ifdef NFSCTL_GETFH V(NFSCTL_GETFH), #endif V(NFSCTL_GETFD), V(NFSCTL_GETFS), {0, NULL} }; %} function _nfsctl_cmd_str:string(cmd:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_nfsctl_cmd_list, (unsigned int)STAP_ARG_cmd, STAP_RETVALUE, MAXSTRINGLEN); %} %) /* * Return the symbolic string representation * of the clockid argument given to create_timer * consult `man create_timer` for more info * CALLERS: * syscall.timer_create * syscall.clock_settime * syscall.clock_gettime * syscall.clock_getres * syscall.clock_nanosleep */ %{ #include <linux/time.h> static const _stp_val_array _stp_wc_str_list[] = { V(CLOCK_REALTIME), V(CLOCK_MONOTONIC), V(CLOCK_PROCESS_CPUTIME_ID), V(CLOCK_THREAD_CPUTIME_ID), #ifdef CLOCK_MONOTONIC_RAW V(CLOCK_MONOTONIC_RAW), #endif #ifdef CLOCK_REALTIME_COARSE V(CLOCK_REALTIME_COARSE), #endif #ifdef CLOCK_MONOTONIC_COARSE V(CLOCK_MONOTONIC_COARSE), #endif #ifdef CLOCK_BOOTTIME V(CLOCK_BOOTTIME), #endif #ifdef CLOCK_REALTIME_ALARM V(CLOCK_REALTIME_ALARM), #endif #ifdef CLOCK_BOOTTIME_ALARM V(CLOCK_BOOTTIME_ALARM), #endif V(CLOCK_SGI_CYCLE), #ifdef CLOCK_TAI V(CLOCK_TAI), #endif {0, NULL} }; %} function _get_wc_str:string(wc:long) %{ /* pure */ /* unprivileged */ unsigned int clkid = (unsigned int)STAP_ARG_wc; _stp_lookup_str(_stp_wc_str_list, clkid, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/fcntl.h> static const _stp_val_array _stp_flock_cmd_list[] = { V(LOCK_SH), V(LOCK_EX), V(LOCK_NB), V(LOCK_UN), V(LOCK_MAND), V(LOCK_READ), V(LOCK_WRITE), V(LOCK_RW), {0, NULL} }; static const _stp_val_array _stp_pipe2_flags_list[] = { #ifdef O_NONBLOCK V(O_NONBLOCK), #endif #ifdef O_CLOEXEC V(O_CLOEXEC), #endif #ifdef O_DIRECT V(O_DIRECT), #endif {0, NULL} }; %} function _flock_cmd_str:string(c:long) %{ /* pure */ /* unprivileged */ _stp_lookup_or_str(_stp_flock_cmd_list, (unsigned int)STAP_ARG_c, STAP_RETVALUE, MAXSTRINGLEN); %} /* `man 2 pipe2` for more information */ function _sys_pipe2_flag_str:string (f:long) %{ /* pure */ /* unprivileged */ unsigned int flags = STAP_ARG_f; _stp_lookup_or_str(_stp_pipe2_flags_list, flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/fcntl.h> static const _stp_val_array _stp_open_mode_flags_list[] = { #ifdef O_CREAT V(O_CREAT), #endif #ifdef O_EXCL V(O_EXCL), #endif #ifdef O_NOCTTY V(O_NOCTTY), #endif #ifdef O_TRUNC V(O_TRUNC), #endif #ifdef O_APPEND V(O_APPEND), #endif #ifdef O_NONBLOCK V(O_NONBLOCK), #endif /* Here's a comment from the kernel source: * * ==== * Before Linux 2.6.33 only O_DSYNC semantics were implemented, but using * the O_SYNC flag. We continue to use the existing numerical value * for O_DSYNC semantics now, but using the correct symbolic name for it. * This new value is used to request true Posix O_SYNC semantics. It is * defined in this strange way to make sure applications compiled against * new headers get at least O_DSYNC semantics on older kernels. * ==== * * On RHEL6 (2.6.32-431.3.1.el6.x86_64), the user headers are ahead of * the kernel source and define O_DSYNC, but the kernel just ignores * the extra bit set. We'll try to handle it here. */ #ifndef O_DSYNC { O_SYNC | 04000000, "O_SYNC" }, #endif #ifdef O_SYNC V(O_SYNC), #endif #ifdef O_DSYNC V(O_DSYNC), #endif #ifdef O_ASYNC V(O_ASYNC), #elif defined(FASYNC) { FASYNC, "O_ASYNC" }, #endif #ifdef O_DIRECT V(O_DIRECT), #endif #ifdef O_LARGEFILE V(O_LARGEFILE), #endif #ifdef O_DIRECTORY V(O_DIRECTORY), #endif #ifdef O_NOFOLLOW V(O_NOFOLLOW), #endif #ifdef O_NOATIME V(O_NOATIME), #endif #ifdef O_CLOEXEC V(O_CLOEXEC), #endif #ifdef O_PATH V(O_PATH), #endif {0, NULL} }; %} /* `man 2 open` for more information */ function _sys_open_flag_str:string (f:long) %{ /* pure */ /* unprivileged */ int flags = (int)STAP_ARG_f; int acc = flags & O_ACCMODE; switch (acc) { case O_WRONLY: strlcpy (STAP_RETVALUE, "O_WRONLY", MAXSTRINGLEN); break; case O_RDWR: strlcpy (STAP_RETVALUE, "O_RDWR", MAXSTRINGLEN); break; default: strlcpy (STAP_RETVALUE, "O_RDONLY", MAXSTRINGLEN); } flags &= ~O_ACCMODE; if (flags) { strlcat(STAP_RETVALUE, "|", MAXSTRINGLEN); _stp_lookup_or_str(_stp_open_mode_flags_list, flags, STAP_RETVALUE, MAXSTRINGLEN); } %} %{ /* Notice that the kernel defines and the user defines are named * differently. */ static const _stp_val_array _stp_access_mode_list[] = { {0, "F_OK"}, {MAY_READ, "R_OK"}, {MAY_WRITE, "W_OK"}, {MAY_EXEC, "X_OK"}, {0, NULL} }; %} /* `man 2 open` for more information */ function _access_mode_str:string(mode:long) %{ /* pure */ /* unprivileged */ unsigned int mode = (unsigned int)STAP_ARG_mode; _stp_lookup_or_str(_stp_access_mode_list, mode, STAP_RETVALUE, MAXSTRINGLEN); %} /* `man 2 open` for more information */ @__private30 function _sys_open_mode_str(f) { if ((f & @const("S_IRWXU")) == @const("S_IRWXU")) bs="S_IRWXU|".bs else { if (f & @const("S_IRUSR")) bs="S_IRUSR|" . bs if (f & @const("S_IWUSR")) bs="S_IWUSR|" . bs if (f & @const("S_IXUSR")) bs="S_IXUSR|" . bs } if ((f & @const("S_IRWXG")) == @const("S_IRWXG")) bs="S_IRWXG|" . bs else { if (f & @const("S_IRGRP")) bs="S_IRGRP|" . bs if (f & @const("S_IWGRP")) bs="S_IWGRP|" . bs if (f & @const("S_IXGRP")) bs="S_IXGRP|" . bs } if ((f & @const("S_IRWXO")) == @const("S_IRWXO")) bs="S_IRWXO|" . bs else { if (f & @const("S_IROTH")) bs="S_IROTH|" . bs if (f & @const("S_IWOTH")) bs="S_IWOTH|" . bs if (f & @const("S_IXOTH")) bs="S_IXOTH|" . bs } return (strlen(bs) > 0) ? substr(bs, 0, strlen(bs) - 1) : sprintf("%#o", f) } /* `man 2 mknod` for more information */ function _mknod_mode_str:string(mode:long) { type = mode & @const("S_IFMT") mode &= ~@const("S_IFMT") if (type == @const("S_IFREG")) return sprintf("S_IFREG|%#o", mode) if (type == @const("S_IFCHR")) return sprintf("S_IFCHR|%#o", mode) if (type == @const("S_IFBLK")) return sprintf("S_IFBLK|%#o", mode) if (type == @const("S_IFIFO")) return sprintf("S_IFIFO|%#o", mode) if (type == @const("S_IFSOCK")) return sprintf("S_IFSOCK|%#o", mode) return sprintf("%#o", type | mode) } %{ #include <linux/mman.h> static const _stp_val_array _stp_msync_flag_list[] = { V(MS_ASYNC), V(MS_INVALIDATE), V(MS_SYNC), {0, NULL} }; %} /* `man msync` for more information */ function _msync_flag_str:string(f:long) %{ /* pure */ /* unprivileged */ uint32_t flags = (uint32_t)STAP_ARG_f; _stp_lookup_or_str(_stp_msync_flag_list, flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/wait.h> static const _stp_val_array _stp_wait4_op_list[] = { V(WNOHANG), #if !defined(WSTOPPED) && defined(WUNTRACED) V(WUNTRACED), #endif V(WEXITED), #ifdef WSTOPPED V(WSTOPPED), #endif V(WCONTINUED), V(WNOWAIT), V(__WNOTHREAD), V(__WALL), V(__WCLONE), {0, NULL} }; %} %(systemtap_v <= "2.7" %? function _internal_wait_opt_str:string(f:long, bit_num:long, bit_str:string) %{ /* pure */ /* unprivileged */ /* ignore bit_num and bit_str */ _stp_lookup_or_str(_stp_wait4_op_list, (unsigned int)STAP_ARG_f, STAP_RETVALUE, MAXSTRINGLEN); %} /* `man waitid` for more information */ function _waitid_opt_str:string(f:long) %{ /* pure */ /* unprivileged */ _stp_lookup_or_str(_stp_wait4_op_list, (unsigned int)STAP_ARG_f, STAP_RETVALUE, MAXSTRINGLEN); %} %) /* `man wait4` for more information */ function _wait4_opt_str:string(f:long) %{ /* pure */ /* unprivileged */ _stp_lookup_or_str(_stp_wait4_op_list, (unsigned int)STAP_ARG_f, STAP_RETVALUE, MAXSTRINGLEN); %} function WIFEXITED(f) { return (f & 0x7f) == 0 } function WEXITSTATUS(f) { return (f & 0xff00) >> 8 } @__private30 function WIFSIGNALED(f) { return (f & 0x7f) != 0 && (f & 0x7f) != 0x7f } @__private30 function WCOREDUMP(f) { return f & 0x80 } function WTERMSIG(f) { return f & 0x7f } @__private30 function WIFSTOPPED(f) { return (f & 0xff) == 0x7f } @__private30 function WSTOPSIG(f) { return (f & 0xff00) >> 8 } @__private30 function WIFCONTINUED(f) { return f == 0xffff } @__private30 function _ptrace_event_name(f) { if (f == @const("PTRACE_EVENT_FORK")) return "PTRACE_EVENT_FORK" if (f == @const("PTRACE_EVENT_VFORK")) return "PTRACE_EVENT_VFORK" if (f == @const("PTRACE_EVENT_CLONE")) return "PTRACE_EVENT_CLONE" if (f == @const("PTRACE_EVENT_EXEC")) return "PTRACE_EVENT_EXEC" if (f == @const("PTRACE_EVENT_VFORK_DONE")) return "PTRACE_EVENT_VFORK_DONE" if (f == @const("PTRACE_EVENT_EXIT")) return "PTRACE_EVENT_EXIT" return "" } /* `man 2 wait` for more information */ function _wait_status_str(f) { if ((f >> 16) != 0) tail = sprintf (" | 0x%x", f & ~0xffff) else tail = "" if (WIFEXITED(f)) return sprintf ("WEXITSTATUS=%d", WEXITSTATUS(f)).tail if (WIFSIGNALED(f)) { if (WCOREDUMP(f)) return "WCOREDUMP".tail return sprintf ("WTERMSIG=%s", _signal_name(WTERMSIG(f))).tail } if (WIFSTOPPED(f)) { if (WSTOPSIG(f) == @const("SIGTRAP")) { event = _ptrace_event_name (f >> 16) if (event != "") tail = " | ".event." << 8" } return sprintf ("WSTOPSIG=%s", _signal_name(WSTOPSIG(f))).tail } if (WIFCONTINUED(f)) return "WIFCONTINUED".tail return sprintf ("?=0x%x", f) } %{ #include <linux/seccomp.h> static const _stp_val_array _stp_seccomp_flags_list[] = { #ifdef SECCOMP_FILTER_FLAG_TSYNC V(SECCOMP_FILTER_FLAG_TSYNC), #endif {0, NULL} }; static const _stp_val_array _stp_seccomp_mode_list[] = { #ifdef SECCOMP_MODE_DISABLED V(SECCOMP_MODE_DISABLED), #endif #ifdef SECCOMP_MODE_STRICT V(SECCOMP_MODE_STRICT), #endif #ifdef SECCOMP_MODE_FILTER V(SECCOMP_MODE_FILTER), #endif {0, NULL} }; %} function _seccomp_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ unsigned int flags = (unsigned int)STAP_ARG_flags; _stp_lookup_str(_stp_seccomp_flags_list, flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ static const _stp_val_array _stp_msg_flags_list[] = { V(MSG_OOB), V(MSG_PEEK), V(MSG_DONTROUTE), V(MSG_TRYHARD), V(MSG_CTRUNC), V(MSG_PROBE), V(MSG_TRUNC), V(MSG_DONTWAIT), V(MSG_EOR), V(MSG_WAITALL), V(MSG_FIN), V(MSG_SYN), V(MSG_CONFIRM), V(MSG_RST), V(MSG_ERRQUEUE), V(MSG_NOSIGNAL), V(MSG_MORE), #ifdef MSG_WAITFORONE V(MSG_WAITFORONE), #endif #ifdef MSG_SENDPAGE_NOTLAST V(MSG_SENDPAGE_NOTLAST), #endif V(MSG_EOF), #ifdef MSG_FASTOPEN V(MSG_FASTOPEN), #endif #ifdef MSG_CMSG_CLOEXEC V(MSG_CMSG_CLOEXEC), #endif {0, NULL} }; %} function _msg_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ // Ignore MSG_CMSG_COMPAT in flags. _stp_lookup_or_str(_stp_msg_flags_list, (STAP_ARG_flags & ~MSG_CMSG_COMPAT), STAP_RETVALUE, MAXSTRINGLEN); %} %(systemtap_v <= "2.5" %? function _sendflags_str:string(flags:long) { return _msg_flags_str(flags) } function _recvflags_str:string(flags:long) { return _msg_flags_str(flags) } %) %{ #ifdef __NR_memfd_create #include <uapi/linux/memfd.h> #endif static const _stp_val_array _stp_mfd_flags_list[] = { #ifdef MFD_CLOEXEC V(MFD_CLOEXEC), #endif #ifdef MFD_ALLOW_SEALING V(MFD_ALLOW_SEALING), #endif {0, NULL} }; %} function _mfd_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ unsigned int flags = (unsigned int)STAP_ARG_flags; _stp_lookup_or_str(_stp_mfd_flags_list, flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/mman.h> static const _stp_val_array _stp_mlock2_flags_list[] = { #ifdef MLOCK_ONFAULT V(MLOCK_ONFAULT), #endif {0, NULL} }; %} /* `man mlock2` for more information */ function _stp_mlock2_str:string(flags:long) %{ /* pure */ /* unprivileged */ uint32_t flags = (uint32_t)STAP_ARG_flags; _stp_lookup_or_str(_stp_mlock2_flags_list, flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/mman.h> static const _stp_val_array _stp_mlockall_flags_list[] = { V(MCL_CURRENT), V(MCL_FUTURE), #ifdef MCL_ONFAULT V(MCL_ONFAULT), #endif {0, NULL} }; %} /* `man mlockall` for more information */ function _mlockall_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ uint32_t flags = (uint32_t)STAP_ARG_flags; _stp_lookup_or_str(_stp_mlockall_flags_list, flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ static const _stp_val_array _stp_module_flags_list[] = { V(O_TRUNC), V(O_NONBLOCK), {0, NULL} }; %} /* used by sys_delete_module */ function _module_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ _stp_lookup_or_str(_stp_module_flags_list, (unsigned int)STAP_ARG_flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/sched.h> #if defined(STAPCONF_LINUX_SCHED_HEADERS) #include <uapi/linux/sched/types.h> #endif static const _stp_val_array _stp_sched_policy_list[] = { {SCHED_NORMAL, "SCHED_OTHER"}, // SCHED_NORMAL==SCHED_OTHER V(SCHED_FIFO), V(SCHED_RR), V(SCHED_BATCH), #ifdef SCHED_IDLE V(SCHED_IDLE), #endif #ifdef SCHED_DEADLINE V(SCHED_DEADLINE), #endif {0, NULL} }; %} function _sched_policy_str:string(policy:long) %{ /* pure */ /* unprivileged */ unsigned int policy = (unsigned int)STAP_ARG_policy; int len; #ifdef SCHED_RESET_ON_FORK if (((int)STAP_ARG_policy > 0) && (policy & SCHED_RESET_ON_FORK)) { strlcpy(STAP_RETVALUE, "SCHED_RESET_ON_FORK|", MAXSTRINGLEN); policy &= ~SCHED_RESET_ON_FORK; } #endif len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_sched_policy_list, policy, STAP_RETVALUE + len, MAXSTRINGLEN - len); %} %{ static const _stp_val_array _stp_priority_which_list[] = { V(PRIO_PROCESS), V(PRIO_PGRP), V(PRIO_USER), {0, NULL} }; %} function _priority_which_str:string(which:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_priority_which_list, (unsigned int)STAP_ARG_which, STAP_RETVALUE, MAXSTRINGLEN); %} %{ static const _stp_val_array _stp_shutdown_how_list[] = { V(SHUT_RD), V(SHUT_WR), V(SHUT_RDWR), {0, NULL} }; %} function _shutdown_how_str:string(how:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_shutdown_how_list, (unsigned int)STAP_ARG_how, STAP_RETVALUE, MAXSTRINGLEN); %} %{ // Needed for function __reboot_magic_str:string. Unfortunately cannot // be inlined into the function since these header file defines static // functions on some architectures. #include <linux/reboot.h> static const _stp_val_array _stp_reboot_magic_list[] = { V(LINUX_REBOOT_MAGIC1), V(LINUX_REBOOT_MAGIC2), V(LINUX_REBOOT_MAGIC2A), V(LINUX_REBOOT_MAGIC2B), V(LINUX_REBOOT_MAGIC2C), {0, NULL} }; %} function _reboot_magic_str:string(magic:long) %{ /* pure */ /* unprivileged */ unsigned int magic = (unsigned int)STAP_ARG_magic; _stp_lookup_str(_stp_reboot_magic_list, magic, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/reboot.h> static const _stp_val_array _stp_reboot_flag_list[] = { V(LINUX_REBOOT_CMD_RESTART), V(LINUX_REBOOT_CMD_HALT), V(LINUX_REBOOT_CMD_CAD_ON), V(LINUX_REBOOT_CMD_CAD_OFF), V(LINUX_REBOOT_CMD_POWER_OFF), V(LINUX_REBOOT_CMD_RESTART2), V(LINUX_REBOOT_CMD_SW_SUSPEND), V(LINUX_REBOOT_CMD_KEXEC), {0, NULL} }; %} function _reboot_flag_str:string(flag:long) %{ /* pure */ /* unprivileged */ unsigned int flag = (unsigned int)STAP_ARG_flag; _stp_lookup_str(_stp_reboot_flag_list, flag, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/wait.h> static const _stp_val_array _stp_waitid_which_list[] = { V(P_ALL), V(P_PID), V(P_PGID), {0, NULL} }; %} function _waitid_which_str:string(flag:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_waitid_which_list, (unsigned int)STAP_ARG_flag, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/futex.h> // We need the following defines to have a value for the // @__futex_argstr() macro. #ifndef FUTEX_WAIT_BITSET #define FUTEX_WAIT_BITSET 9 #endif #ifndef FUTEX_WAKE_BITSET #define FUTEX_WAKE_BITSET 10 #endif #ifndef FUTEX_WAIT_REQUEUE_PI #define FUTEX_WAIT_REQUEUE_PI 11 #endif #ifndef FUTEX_CMP_REQUEUE_PI #define FUTEX_CMP_REQUEUE_PI 12 #endif #ifndef FUTEX_PRIVATE_FLAG #define FUTEX_PRIVATE_FLAG 128 #endif #ifndef FUTEX_WAIT_BITSET_PRIVATE #define FUTEX_WAIT_BITSET_PRIVATE (FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG) #endif #ifndef FUTEX_WAKE_BITSET_PRIVATE #define FUTEX_WAKE_BITSET_PRIVATE (FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG) #endif #ifndef FUTEX_WAIT_REQUEUE_PI_PRIVATE #define FUTEX_WAIT_REQUEUE_PI_PRIVATE (FUTEX_WAIT_REQUEUE_PI | \ FUTEX_PRIVATE_FLAG) #endif #ifndef FUTEX_CMP_REQUEUE_PI_PRIVATE #define FUTEX_CMP_REQUEUE_PI_PRIVATE (FUTEX_CMP_REQUEUE_PI | \ FUTEX_PRIVATE_FLAG) #endif static const _stp_val_array _stp_futex_op_list[] = { V(FUTEX_WAIT), V(FUTEX_WAKE), V(FUTEX_FD), V(FUTEX_REQUEUE), V(FUTEX_CMP_REQUEUE), V(FUTEX_WAKE_OP), V(FUTEX_LOCK_PI), V(FUTEX_UNLOCK_PI), V(FUTEX_TRYLOCK_PI), V(FUTEX_WAIT_BITSET), V(FUTEX_WAKE_BITSET), V(FUTEX_WAIT_REQUEUE_PI), V(FUTEX_CMP_REQUEUE_PI), V(FUTEX_WAIT_PRIVATE), V(FUTEX_WAKE_PRIVATE), V(FUTEX_REQUEUE_PRIVATE), V(FUTEX_CMP_REQUEUE_PRIVATE), V(FUTEX_WAKE_OP_PRIVATE), V(FUTEX_LOCK_PI_PRIVATE), V(FUTEX_UNLOCK_PI_PRIVATE), V(FUTEX_TRYLOCK_PI_PRIVATE), V(FUTEX_WAIT_BITSET_PRIVATE), V(FUTEX_WAKE_BITSET_PRIVATE), V(FUTEX_WAIT_REQUEUE_PI_PRIVATE), V(FUTEX_CMP_REQUEUE_PI_PRIVATE), {0, NULL} }; static const _stp_val_array _stp_futex_wake_ops_list[] = { V(FUTEX_OP_SET), V(FUTEX_OP_ADD), V(FUTEX_OP_OR), V(FUTEX_OP_ANDN), V(FUTEX_OP_XOR), {0, NULL} }; static const _stp_val_array _stp_futex_wake_cmps_list[] = { V(FUTEX_OP_CMP_EQ), V(FUTEX_OP_CMP_NE), V(FUTEX_OP_CMP_LT), V(FUTEX_OP_CMP_LE), V(FUTEX_OP_CMP_GT), V(FUTEX_OP_CMP_GE), {0, NULL} }; %} function _futex_op_str:string(op:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_futex_op_list, (unsigned int)STAP_ARG_op, STAP_RETVALUE, MAXSTRINGLEN); %} function _futex_wake_op_str:string(encoded_op:long) %{ /* pure */ /* unprivileged */ int encoded_op = (int)STAP_ARG_encoded_op; int op = (encoded_op >> 28) & 7; int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; int slen; strlcpy(STAP_RETVALUE, "{", MAXSTRINGLEN); slen = strlen(STAP_RETVALUE); if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) { strlcat(STAP_RETVALUE + slen, "FUTEX_OP_OPARG_SHIFT|", MAXSTRINGLEN - slen); slen = strlen(STAP_RETVALUE); } _stp_lookup_str(_stp_futex_wake_ops_list, op, STAP_RETVALUE + slen, MAXSTRINGLEN - slen); slen = strlen(STAP_RETVALUE); _stp_snprintf(STAP_RETVALUE + slen, MAXSTRINGLEN - slen, ", %d, ", oparg); slen = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_futex_wake_cmps_list, cmp, STAP_RETVALUE + slen, MAXSTRINGLEN - slen); slen = strlen(STAP_RETVALUE); _stp_snprintf(STAP_RETVALUE + slen, MAXSTRINGLEN - slen, ", %d}", cmparg); %} %{ static const _stp_val_array _stp_mountflags_list[] = { V(MS_RDONLY), V(MS_NOSUID), V(MS_NODEV), V(MS_NOEXEC), V(MS_SYNCHRONOUS), V(MS_REMOUNT), V(MS_MANDLOCK), V(MS_DIRSYNC), V(MS_NOATIME), V(MS_NODIRATIME), V(MS_BIND), V(MS_MOVE), V(MS_REC), /* MS_SILENT replaced MS_VERBOSE */ #ifdef MS_SILENT V(MS_SILENT), #else V(MS_VERBOSE), #endif V(MS_POSIXACL), V(MS_UNBINDABLE), V(MS_PRIVATE), V(MS_SLAVE), V(MS_SHARED), #ifdef MS_RELATIME V(MS_RELATIME), #endif #ifdef MS_KERNMOUNT V(MS_KERNMOUNT), #endif #ifdef MS_I_VERSION V(MS_I_VERSION), #endif #ifdef MS_STRICTATIME V(MS_STRICTATIME), #endif {0, NULL} }; static const _stp_val_array _stp_umountflags_list[] = { V(MNT_FORCE), V(MNT_DETACH), V(MNT_EXPIRE), #ifdef UMOUNT_NOFOLLOW V(UMOUNT_NOFOLLOW), #endif {0, NULL} }; %} function _mountflags_str:string(op:long) %{ /* pure */ /* unprivileged */ _stp_lookup_or_str(_stp_mountflags_list, (unsigned long)STAP_ARG_op, STAP_RETVALUE, MAXSTRINGLEN); %} function _umountflags_str:string(op:long) %{ /* pure */ /* unprivileged */ _stp_lookup_or_str(_stp_umountflags_list, (unsigned int)STAP_ARG_op, STAP_RETVALUE, MAXSTRINGLEN); %} %(systemtap_v <= "2.7" %? // This function is unused, so deprecate it. function _statfs_f_type_str(f) { if(f==0xadf5) return "ADFS_SUPER_MAGIC" if(f==0xADFF) return "AFFS_SUPER_MAGIC" if(f==0x42465331) return "BEFS_SUPER_MAGIC" if(f==0x1BADFACE) return "BFS_MAGIC" if(f==0xFF534D42) return "CIFS_MAGIC_NUMBER" if(f==0x73757245) return "CODA_SUPER_MAGIC" if(f==0x012FF7B7) return "COH_SUPER_MAGIC" if(f==0x28cd3d45) return "CRAMFS_MAGIC" if(f==0x1373) return "DEVFS_SUPER_MAGIC" if(f==0x00414A53) return "EFS_SUPER_MAGIC" if(f==0x137D) return "EXT_SUPER_MAGIC" if(f==0xEF51) return "EXT2_OLD_SUPER_MAGIC" if(f==0xEF53) return "EXT2_SUPER_MAGIC" if(f==0xEF53) return "EXT3_SUPER_MAGIC" if(f==0x4244) return "HFS_SUPER_MAGIC" if(f==0xF995E849) return "HPFS_SUPER_MAGIC" if(f==0x958458f6) return "HUGETLBFS_MAGIC" if(f==0x9660) return "ISOFS_SUPER_MAGIC" if(f==0x72b6) return "JFFS2_SUPER_MAGIC" if(f==0x3153464a) return "JFS_SUPER_MAGIC" if(f==0x137F) return "MINIX_SUPER_MAGIC" if(f==0x138F) return "MINIX_SUPER_MAGIC2" if(f==0x2468) return "MINIX2_SUPER_MAGIC" if(f==0x2478) return "MINIX2_SUPER_MAGIC2" if(f==0x4d44) return "MSDOS_SUPER_MAGIC" if(f==0x564c) return "NCP_SUPER_MAGIC" if(f==0x6969) return "NFS_SUPER_MAGIC" if(f==0x5346544e) return "NTFS_SB_MAGIC" if(f==0x9fa1) return "OPENPROM_SUPER_MAGIC" if(f==0x9fa0) return "PROC_SUPER_MAGIC" if(f==0x002f) return "QNX4_SUPER_MAGIC" if(f==0x52654973) return "REISERFS_SUPER_MAGIC" if(f==0x7275) return "ROMFS_MAGIC" if(f==0x517B) return "SMB_SUPER_MAGIC" if(f==0x012FF7B6) return "SYSV2_SUPER_MAGIC" if(f==0x012FF7B5) return "SYSV4_SUPER_MAGIC" if(f==0x01021994) return "TMPFS_MAGIC" if(f==0x15013346) return "UDF_SUPER_MAGIC" if(f==0x00011954) return "UFS_MAGIC" if(f==0x9fa2) return "USBDEVICE_SUPER_MAGIC" if(f==0xa501FCF5) return "VXFS_SUPER_MAGIC" if(f==0x012FF7B4) return "XENIX_SUPER_MAGIC" if(f==0x58465342) return "XFS_SUPER_MAGIC" if(f==0x012FD16D) return "_XIAFS_SUPER_MAGIC" return sprintf("UNKNOWN VALUE: %d", f) } %) %{ #include <linux/mman.h> static const _stp_val_array _stp_mremap_flags_list[] = { V(MREMAP_MAYMOVE), V(MREMAP_FIXED), {0, NULL} }; %} function _mremap_flags:string(flags:long) %{ /* pure */ /* unprivileged */ _stp_lookup_or_str(_stp_mremap_flags_list, (uint32_t)STAP_ARG_flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/mman.h> static const _stp_val_array _stp_madvice_advice_list[] = { V(MADV_NORMAL), V(MADV_RANDOM), V(MADV_SEQUENTIAL), V(MADV_WILLNEED), V(MADV_DONTNEED), #ifdef MADV_FREE V(MADV_FREE), #endif V(MADV_REMOVE), V(MADV_DONTFORK), V(MADV_DOFORK), #ifdef MADV_HWPOISON V(MADV_HWPOISON), #endif #ifdef MADV_SOFT_OFFLINE V(MADV_SOFT_OFFLINE), #endif #ifdef MADV_MERGEABLE V(MADV_MERGEABLE), #endif #ifdef MADV_UNMERGEABLE V(MADV_UNMERGEABLE), #endif #ifdef MADV_HUGEPAGE V(MADV_HUGEPAGE), #endif #ifdef MADV_NOHUGEPAGE V(MADV_NOHUGEPAGE), #endif #ifdef MADV_DONTDUMP V(MADV_DONTDUMP), #endif #ifdef MADV_DODUMP V(MADV_DODUMP), #endif {0, NULL} }; %} function _madvice_advice_str:string(behavior:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_madvice_advice_list, (unsigned int)STAP_ARG_behavior, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/fadvise.h> static const _stp_val_array _stp_fadvice_advice_list[] = { V(POSIX_FADV_NORMAL), V(POSIX_FADV_RANDOM), V(POSIX_FADV_SEQUENTIAL), V(POSIX_FADV_WILLNEED), V(POSIX_FADV_DONTNEED), V(POSIX_FADV_NOREUSE), #if defined(__s390x__) /* On s390x, 64-bit exes and 32-bit exes have different * versions of the following values. */ {4, "POSIX_FADV_DONTNEED"}, {5, "POSIX_FADV_NOREUSE"}, #endif {0, NULL} }; %} function _fadvice_advice_str:string(behavior:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_fadvice_advice_list, (unsigned int)STAP_ARG_behavior, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/fcntl.h> static const _stp_val_array _stp_fcntl_cmd_list[] = { V(F_DUPFD), V(F_GETFD), V(F_SETFD), V(F_GETFL), V(F_SETFL), V(F_GETLK), V(F_SETLK), V(F_SETLKW), V(F_SETOWN), V(F_GETOWN), V(F_SETSIG), V(F_GETSIG), #ifdef F_GETLK64 V(F_GETLK64), #endif #ifdef F_SETLK64 V(F_SETLK64), #endif #ifdef F_SETLKW64 V(F_SETLKW64), #endif #ifdef F_SETOWN_EX V(F_SETOWN_EX), #endif #ifdef F_GETOWN_EX V(F_GETOWN_EX), #endif #ifdef F_GETOWNER_UIDS V(F_GETOWNER_UIDS), #endif #ifdef F_SETLEASE V(F_SETLEASE), #endif #ifdef F_GETLEASE V(F_GETLEASE), #endif #ifdef F_DUPFD_CLOEXEC V(F_DUPFD_CLOEXEC), #endif #ifdef F_NOTIFY V(F_NOTIFY), #endif #ifdef F_SETPIPE_SZ V(F_SETPIPE_SZ), #endif #ifdef F_GETPIPE_SZ V(F_GETPIPE_SZ), #endif {0, NULL} }; %} function _fcntl_cmd_str:string(cmd:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_fcntl_cmd_list, (unsigned int)STAP_ARG_cmd, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/fs.h> #ifndef SEEK_SET #define SEEK_SET 0 #endif #ifndef SEEK_CUR #define SEEK_CUR 1 #endif #ifndef SEEK_END #define SEEK_END 2 #endif #ifndef SEEK_DATA #define SEEK_DATA 3 #endif #ifndef SEEK_HOLE #define SEEK_HOLE 4 #endif static const _stp_val_array _stp_seek_whence_list[] = { V(SEEK_SET), V(SEEK_CUR), V(SEEK_END), V(SEEK_DATA), V(SEEK_HOLE), {0, NULL} }; %} function _seek_whence_str:string(w:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_seek_whence_list, (unsigned int)STAP_ARG_w, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/quota.h> static const _stp_val_array _stp_quotactl_cmd_list[] = { V(Q_SYNC), V(Q_QUOTAON), V(Q_QUOTAOFF), V(Q_GETFMT), V(Q_GETINFO), V(Q_SETINFO), V(Q_GETQUOTA), V(Q_SETQUOTA), /* XFS Quota Manager (XQM) Codes */ V(Q_XQUOTAON), V(Q_XQUOTAOFF), V(Q_XGETQUOTA), V(Q_XSETQLIM), V(Q_XGETQSTAT), V(Q_XQUOTARM), V(Q_XQUOTASYNC), #ifdef Q_XGETQSTATV V(Q_XGETQSTATV), #endif {0, NULL} }; %} function _quotactl_cmd_str:string(cmd:long) %{ /* pure */ /* unprivileged */ unsigned int cmd = (unsigned int)STAP_ARG_cmd >> SUBCMDSHIFT; unsigned int type = (unsigned int)STAP_ARG_cmd & SUBCMDMASK; _stp_lookup_str(_stp_quotactl_cmd_list, cmd, STAP_RETVALUE, MAXSTRINGLEN); if (type == USRQUOTA) strlcat(STAP_RETVALUE, "|USRQUOTA", MAXSTRINGLEN); else if (type == GRPQUOTA) strlcat(STAP_RETVALUE, "|GRPQUOTA", MAXSTRINGLEN); else { int len = strlen(STAP_RETVALUE); _stp_snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, "|0x%x", type); } %} function _quotactl_subcmd:long(cmd:long) %{ /* pure */ /* unprivileged */ STAP_RETVALUE = (unsigned int)STAP_ARG_cmd >> SUBCMDSHIFT; %} %{ static const _stp_val_array _stp_quotactl_format_list[] = { V(QFMT_VFS_OLD), #ifdef QFMT_VFS_V0 V(QFMT_VFS_V0), #endif #ifdef QFMT_OCFS2 V(QFMT_OCFS2), #endif #ifdef QFMT_VFS_V1 V(QFMT_VFS_V1), #endif {0, NULL} }; %} function _quotactl_quota_type_str:string(fmt:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_quotactl_format_list, (int)STAP_ARG_fmt, STAP_RETVALUE, MAXSTRINGLEN); %} function _struct_dqblk_u:string(uaddr:long) %{ /* pure */ struct if_dqblk dqb; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char*)&dqb, ptr, sizeof(struct if_dqblk)) == 0) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{dqb_bhardlimit=%llu, dqb_bsoftlimit=%llu, dqb_curspace=%llu, dqb_ihardlimit=%llu, dqb_isoftlimit=%llu, ...}", (unsigned long long)dqb.dqb_bhardlimit, (unsigned long long)dqb.dqb_bsoftlimit, (unsigned long long)dqb.dqb_curspace, (unsigned long long)dqb.dqb_ihardlimit, (unsigned long long)dqb.dqb_isoftlimit); } else { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); } } %} function _struct_dqinfo_u:string(uaddr:long) %{ /* pure */ struct if_dqinfo dqi; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char*)&dqi, ptr, sizeof(struct if_dqinfo)) == 0) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{dqi_bgrace=%llu, dqi_igrace=%llu, dqi_flags=%d, dqi_valid=%d}", (unsigned long long)dqi.dqi_bgrace, (unsigned long long)dqi.dqi_igrace, dqi.dqi_flags, dqi.dqi_valid); } else { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); } } %} %{ #include <linux/socket.h> static const _stp_val_array _stp_sockopt_optname_list[] = { V(SO_DEBUG), V(SO_REUSEADDR), V(SO_TYPE), V(SO_ERROR), V(SO_DONTROUTE), V(SO_BROADCAST), V(SO_SNDBUF), V(SO_RCVBUF), V(SO_SNDBUFFORCE), V(SO_RCVBUFFORCE), V(SO_KEEPALIVE), V(SO_OOBINLINE), V(SO_NO_CHECK), V(SO_PRIORITY), V(SO_LINGER), V(SO_BSDCOMPAT), #ifdef SO_REUSEPORT V(SO_REUSEPORT), #endif V(SO_PASSCRED), V(SO_PEERCRED), V(SO_RCVLOWAT), V(SO_SNDLOWAT), V(SO_RCVTIMEO), V(SO_SNDTIMEO), V(SO_SECURITY_AUTHENTICATION), V(SO_SECURITY_ENCRYPTION_TRANSPORT), V(SO_SECURITY_ENCRYPTION_NETWORK), V(SO_BINDTODEVICE), V(SO_ATTACH_FILTER), V(SO_DETACH_FILTER), V(SO_PEERNAME), V(SO_TIMESTAMP), V(SO_ACCEPTCONN), V(SO_PEERSEC), V(SO_PASSSEC), #ifdef SO_TIMESTAMPNS V(SO_TIMESTAMPNS), #endif #ifdef SO_MARK V(SO_MARK), #endif #ifdef SO_TIMESTAMPING V(SO_TIMESTAMPING), #endif #ifdef SO_PROTOCOL V(SO_PROTOCOL), #endif #ifdef SO_DOMAIN V(SO_DOMAIN), #endif #ifdef SO_RXQ_OVFL V(SO_RXQ_OVFL), #endif #ifdef SO_WIFI_STATUS V(SO_WIFI_STATUS), #endif #ifdef SO_PEEK_OFF V(SO_PEEK_OFF), #endif #ifdef SO_NOFCS V(SO_NOFCS), #endif #ifdef SO_LOCK_FILTER V(SO_LOCK_FILTER), #endif #ifdef SO_SELECT_ERR_QUEUE V(SO_SELECT_ERR_QUEUE), #endif #ifdef SO_BUSY_POLL V(SO_BUSY_POLL), #endif #ifdef SO_MAX_PACING_RATE V(SO_MAX_PACING_RATE), #endif #ifdef SO_BPF_EXTENSIONS V(SO_BPF_EXTENSIONS), #endif {0, NULL} }; %} /* see sys/socket.h (for setsockopt) */ function _sockopt_optname_str:string(opt:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_sockopt_optname_list, STAP_ARG_opt, STAP_RETVALUE, MAXSTRINGLEN); %} %{ static const _stp_val_array _stp_sockopt_level_list[] = { V(SOL_IP), V(SOL_SOCKET), V(SOL_TCP), V(SOL_UDP), V(SOL_IPV6), V(SOL_ICMPV6), V(SOL_SCTP), #ifdef SOL_UDPLITE V(SOL_UDPLITE), #endif V(SOL_RAW), V(SOL_IPX), V(SOL_AX25), V(SOL_ATALK), V(SOL_NETROM), V(SOL_ROSE), V(SOL_DECNET), #ifdef SOL_X25 V(SOL_X25), #endif V(SOL_PACKET), V(SOL_ATM), V(SOL_AAL), V(SOL_IRDA), V(SOL_NETBEUI), V(SOL_LLC), V(SOL_DCCP), V(SOL_NETLINK), V(SOL_TIPC), #ifdef SOL_RXRPC V(SOL_RXRPC), #endif #ifdef SOL_PPPOL2TP V(SOL_PPPOL2TP), #endif #ifdef SOL_BLUETOOTH V(SOL_BLUETOOTH), #endif #ifdef SOL_PNPIPE V(SOL_PNPIPE), #endif #ifdef SOL_RDS V(SOL_RDS), #endif V(SOL_IUCV), #ifdef SOL_CAIF V(SOL_CAIF), #endif #ifdef SOL_ALG V(SOL_ALG), #endif #ifdef SOL_NFC V(SOL_NFC), #endif {0, NULL} }; %} /* `man 2 setsockopt` for more information */ function _sockopt_level_str:string(level:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_sockopt_level_list, STAP_ARG_level, STAP_RETVALUE, MAXSTRINGLEN); %} %{ static const _stp_val_array _stp_sock_family_list[] = { V(PF_UNSPEC), V(PF_LOCAL), /* same thing as PF_UNIX */ V(PF_INET), V(PF_AX25), V(PF_IPX), V(PF_APPLETALK), V(PF_NETROM), V(PF_BRIDGE), V(PF_ATMPVC), V(PF_X25), V(PF_INET6), V(PF_ROSE), V(PF_DECnet), V(PF_NETBEUI), V(PF_SECURITY), V(PF_KEY), V(PF_NETLINK), V(PF_ROUTE), V(PF_PACKET), V(PF_ASH), V(PF_ECONET), V(PF_ATMSVC), #ifdef PF_RDS V(PF_RDS), #endif V(PF_SNA), V(PF_IRDA), V(PF_PPPOX), V(PF_WANPIPE), V(PF_LLC), #ifdef PF_IB V(PF_IB), #endif #ifdef PF_CAN V(PF_CAN), #endif V(PF_TIPC), V(PF_BLUETOOTH), V(PF_IUCV), #ifdef PF_RXRPC V(PF_RXRPC), #endif #ifdef PF_ISDN V(PF_ISDN), #endif #ifdef PF_PHONET V(PF_PHONET), #endif #ifdef PF_IEEE802154 V(PF_IEEE802154), #endif #ifdef PF_CAIF V(PF_CAIF), #endif #ifdef PF_ALG V(PF_ALG), #endif #ifdef PF_NFC V(PF_NFC), #endif #ifdef PF_VSOCK V(PF_VSOCK), #endif {0, NULL} }; %} function _sock_family_str:string(f:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_sock_family_list, (unsigned int)STAP_ARG_f, STAP_RETVALUE, MAXSTRINGLEN); %} function _sock_type_str:string(type:long) %{ /* pure */ /* unprivileged */ #ifdef SOCK_TYPE_MASK int flags = (int)STAP_ARG_type & ~SOCK_TYPE_MASK; int t = (int)STAP_ARG_type & SOCK_TYPE_MASK; #else int t = (int)STAP_ARG_type; #endif int data_added = 0; /* * This is a bit tricky. We've got 2 types of information * here. A socket type and a possible combination of socket * flags. In addition, we only want one final listing of * any unknown bits set. * * We can't call _stp_lookup_str() here since it would go * ahead and display any unknown type value, and we want to * wait until after any possible flags are displayed. */ switch (t) { case SOCK_STREAM: strlcpy (STAP_RETVALUE, "SOCK_STREAM", MAXSTRINGLEN); t = 0; data_added = 1; break; case SOCK_DGRAM: strlcpy (STAP_RETVALUE, "SOCK_DGRAM", MAXSTRINGLEN); t = 0; data_added = 1; break; case SOCK_RAW: strlcpy (STAP_RETVALUE, "SOCK_RAW", MAXSTRINGLEN); t = 0; data_added = 1; break; case SOCK_RDM: strlcpy (STAP_RETVALUE, "SOCK_RDM", MAXSTRINGLEN); t = 0; data_added = 1; break; case SOCK_SEQPACKET: strlcpy (STAP_RETVALUE, "SOCK_SEQPACKET", MAXSTRINGLEN); t = 0; data_added = 1; break; #ifdef SOL_DCCP case SOCK_DCCP: strlcpy (STAP_RETVALUE, "SOCK_DCCP", MAXSTRINGLEN); t = 0; data_added = 1; break; #endif case SOCK_PACKET: strlcpy (STAP_RETVALUE, "SOCK_PACKET", MAXSTRINGLEN); t = 0; data_added = 1; break; } #ifdef SOCK_TYPE_MASK /* We can't use _stp_lookup_or_str() here since if none of * these flags are set it would put a "0x0" on the end, which * we don't want to add to the socket type. */ if (flags & SOCK_CLOEXEC) { if (data_added) strlcat(STAP_RETVALUE, "|", MAXSTRINGLEN); strlcat (STAP_RETVALUE, "SOCK_CLOEXEC", MAXSTRINGLEN); flags &= ~SOCK_CLOEXEC; data_added = 1; } if (flags & SOCK_NONBLOCK) { if (data_added) strlcat(STAP_RETVALUE, "|", MAXSTRINGLEN); strlcat (STAP_RETVALUE, "SOCK_NONBLOCK", MAXSTRINGLEN); flags &= ~SOCK_NONBLOCK; data_added = 1; } /* If we have any leftover flags bits, add them back to the * type bits to get displayed together. */ t |= flags; #endif /* Display any leftover bits. */ if (t != 0 || !data_added) { int slen; if (data_added) strlcat(STAP_RETVALUE, "|", MAXSTRINGLEN); slen = strlen(STAP_RETVALUE); _stp_snprintf(STAP_RETVALUE + slen, MAXSTRINGLEN - slen, "0x%x", t); } %} %{ static const _stp_val_array _stp_sock_flags_list[] = { #ifdef SOCK_TYPE_MASK V(SOCK_CLOEXEC), V(SOCK_NONBLOCK), #endif {0, NULL} }; %} function _sock_flags_str:string(f:long) %{ /* pure */ /* unprivileged */ _stp_lookup_or_str(_stp_sock_flags_list, (unsigned int)STAP_ARG_f, STAP_RETVALUE, MAXSTRINGLEN); %} %{ // Be sure we have the IPPROTO_* defines. But, on some older kernels // we don't have all of them defined. Also note that on some older // kernels these values are enum values, not defines. But, the // following code should work anyway. #include <linux/in.h> #ifndef IPPROTO_TP #define IPPROTO_TP 29 #endif #ifndef IPPROTO_MTP #define IPPROTO_MTP 92 #endif #ifndef IPPROTO_ENCAP #define IPPROTO_ENCAP 98 #endif #ifndef IPPROTO_UDPLITE #define IPPROTO_UDPLITE 136 #endif %} function _sock_protocol_str:string(family:long, protocol:long) { if (family == @const("PF_INET") || family == @const("PF_INET6")) { if (protocol == @const("IPPROTO_IP")) return "IPPROTO_IP" if (protocol == @const("IPPROTO_ICMP")) return "IPPROTO_ICMP" if (protocol == @const("IPPROTO_IGMP")) return "IPPROTO_IGMP" if (protocol == @const("IPPROTO_IPIP")) return "IPPROTO_IPIP" if (protocol == @const("IPPROTO_TCP")) return "IPPROTO_TCP" if (protocol == @const("IPPROTO_EGP")) return "IPPROTO_EGP" if (protocol == @const("IPPROTO_PUP")) return "IPPROTO_PUP" if (protocol == @const("IPPROTO_UDP")) return "IPPROTO_UDP" if (protocol == @const("IPPROTO_IDP")) return "IPPROTO_IDP" if (protocol == @const("IPPROTO_TP")) return "IPPROTO_TP" if (protocol == @const("IPPROTO_DCCP")) return "IPPROTO_DCCP" if (protocol == @const("IPPROTO_IPV6")) return "IPPROTO_IPV6" if (protocol == @const("IPPROTO_RSVP")) return "IPPROTO_RSVP" if (protocol == @const("IPPROTO_GRE")) return "IPPROTO_GRE" if (protocol == @const("IPPROTO_ESP")) return "IPPROTO_ESP" if (protocol == @const("IPPROTO_AH")) return "IPPROTO_AH" if (protocol == @const("IPPROTO_MTP")) return "IPPROTO_MTP" if (protocol == @const("IPPROTO_ENCAP")) return "IPPROTO_ENCAP" if (protocol == @const("IPPROTO_PIM")) return "IPPROTO_PIM" if (protocol == @const("IPPROTO_COMP")) return "IPPROTO_COMP" if (protocol == @const("IPPROTO_SCTP")) return "IPPROTO_SCTP" if (protocol == @const("IPPROTO_UDPLITE")) return "IPPROTO_UDPLITE" if (protocol == @const("IPPROTO_RAW")) return "IPPROTO_RAW" } return sprintf("%d", protocol) } function _opoll_op_str:string(o:long) %{ /* pure */ /* unprivileged */ static const _stp_val_array opoll_op_list[] = { V(EPOLL_CTL_ADD), V(EPOLL_CTL_MOD), V(EPOLL_CTL_DEL), {0, NULL} }; _stp_lookup_str(opoll_op_list, (unsigned int)STAP_ARG_o, STAP_RETVALUE, MAXSTRINGLEN); %} %(systemtap_v <= "2.7" %? // This function isn't actually used anywhere, so let's deprecate it. function _epoll_events_str(e) { if(e==1) return "EPOLLIN" if(e==4) return "EPOLLOUT" if(e==2) return "EPOLLPRI" if(e==8) return "EPOLLERR" if(e==16) return "EPOLLHUP" if(e==-2147483648) return "EPOLLET" if(e==1073741824) return "EPOLLONESHOT" return sprintf("UNKNOWN VALUE: %d", e) } %) %{ #include <linux/resource.h> static const _stp_val_array _stp_rlimit_resource_list[] = { { (unsigned int)RLIM_INFINITY, "RLIM_INFINITY"}, V(RLIMIT_CPU), V(RLIMIT_FSIZE), V(RLIMIT_DATA), V(RLIMIT_STACK), V(RLIMIT_CORE), V(RLIMIT_RSS), V(RLIMIT_NPROC), V(RLIMIT_NOFILE), V(RLIMIT_MEMLOCK), V(RLIMIT_AS), V(RLIMIT_LOCKS), V(RLIMIT_SIGPENDING), V(RLIMIT_MSGQUEUE), V(RLIMIT_NICE), V(RLIMIT_RTPRIO), #ifdef RLIMIT_RTTIME V(RLIMIT_RTTIME), #endif V(RLIM_NLIMITS), {0, NULL} }; static const _stp_val_array _stp_rusage_who_list[] = { V(RUSAGE_SELF), {(unsigned int)RUSAGE_CHILDREN, "RUSAGE_CHILDREN"}, {(unsigned int)RUSAGE_BOTH, "RUSAGE_BOTH"}, V(RUSAGE_THREAD), {0, NULL} }; %} function _rlimit_resource_str:string(r:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_rlimit_resource_list, (unsigned int)STAP_ARG_r, STAP_RETVALUE, MAXSTRINGLEN); %} function _rusage_who_str:string(w:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_rusage_who_list, (unsigned int)STAP_ARG_w, STAP_RETVALUE, MAXSTRINGLEN); %} /* for accessing 16-bit values encoded in a long */ function __short:long(val:long) %{ /* pure */ /* unprivileged */ STAP_RETVALUE = (short)STAP_ARG_val; %} function __ushort:long(val:long) %{ /* pure */ /* unprivileged */ STAP_RETVALUE = (unsigned short)STAP_ARG_val; %} /* uid_t is unsigned, but calling functions take "-1" as a parameter */ /* so this hack is necessary to correct that mismatch. */ function __int32:long(val:long) %{ /* pure */ /* unprivileged */ STAP_RETVALUE = (int32_t)STAP_ARG_val; %} function __uint32:long(val:long) %{ /* pure */ /* unprivileged */ STAP_RETVALUE = (uint32_t)STAP_ARG_val; %} /* Unsigned values can get get sign-extended and become negative. */ function __ulong:long(val:long) %{ /* pure */ /* unprivileged */ STAP_RETVALUE = (unsigned long)STAP_ARG_val; %} function __long:long(val:long) %{ /* pure */ /* unprivileged */ STAP_RETVALUE = (long)STAP_ARG_val; %} # For utimensat and futimesat, the directory fd can have a special value function _dfd_str:string(d:long) { if (d == @const("AT_FDCWD")) return "AT_FDCWD" return sprint(d) } %{ static const _stp_val_array _stp_adjtimex_return_str_list[] = { V(TIME_OK), V(TIME_INS), V(TIME_DEL), V(TIME_OOP), V(TIME_WAIT), V(TIME_ERROR), V(TIME_BAD), {0, NULL} }; %} function _adjtimex_return_str:string(ret:long) %{ /* pure */ /* unprivileged */ int len; snprintf (STAP_RETVALUE, MAXSTRINGLEN, "%d (", (int)STAP_ARG_ret); len = strlen(STAP_RETVALUE); _stp_lookup_str2(_stp_adjtimex_return_str_list, (int)STAP_ARG_ret, STAP_RETVALUE + len, MAXSTRINGLEN - len, 10); strlcat (STAP_RETVALUE, ")", MAXSTRINGLEN); %} %{ static const _stp_val_array _stp_signal_list[] = { {0, "SIG_0"}, V(SIGHUP), V(SIGINT), V(SIGQUIT), V(SIGILL), V(SIGTRAP), V(SIGABRT), V(SIGBUS), V(SIGFPE), V(SIGKILL), V(SIGUSR1), V(SIGSEGV), V(SIGPIPE), V(SIGUSR2), V(SIGALRM), V(SIGTERM), V(SIGCHLD), V(SIGCONT), V(SIGSTOP), V(SIGTSTP), V(SIGTTIN), V(SIGTTOU), V(SIGURG), #ifdef SIGXCPU V(SIGXCPU), #endif #ifdef SIGXFSZ V(SIGXFSZ), #endif V(SIGVTALRM), V(SIGPROF), V(SIGWINCH), {SIGIO,"SIGIO/SIGPOLL"}, V(SIGPWR), #ifdef SIGSYS V(SIGSYS), #endif {SIGTRAP|0x80,"TRACESYSGOOD"}, {0, NULL} }; static void _stp_sigset_str(sigset_t *mask, char *ptr, int len) { const _stp_val_array * const array = _stp_signal_list; int i = 0, flag = 0; while (array[i].name) { if (array[i].val > 0 && array[i].val <= _NSIG && sigismember(mask, array[i].val)) { if (flag) strlcat(ptr, "|", len); else strlcat(ptr, "[", len); strlcat(ptr, array[i].name, len); flag = 1; } i++; } if (flag == 0) strlcat(ptr, "[EMPTY]", len); else strlcat(ptr, "]", len); } %} function _signal_name:string(sig:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_signal_list, (unsigned int)STAP_ARG_sig, STAP_RETVALUE, MAXSTRINGLEN); %} %{ static const _stp_val_array _stp_semctl_list[] = { V(IPC_INFO), V(SEM_INFO), V(SEM_STAT), V(GETALL), V(GETVAL), V(GETPID), V(GETNCNT), V(GETZCNT), V(IPC_STAT), V(SETVAL), V(SETALL), V(IPC_RMID), V(IPC_SET), {0, NULL} }; %} function _semctl_cmd:string(cmd:long) %{ /* pure */ /* unprivileged */ unsigned int cmd = STAP_ARG_cmd; int len; #ifdef IPC_64 if (cmd & IPC_64) { strlcpy(STAP_RETVALUE, "IPC_64|", MAXSTRINGLEN); cmd &= ~IPC_64; } #endif len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_semctl_list, cmd, STAP_RETVALUE + len, MAXSTRINGLEN - len); %} function _stp_sigset_u:string(setptr:long) %{ /* pure */ char *ptr = (char *)(uintptr_t)STAP_ARG_setptr; sigset_t set; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char*)&set,ptr,sizeof(sigset_t)) == 0) _stp_sigset_str(&set, STAP_RETVALUE, MAXSTRINGLEN); else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); } %} function _stp_compat_sigset_u:string(setptr:long) %{ /* pure */ #ifdef CONFIG_COMPAT char *ptr = (char *)(uintptr_t)STAP_ARG_setptr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { compat_sigset_t set; if (_stp_copy_from_user((char*)&set, ptr, sizeof(compat_sigset_t)) == 0) { sigset_t new_set; sigset_from_compat(&new_set, &set); _stp_sigset_str(&new_set, STAP_RETVALUE, MAXSTRINGLEN); } else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); } #endif %} %{ static const _stp_val_array _stp_fork_list[] = { V(CLONE_VM), V(CLONE_FS), V(CLONE_FILES), V(CLONE_SIGHAND), V(CLONE_PTRACE), V(CLONE_VFORK), V(CLONE_PARENT), V(CLONE_THREAD), V(CLONE_NEWNS), V(CLONE_SYSVSEM), V(CLONE_SETTLS), V(CLONE_PARENT_SETTID), V(CLONE_CHILD_CLEARTID), V(CLONE_DETACHED), V(CLONE_UNTRACED), V(CLONE_CHILD_SETTID), #ifdef CLONE_STOPPED V(CLONE_STOPPED), #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) V(CLONE_NEWUTS), V(CLONE_NEWIPC), #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) V(CLONE_NEWUSER), #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) V(CLONE_NEWPID), V(CLONE_NEWNET), #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) V(CLONE_IO), #endif {0, NULL} }; %} function __fork_flags:string(flags:long) %{ /* pure */ /* unprivileged */ _stp_lookup_or_str(_stp_fork_list, STAP_ARG_flags & ~0xff, STAP_RETVALUE, MAXSTRINGLEN); if ( STAP_ARG_flags & 0xff ) { /* flags contains the termination signal */ if (*STAP_RETVALUE) strlcat(STAP_RETVALUE, "|", MAXSTRINGLEN); _stp_lookup_str(_stp_signal_list, STAP_ARG_flags & 0xff, STAP_RETVALUE, MAXSTRINGLEN); } %} %{ static const _stp_val_array _stp_atflag_list[] = { #ifdef AT_SYMLINK_NOFOLLOW V(AT_SYMLINK_NOFOLLOW), #endif #ifdef AT_REMOVEDIR V(AT_REMOVEDIR), #endif #ifdef AT_SYMLINK_FOLLOW V(AT_SYMLINK_FOLLOW), #endif #ifdef AT_NO_AUTOMOUNT V(AT_NO_AUTOMOUNT), #endif #ifdef AT_EMPTY_PATH V(AT_EMPTY_PATH), #endif {0, NULL} }; %} function _at_flag_str:string(f:long) %{ /* pure */ /* unprivileged */ _stp_lookup_or_str(_stp_atflag_list, STAP_ARG_f, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/eventpoll.h> %} function _epoll_create1_flag_str:string(f:long) %{ /* pure */ /* unprivileged */ static const _stp_val_array epoll_create1_flags_list[] = { #ifdef EPOLL_CLOEXEC V(EPOLL_CLOEXEC), #endif {0, NULL} }; _stp_lookup_or_str(epoll_create1_flags_list, (unsigned int)STAP_ARG_f, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) #include <linux/eventfd.h> #endif static const _stp_val_array _stp_eventfd2_flag_list[] = { #ifdef EFD_NONBLOCK V(EFD_NONBLOCK), #endif #ifdef EFD_CLOEXEC V(EFD_CLOEXEC), #endif #ifdef EFD_SEMAPHORE V(EFD_SEMAPHORE), #endif {0, NULL} }; %} function _eventfd2_flag_str:string(flags:long) %{ /* pure */ /* unprivileged */ uint32_t flags = (uint32_t)STAP_ARG_flags; _stp_lookup_or_str(_stp_eventfd2_flag_list, flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) #include <linux/signalfd.h> #endif static const _stp_val_array _stp_signalfd4_flags_list[] = { #ifdef SFD_NONBLOCK V(SFD_NONBLOCK), #endif #ifdef SFD_CLOEXEC V(SFD_CLOEXEC), #endif {0, NULL} }; %} function _signalfd4_flags_str:string(f:long) %{ /* pure */ /* unprivileged */ uint32_t flags = (uint32_t)STAP_ARG_f; _stp_lookup_or_str(_stp_signalfd4_flags_list, flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #if (defined(CONFIG_INOTIFY) || defined(CONFIG_INOTIFY_USER)) #include <linux/inotify.h> #endif static const _stp_val_array _stp_inotify_init1_flag_list[] = { #if defined(IN_NONBLOCK) V(IN_NONBLOCK), #endif #if defined(IN_CLOEXEC) V(IN_CLOEXEC), #endif {0, NULL} }; %} function _inotify_init1_flag_str:string(f:long) %{ /* pure */ /* unprivileged */ unsigned int flags = (unsigned int)STAP_ARG_f; _stp_lookup_or_str(_stp_inotify_init1_flag_list, flags, STAP_RETVALUE, MAXSTRINGLEN); %} function _dup3_flag_str:string(f:long) %{ /* pure */ /* unprivileged */ unsigned int flags = (unsigned int)STAP_ARG_f; _stp_lookup_or_str(_stp_open_mode_flags_list, flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/shm.h> static const _stp_val_array _stp_shmat_list[] = { V(SHM_RDONLY), V(SHM_RND), V(SHM_REMAP), V(SHM_EXEC), {0, NULL} }; %} function _shmat_flags_str:string(f:long) %{ /* pure */ /* unprivileged */ _stp_lookup_or_str(_stp_shmat_list, STAP_ARG_f, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/mman.h> static const _stp_val_array _stp_mprotect_list[] = { {0, "PROT_NONE"}, V(PROT_READ), V(PROT_WRITE), V(PROT_EXEC), V(PROT_SEM), V(PROT_GROWSDOWN), V(PROT_GROWSUP), #ifdef PROT_SAO // powerpc only V(PROT_SAO), #endif {0, NULL} }; %} function _mprotect_prot_str:string(prot:long) %{ /* pure */ /* unprivileged */ _stp_lookup_or_str(_stp_mprotect_list, STAP_ARG_prot, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/mman.h> static const _stp_val_array _stp_mmap_list[] = { V(MAP_SHARED), V(MAP_PRIVATE), V(MAP_FIXED), V(MAP_ANONYMOUS), V(MAP_GROWSDOWN), V(MAP_DENYWRITE), V(MAP_EXECUTABLE), V(MAP_LOCKED), V(MAP_NORESERVE), V(MAP_POPULATE), V(MAP_NONBLOCK), #ifdef MAP_STACK V(MAP_STACK), #endif #ifdef MAP_HUGETLB V(MAP_HUGETLB), #endif #ifdef MAP_UNINITIALIZED V(MAP_UNINITIALIZED), #endif #ifdef MAP_32BIT // x86 only V(MAP_32BIT), #endif {0, NULL} }; %} function _mmap_flags:string(flags:long) %{ /* pure */ /* unprivileged */ #ifdef MAP_HUGE_SHIFT // Extract the huge page size for special treatment. u8 huge = (STAP_ARG_flags >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK; STAP_ARG_flags &= ~((long)MAP_HUGE_MASK << MAP_HUGE_SHIFT); if (huge) { // MAP_HUGE_2MB and MAP_HUGE_1GB are predefined on x86, but // the log2 value can be used to represent any power of two. const char* suffix = ""; if (huge >= 60) { huge -= 60; suffix = "EB"; } else if (huge >= 50) { huge -= 50; suffix = "PB"; } else if (huge >= 40) { huge -= 40; suffix = "TB"; } else if (huge >= 30) { huge -= 30; suffix = "GB"; } else if (huge >= 20) { huge -= 20; suffix = "MB"; } else if (huge >= 10) { huge -= 10; suffix = "KB"; } _stp_snprintf(STAP_RETVALUE, MAXSTRINGLEN, "MAP_HUGE_%ld%s|", 1L << huge, suffix); } #endif _stp_lookup_or_str(_stp_mmap_list, STAP_ARG_flags, STAP_RETVALUE, MAXSTRINGLEN); %} %( systemtap_v <= "3.0" %? # old mmap functions passed in a struct like this. # function get_mmap_args:string (args:long) %{ /* pure */ #if defined (__x86_64__) || defined (__ia64__) struct mmap_arg_struct { unsigned int addr; unsigned int len; unsigned int prot; unsigned int flags; int fd; unsigned int offset; } a; #else struct mmap_arg_struct { unsigned long addr; unsigned long len; unsigned long prot; unsigned long flags; long fd; unsigned long offset; } a; #endif if(_stp_copy_from_user((char *)&a,(char *)(uintptr_t)STAP_ARG_args, sizeof(a))== 0) { int len; _stp_snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx, %lu, ", (unsigned long)a.addr, (unsigned long)a.len); _stp_lookup_or_str(_stp_mprotect_list, a.prot, STAP_RETVALUE, MAXSTRINGLEN); strlcat (STAP_RETVALUE, ", ", MAXSTRINGLEN); _stp_lookup_or_str(_stp_mmap_list, a.flags, STAP_RETVALUE, MAXSTRINGLEN); strlcat (STAP_RETVALUE, ", ", MAXSTRINGLEN); len = strlen(STAP_RETVALUE); _stp_snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, "%ld, %ld", (long)a.fd, (long)a.offset); } else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)STAP_ARG_args); %} %) function _sighandler_str:string(uaddr:long) %{ /* pure */ /* unprivileged */ static const _stp_val_array _stp_sa_handler_list[] = { {0, "SIG_DFL"}, {1, "SIG_IGN"}, {0, NULL} }; _stp_lookup_str(_stp_sa_handler_list, (long)STAP_ARG_uaddr, STAP_RETVALUE, MAXSTRINGLEN); %} %{ static void _stp_sigaction_str(struct sigaction *act, char *ptr, int len) { static const _stp_val_array _stp_sa_handler_list[] = { {0, "SIG_DFL"}, {1, "SIG_IGN"}, {0, NULL} }; static const _stp_val_array _stp_sa_flags_list[] = { V(SA_NOCLDSTOP), V(SA_NOCLDWAIT), V(SA_RESETHAND), V(SA_ONSTACK), V(SA_RESTART), V(SA_NODEFER), V(SA_SIGINFO), #ifdef SA_RESTORER V(SA_RESTORER), #endif {0, NULL} }; int slen; _stp_lookup_str(_stp_sa_handler_list, (long)act->sa_handler, ptr, len); if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL) { strlcat (ptr, ", ", len); _stp_lookup_or_str(_stp_sa_flags_list, act->sa_flags, ptr, len); strlcat (ptr, ", ", len); #if !defined (__ia64__) && !defined (__mips__) slen = strlen(ptr); _stp_snprintf(ptr + slen, len - slen, "0x%lx, ", (long)act->sa_restorer); #endif _stp_sigset_str(&act->sa_mask, ptr, len); } } %} function _stp_sigmask_str:string(sigmask:long) %{ /* pure */ unsigned long mask = (unsigned long)STAP_ARG_sigmask; sigset_t set; siginitset(&set, mask); _stp_sigset_str(&set, STAP_RETVALUE, MAXSTRINGLEN); %} function _struct_sigaction_u:string(uaddr:long) %{ /* pure */ struct sigaction act; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char*)&act, ptr, sizeof(struct sigaction)) == 0) _stp_sigaction_str(&act, STAP_RETVALUE, MAXSTRINGLEN); else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); } %} function _struct_sigaction32_u:string(uaddr:long) %{ /* pure */ #ifdef CONFIG_COMPAT #include <linux/compat.h> #ifdef AUTOCONF_COMPAT_SIGACTION struct compat_sigaction act32; #else // There seems to be no public cross arch header that defines this. // For x86, you can find it in asm/ia32.h. For s390x, it is defined // in a private header. struct sigaction32 { compat_uptr_t sa_handler; unsigned int sa_flags; unsigned int sa_restorer; /* Another 32 bit pointer */ compat_sigset_t sa_mask; /* A 32 bit mask */ }; struct sigaction32 act32; #endif char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char*)&act32, ptr, sizeof(act32)) == 0) { struct sigaction act; act.sa_handler = (void *)compat_ptr(act32.sa_handler); act.sa_flags = (unsigned long)act32.sa_flags; #ifdef SA_RESTORER act.sa_restorer = (void *)compat_ptr(act32.sa_restorer); #endif /* swap words around to get right endian order. */ switch (_NSIG_WORDS) { case 4: act.sa_mask.sig[3] = act32.sa_mask.sig[6] | (((long)act32.sa_mask.sig[7]) << 32); case 3: act.sa_mask.sig[2] = act32.sa_mask.sig[4] | (((long)act32.sa_mask.sig[5]) << 32); case 2: act.sa_mask.sig[1] = act32.sa_mask.sig[2] | (((long)act32.sa_mask.sig[3]) << 32); case 1: act.sa_mask.sig[0] = act32.sa_mask.sig[0] | (((long)act32.sa_mask.sig[1]) << 32); } _stp_sigaction_str(&act, STAP_RETVALUE, MAXSTRINGLEN); } else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); } #endif %} function _struct_old_sigaction32_u:string(uaddr:long) %{ /* pure */ #ifdef CONFIG_COMPAT #include <linux/compat.h> #ifdef CONFIG_COMPAT_OLD_SIGACTION struct compat_old_sigaction act32; #else // There seems to be no public cross arch header that defines this. // For x86, you can find it in asm/ia32.h. For s390x, it is defined // in a private header. struct old_sigaction32 { compat_uptr_t sa_handler; compat_old_sigset_t sa_mask; /* A 32 bit mask */ unsigned int sa_flags; unsigned int sa_restorer; /* Another 32 bit pointer */ }; struct old_sigaction32 act32; #endif char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char*)&act32, ptr, sizeof(act32)) == 0) { struct sigaction act; act.sa_handler = (void *)compat_ptr(act32.sa_handler); #ifdef SA_RESTORER act.sa_restorer = (void *)compat_ptr(act32.sa_restorer); #endif act.sa_flags = (unsigned long)act32.sa_flags; siginitset(&act.sa_mask, act32.sa_mask); _stp_sigaction_str(&act, STAP_RETVALUE, MAXSTRINGLEN); } else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); } #endif %} /* * Function irqflags_str : * Returns the symbolic string representation of the IRQ flags. * */ %{ #include <linux/interrupt.h> #ifndef IRQF_ONESHOT #define IRQF_ONESHOT 0x00002000 #endif static const _stp_val_array _stp_irq_list[] = { #ifdef IRQF_DISABLED V(IRQF_DISABLED), #endif #ifdef IRQF_SAMPLE_RANDOM V(IRQF_SAMPLE_RANDOM), #endif #ifdef IRQF_SHARED V(IRQF_SHARED), #endif #ifdef IRQF_PROBE_SHARED V(IRQF_PROBE_SHARED), #endif #ifdef IRQF_TIMER V(IRQF_TIMER), #endif #ifdef IRQF_PERCPU V(IRQF_PERCPU), #endif #ifdef IRQF_NOBALANCING V(IRQF_NOBALANCING), #endif #ifdef IRQF_IRQPOLL V(IRQF_IRQPOLL), #endif V(IRQF_ONESHOT), {0, NULL} }; %} function irqflags_str:string(f:long) %{ /* pure */ /* unprivileged */ _stp_lookup_or_str(_stp_irq_list, STAP_ARG_f, STAP_RETVALUE, MAXSTRINGLEN); %} @__private30 function _stp_struct_iovec_u:string(iov_uaddr:long) %{ /* pure */ char *iov_uaddr = (void *)(uintptr_t)STAP_ARG_iov_uaddr; struct iovec iov = { 0 }; if (iov_uaddr == NULL) strlcpy(STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char*)&iov, iov_uaddr, sizeof(struct iovec)) == 0) { _stp_snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[{%#lx, %lu}]", iov.iov_base, iov.iov_len); } else _stp_snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)iov_uaddr); } %} @__private30 function _stp_struct_compat_iovec_u:string(iov_uaddr:long) %{ /* pure */ #ifdef CONFIG_COMPAT char *iov_uaddr = (void *)(uintptr_t)STAP_ARG_iov_uaddr; struct compat_iovec iov = { 0 }; if (iov_uaddr == NULL) strlcpy(STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char*)&iov, iov_uaddr, sizeof(struct compat_iovec)) == 0) { _stp_snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[{%#lx, %lu}]", iov.iov_base, iov.iov_len); } else _stp_snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)iov_uaddr); } #endif %} %{ #include <linux/ptrace.h> static const _stp_val_array _stp_ptrace_options_list[] = { #ifdef PTRACE_O_EXITKILL V(PTRACE_O_EXITKILL), #endif V(PTRACE_O_TRACECLONE), V(PTRACE_O_TRACEEXEC), V(PTRACE_O_TRACEEXIT), V(PTRACE_O_TRACEFORK), V(PTRACE_O_TRACESYSGOOD), V(PTRACE_O_TRACEVFORK), V(PTRACE_O_TRACEVFORKDONE), #ifdef PTRACE_O_TRACESECCOMP V(PTRACE_O_TRACESECCOMP), #endif {0, NULL} }; %} /* PTRACE_SETOPTIONS parser of the DATA parameter. */ function _ptrace_options_str:string(f:long) %{ /* pure */ /* unprivileged */ unsigned long f = (unsigned long)STAP_ARG_f; _stp_lookup_or_str(_stp_ptrace_options_list, f, STAP_RETVALUE, MAXSTRINGLEN); %} /* ptrace syscall provisioning of argstr. */ %{ #include <linux/elf.h> static const _stp_val_array _stp_elf_notes_list[] = { V(NT_PRSTATUS), V(NT_PRFPREG), V(NT_PRPSINFO), V(NT_TASKSTRUCT), V(NT_AUXV), #ifdef NT_SIGINFO V(NT_SIGINFO), #endif #ifdef NT_FILE V(NT_FILE), #endif V(NT_PRXFPREG), #ifdef NT_PPC_VMX V(NT_PPC_VMX), #endif #ifdef NT_PPC_SPE V(NT_PPC_SPE), #endif #ifdef NT_PPC_VSX V(NT_PPC_VSX), #endif #ifdef NT_386_TLS V(NT_386_TLS), #endif #ifdef NT_386_IOPERM V(NT_386_IOPERM), #endif #ifdef NT_X86_XSTATE V(NT_X86_XSTATE), #endif #ifdef NT_S390_HIGH_GPRS V(NT_S390_HIGH_GPRS), #endif #ifdef NT_S390_TIMER V(NT_S390_TIMER), #endif #ifdef NT_S390_TODCMP V(NT_S390_TODCMP), #endif #ifdef NT_S390_TODPREG V(NT_S390_TODPREG), #endif #ifdef NT_S390_CTRS V(NT_S390_CTRS), #endif #ifdef NT_S390_PREFIX V(NT_S390_PREFIX), #endif #ifdef NT_S390_LAST_BREAK V(NT_S390_LAST_BREAK), #endif #ifdef NT_S390_SYSTEM_CALL V(NT_S390_SYSTEM_CALL), #endif #ifdef NT_S390_TDB V(NT_S390_TDB), #endif #ifdef NT_S390_VXRS_LOW V(NT_S390_VXRS_LOW), #endif #ifdef NT_S390_VXRS_HIGH V(NT_S390_VXRS_HIGH), #endif #ifdef NT_ARM_VFP V(NT_ARM_VFP), #endif #ifdef NT_ARM_TLS V(NT_ARM_TLS), #endif #ifdef NT_ARM_HW_BREAK V(NT_ARM_HW_BREAK), #endif #ifdef NT_ARM_HW_WATCH V(NT_ARM_HW_WATCH), #endif #ifdef NT_ARM_SYSTEM_CALL V(NT_ARM_SYSTEM_CALL), #endif #ifdef NT_METAG_CBUF V(NT_METAG_CBUF), #endif #ifdef NT_METAG_RPIPE V(NT_METAG_RPIPE), #endif #ifdef NT_METAG_TLS V(NT_METAG_TLS), #endif {0, NULL} }; %} @__private30 function _stp_elf_notes_str:string(value:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_elf_notes_list, (unsigned long)STAP_ARG_value, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #ifndef PTRACE_GETREGSET # define PTRACE_GETREGSET 0x4204 #endif #ifndef PTRACE_SETREGSET # define PTRACE_SETREGSET 0x4205 #endif #ifndef PTRACE_SEIZE # define PTRACE_SEIZE 0x4206 #endif #ifndef PTRACE_INTERRUPT # define PTRACE_INTERRUPT 0x4207 #endif #ifndef PTRACE_LISTEN # define PTRACE_LISTEN 0x4208 #endif #ifndef PTRACE_PEEKSIGINFO # define PTRACE_PEEKSIGINFO 0x4209 #endif #ifndef PTRACE_GETSIGMASK # define PTRACE_GETSIGMASK 0x420a #endif #ifndef PTRACE_SETSIGMASK # define PTRACE_SETSIGMASK 0x420b #endif /* These are the architecture-independent ptrace requests (although * some return architecture-dependent register buffers). */ static const _stp_val_array _stp_ptrace_request_list[] = { V(PTRACE_TRACEME), V(PTRACE_PEEKTEXT), V(PTRACE_PEEKDATA), V(PTRACE_PEEKUSR), V(PTRACE_POKETEXT), V(PTRACE_POKEDATA), V(PTRACE_POKEUSR), V(PTRACE_CONT), V(PTRACE_KILL), V(PTRACE_SINGLESTEP), V(PTRACE_ATTACH), V(PTRACE_DETACH), V(PTRACE_SYSCALL), V(PTRACE_SETOPTIONS), V(PTRACE_GETEVENTMSG), V(PTRACE_GETSIGINFO), V(PTRACE_SETSIGINFO), V(PTRACE_GETREGSET), V(PTRACE_SETREGSET), V(PTRACE_SEIZE), V(PTRACE_INTERRUPT), V(PTRACE_LISTEN), V(PTRACE_PEEKSIGINFO), V(PTRACE_GETSIGMASK), V(PTRACE_SETSIGMASK), {0, NULL} }; %} @__private30 function __ptrace_request_str:string(request:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_ptrace_request_list, (unsigned long)STAP_ARG_request, STAP_RETVALUE, MAXSTRINGLEN); %} function _ptrace_argstr(request, pid, addr, data) { // Handle arch-specific ptrace requests first. retval=_arch_ptrace_argstr(request, pid, addr, data) if (retval != "") return retval // Handle generic ptrace requests. if (request == @const("PTRACE_PEEKTEXT") || request == @const("PTRACE_PEEKDATA") || request == @const("PTRACE_PEEKUSR")) /* For PTRACE_PEEK{TEXT,DATA,USR}, 'data' is ignored * from the user's point of view, but glibc stores the * result at the 'data' address. */ return sprintf("%s, %d, %p, [%p]", __ptrace_request_str(request), pid, addr, data) if (request == @const("PTRACE_POKETEXT") || request == @const("PTRACE_POKEDATA") || request == @const("PTRACE_POKEUSR") || request == @const("PTRACE_PEEKSIGINFO")) return sprintf("%s, %d, %p, %p", __ptrace_request_str(request), pid, addr, data) if (request == @const("PTRACE_CONT") || request == @const("PTRACE_SYSCALL") || request == @const("PTRACE_SINGLESTEP") || request == @const("PTRACE_DETACH")) return sprintf("%s, %d, %#x, %s", __ptrace_request_str(request), pid, addr, _signal_name (data)) if (request == @const("PTRACE_GETSIGINFO") || request == @const("PTRACE_SETSIGINFO") || request == @const("PTRACE_GETEVENTMSG") || request == @const("PTRACE_GETSIGMASK") || request == @const("PTRACE_SETSIGMASK")) return sprintf("%s, %d, %#x, %p", __ptrace_request_str(request), pid, addr, data) if (request == @const("PTRACE_GETREGSET") || request == @const("PTRACE_SETREGSET")) return sprintf("%s, %d, %s, %s", __ptrace_request_str(request), pid, _stp_elf_notes_str(addr), (@__compat_task ? _stp_struct_compat_iovec_u(data) : _stp_struct_iovec_u(data))) if (request == @const("PTRACE_TRACEME") || request == @const("PTRACE_KILL") || request == @const("PTRACE_ATTACH") || request == @const("PTRACE_SEIZE") || request == @const("PTRACE_INTERRUPT") || request == @const("PTRACE_LISTEN")) return sprintf("%s, %d, %#x, %#x", __ptrace_request_str(request), pid, addr, data) if (request == @const("PTRACE_SETOPTIONS")) return sprintf("PTRACE_SETOPTIONS, %d, %#x, %s", pid, addr, _ptrace_options_str(data)) return sprintf("%s, %d, %p, %p", __ptrace_request_str(request), pid, addr, data) } /* ptrace.return syscall decoder for PTRACE_GETEVENTMSG. */ function _ptrace_return_geteventmsg_data(request,data) { if (request == @const("PTRACE_GETEVENTMSG")) return user_long(data) } %{ #include <linux/swap.h> static const _stp_val_array _stp_swapon_flags_list[] = { V(SWAP_FLAG_PREFER), #ifdef SWAP_FLAG_DISCARD V(SWAP_FLAG_DISCARD), #endif #ifdef SWAP_FLAG_DISCARD_ONCE V(SWAP_FLAG_DISCARD_ONCE), #endif #ifdef SWAP_FLAG_DISCARD_PAGES V(SWAP_FLAG_DISCARD_PAGES), #endif {0, NULL} }; %} function _swapon_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ unsigned int flags = (unsigned int)STAP_ARG_flags; _stp_lookup_or_str(_stp_swapon_flags_list, (flags & ~SWAP_FLAG_PRIO_MASK), STAP_RETVALUE, MAXSTRINGLEN); if (STAP_ARG_flags & SWAP_FLAG_PREFER) { int slen; slen = strlen(STAP_RETVALUE); _stp_snprintf(STAP_RETVALUE + slen, MAXSTRINGLEN - slen, "|%d", flags & SWAP_FLAG_PRIO_MASK); } %} /* do_fork helper function to determine fork type. */ @__private30 function __is_user_regs:long (regs:long) %{ /* pure */ struct pt_regs * regs = (void *)((uintptr_t)STAP_ARG_regs); /* copied from asm/ptrace.h */ #if defined(__i386__) #ifdef STAPCONF_X86_UNIREGS int cs = kread(®s->cs); #else int cs = kread(®s->xcs); #endif STAP_RETVALUE = (!!((cs & 3))); #elif defined(__x86_64__) unsigned long cs = kread(®s->cs); STAP_RETVALUE = (!!((cs & 3))); #elif defined(__ia64__) unsigned long psr = kread(®s->cr_ipsr); STAP_RETVALUE = (((struct ia64_psr *) &psr)->cpl != 0); #elif defined(__powerpc64__) unsigned long msr = kread(®s->msr); STAP_RETVALUE = ((msr >> MSR_PR_LG) & 0x1); #elif defined(__powerpc__) unsigned long msr = kread(®s->msr); STAP_RETVALUE = ((msr >> MSR_PR) != 0); #elif defined(__arm__) long cpsr = kread(®s->ARM_cpsr); STAP_RETVALUE = ((cpsr & 0xf) == 0); #elif defined(__mips__) unsigned long cp0 = kread(®s->cp0_status); #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) STAP_RETVALUE = ((cp0 & 0x08) == 8); #else STAP_RETVALUE = ((cp0 & 0x18) == 0x10); #endif #elif defined(__s390__) || defined(__s390x__) unsigned long mask = kread(®s->psw.mask); STAP_RETVALUE = ((mask & PSW_MASK_PSTATE) != 0); #elif defined(__aarch64__) long pstate = kread(®s->pstate); STAP_RETVALUE = ((pstate & PSR_MODE_MASK) == PSR_MODE_EL0t); #else #error "Unimplemented architecture" #endif CATCH_DEREF_FAULT(); %} %{ #include <linux/ipc.h> #include <linux/shm.h> static const _stp_val_array _stp_shmget_flags_list[] = { V(IPC_CREAT), V(IPC_EXCL), V(SHM_HUGETLB), V(SHM_NORESERVE), {0, NULL} }; %} function _stp_shmget_flags_str:string(shmflg:long) %{ /* pure */ /* unprivileged */ unsigned int shmflg = (unsigned int)STAP_ARG_shmflg; unsigned int modebits; /* Lowest 9 bits are mode bits. */ modebits = shmflg & 0777; shmflg &= ~0777; _stp_lookup_or_str(_stp_shmget_flags_list, shmflg, STAP_RETVALUE, MAXSTRINGLEN); if (modebits) { int slen; slen = strlen(STAP_RETVALUE); if (slen) _stp_snprintf(STAP_RETVALUE + slen, MAXSTRINGLEN - slen, "|%#o", modebits); else _stp_snprintf(STAP_RETVALUE, MAXSTRINGLEN, "%#o", modebits); } %} function _stp_msgget_key_str:string(key:long) { if (key == @const("IPC_PRIVATE")) return "IPC_PRIVATE" return sprintf("%d", key) } %{ #include <linux/msg.h> static const _stp_val_array _stp_msgctl_list[] = { V(IPC_INFO), V(IPC_STAT), V(IPC_RMID), V(IPC_SET), V(MSG_INFO), V(MSG_STAT), {0, NULL} }; %} function _stp_msgctl_cmd_str:string(cmd:long) %{ /* pure */ /* unprivileged */ unsigned int cmd = STAP_ARG_cmd; if (cmd & IPC_64) { strlcpy (STAP_RETVALUE, "IPC_64|", MAXSTRINGLEN); cmd &= ~IPC_64; } _stp_lookup_str(_stp_msgctl_list, cmd, STAP_RETVALUE, MAXSTRINGLEN); %} %{ static const _stp_val_array _stp_msgflg_list[] = { V(MSG_NOERROR), V(MSG_EXCEPT), V(IPC_NOWAIT), {0, NULL} }; %} function _stp_msgflg_str:string(msgflg:long) %{ /* pure */ /* unprivileged */ unsigned int msgflg = STAP_ARG_msgflg; _stp_lookup_or_str(_stp_msgflg_list, msgflg, STAP_RETVALUE, MAXSTRINGLEN); %} %{ // Copied from ipc/compat.c. #ifdef CONFIG_COMPAT struct compat_ipc_kludge { compat_uptr_t msgp; compat_long_t msgtyp; }; #endif %} function _stp_compat_msgrcv_msgbuf:long(uaddr:long, version:long) %{ /* pure */ #ifdef CONFIG_COMPAT char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; int version = (int)(unsigned long)STAP_ARG_version; void *msgbuf = ptr; if (!version) { struct compat_ipc_kludge ipck; msgbuf = NULL; if (ptr != NULL && _stp_copy_from_user((char*)&ipck, ptr, sizeof(ipck)) == 0) { msgbuf = compat_ptr(ipck.msgp); } } STAP_RETVALUE = (unsigned long)msgbuf; #endif %} function _stp_compat_msgrcv_msgtyp:long(uaddr:long, version:long, msgtyp:long) %{ /* pure */ #ifdef CONFIG_COMPAT char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; int version = (int)(unsigned long)STAP_ARG_version; long msgtyp = (long)STAP_ARG_msgtyp; if (!version) { struct compat_ipc_kludge ipck; if (ptr != NULL && _stp_copy_from_user((char*)&ipck, ptr, sizeof(ipck)) == 0) { msgtyp = ipck.msgtyp; } } STAP_RETVALUE = msgtyp; #endif %} %{ #include <linux/xattr.h> static const _stp_val_array _stp_xattr_flags_list[] = { V(XATTR_CREATE), V(XATTR_REPLACE), {0, NULL} }; %} function _stp_xattr_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ unsigned int flags = STAP_ARG_flags; _stp_lookup_or_str(_stp_xattr_flags_list, flags, STAP_RETVALUE, MAXSTRINGLEN); %} function _stp_xattr_val_str:string(uaddr:long, size:long) %{ /* pure */ void *uaddr = (void *)(uintptr_t)STAP_ARG_uaddr; unsigned long size = STAP_ARG_size; unsigned char buffer[50]; size_t copy_size = clamp_t(size_t, size, 0, sizeof(buffer)); if (uaddr != NULL && copy_size > 0 && _stp_copy_from_user(buffer, uaddr, copy_size) == 0) { size_t i; unsigned char *out = STAP_RETVALUE; // Save 3 chars: 2 for the leading and trailing // double-quote chars, one for the trailing NUL. size_t out_size = MAXSTRINGLEN - 3; *out++ = '"'; for (i = 0; i < copy_size; ++i) { #define _stp_is_printable_ascii(c) ((c) >= ' ' && (c) <= 0x7e) #define _stp_tohex(n) "0123456789abcdef"[n] if (_stp_is_printable_ascii(buffer[i])) { if (--out_size >= 0) *out++ = buffer[i]; } else { if (out_size < 4) break; out_size -= 4; if (out_size >= 0) { *out++ = '\\'; *out++ = 'x'; *out++ = _stp_tohex(buffer[i] / 16); *out++ = _stp_tohex(buffer[i] % 16); } } if (out_size == 0) break; } // Don't print terminating NUL from the input data if // there is one. if (i > 1 && buffer[i - 1] == '\0' && _stp_is_printable_ascii(buffer[i - 2])) out -= 4; *out++ = '"'; *out = '\0'; } else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)uaddr); %} %{ #include <linux/ioprio.h> static const _stp_val_array _stp_ioprio_who_list[] = { V(IOPRIO_WHO_PROCESS), V(IOPRIO_WHO_PGRP), V(IOPRIO_WHO_USER), {0, NULL} }; static const _stp_val_array _stp_ioprio_class_list[] = { V(IOPRIO_CLASS_NONE), V(IOPRIO_CLASS_RT), V(IOPRIO_CLASS_BE), V(IOPRIO_CLASS_IDLE), {0, NULL} }; %} function _stp_ioprio_which_str:string(who:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str2(_stp_ioprio_who_list, (int)STAP_ARG_who, STAP_RETVALUE, MAXSTRINGLEN, 10); %} function _stp_ioprio_value_str:string(value:long) %{ /* pure */ /* unprivileged */ unsigned int class = IOPRIO_PRIO_CLASS(((unsigned int)STAP_ARG_value)); int slen; _stp_lookup_str(_stp_ioprio_class_list, class, STAP_RETVALUE, MAXSTRINGLEN); slen = strlen(STAP_RETVALUE); _stp_snprintf(STAP_RETVALUE + slen, MAXSTRINGLEN - slen, "|%d", IOPRIO_PRIO_DATA(((int)STAP_ARG_value))); %} %{ #include <linux/mempolicy.h> static const _stp_val_array _stp_mempolicy_flags_list[] = { V(MPOL_F_NODE), V(MPOL_F_ADDR), #ifdef MPOL_F_MEMS_ALLOWED V(MPOL_F_MEMS_ALLOWED), #endif {0, NULL} }; #ifndef MPOL_MODE_FLAGS #define MPOL_MODE_FLAGS 0 #endif static const _stp_val_array _stp_mempolicy_mode_flags_list[] = { #ifdef MPOL_F_STATIC_NODES V(MPOL_F_STATIC_NODES), #endif #ifdef MPOL_F_RELATIVE_NODES V(MPOL_F_RELATIVE_NODES), #endif {0, NULL} }; static const _stp_val_array _stp_mempolicy_mode_list[] = { V(MPOL_DEFAULT), V(MPOL_PREFERRED), V(MPOL_BIND), V(MPOL_INTERLEAVE), #ifdef MPOL_LOCAL V(MPOL_LOCAL), #endif {0, NULL} }; %} function _mempolicy_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ _stp_lookup_or_str(_stp_mempolicy_flags_list, (unsigned long)STAP_ARG_flags, STAP_RETVALUE, MAXSTRINGLEN); %} function _mempolicy_mode_str:string(mode:long) %{ /* pure */ /* unprivileged */ unsigned int mode = (unsigned int)STAP_ARG_mode; int len = 0; if (mode != 0xffffffff && mode & MPOL_MODE_FLAGS) { _stp_lookup_str(_stp_mempolicy_mode_flags_list, mode & MPOL_MODE_FLAGS, STAP_RETVALUE, MAXSTRINGLEN); strlcat(STAP_RETVALUE, "|", MAXSTRINGLEN); len = strlen(STAP_RETVALUE); mode &= ~MPOL_MODE_FLAGS; } _stp_lookup_str(_stp_mempolicy_mode_list, mode, STAP_RETVALUE + len, MAXSTRINGLEN - len); %} %{ #include <linux/keyctl.h> static const _stp_val_array _stp_keyctl_cmd_list[] = { V(KEYCTL_GET_KEYRING_ID), V(KEYCTL_JOIN_SESSION_KEYRING), V(KEYCTL_UPDATE), V(KEYCTL_REVOKE), V(KEYCTL_CHOWN), V(KEYCTL_SETPERM), V(KEYCTL_DESCRIBE), V(KEYCTL_CLEAR), V(KEYCTL_LINK), V(KEYCTL_UNLINK), V(KEYCTL_SEARCH), V(KEYCTL_READ), V(KEYCTL_INSTANTIATE), V(KEYCTL_NEGATE), V(KEYCTL_SET_REQKEY_KEYRING), V(KEYCTL_SET_TIMEOUT), V(KEYCTL_ASSUME_AUTHORITY), #ifdef KEYCTL_GET_SECURITY V(KEYCTL_GET_SECURITY), #endif #ifdef KEYCTL_SESSION_TO_PARENT V(KEYCTL_SESSION_TO_PARENT), #endif #ifdef KEYCTL_REJECT V(KEYCTL_REJECT), #endif #ifdef KEYCTL_INSTANTIATE_IOV V(KEYCTL_INSTANTIATE_IOV), #endif #ifdef KEYCTL_INVALIDATE V(KEYCTL_INVALIDATE), #endif #ifdef KEYCTL_GET_PERSISTENT V(KEYCTL_GET_PERSISTENT), #endif {0, NULL} }; // For older kernels, we need to define new constants for the // @__keyctl_argstr() macro #ifndef KEYCTL_GET_SECURITY #define KEYCTL_GET_SECURITY 17 #endif #ifndef KEYCTL_SESSION_TO_PARENT #define KEYCTL_SESSION_TO_PARENT 18 #endif #ifndef KEYCTL_REJECT #define KEYCTL_REJECT 19 #endif #ifndef KEYCTL_INSTANTIATE_IOV #define KEYCTL_INSTANTIATE_IOV 20 #endif #ifndef KEYCTL_INVALIDATE #define KEYCTL_INVALIDATE 21 #endif #ifndef KEYCTL_GET_PERSISTENT #define KEYCTL_GET_PERSISTENT 22 #endif %} function _stp_keyctl_cmd_str:string(cmd:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str2(_stp_keyctl_cmd_list, (int)STAP_ARG_cmd, STAP_RETVALUE, MAXSTRINGLEN, 10); %} %{ static const _stp_val_array _stp_keyctl_keyring_shortcut_list[] = { V(KEY_SPEC_THREAD_KEYRING), V(KEY_SPEC_PROCESS_KEYRING), V(KEY_SPEC_SESSION_KEYRING), V(KEY_SPEC_USER_KEYRING), V(KEY_SPEC_USER_SESSION_KEYRING), V(KEY_SPEC_GROUP_KEYRING), V(KEY_SPEC_REQKEY_AUTH_KEY), #ifdef KEY_SPEC_REQUESTOR_KEYRING V(KEY_SPEC_REQUESTOR_KEYRING), #endif {0, NULL} }; %} function _stp_keyctl_keyring_shortcut_str:string(id:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str2(_stp_keyctl_keyring_shortcut_list, (int)STAP_ARG_id, STAP_RETVALUE, MAXSTRINGLEN, 10); %} %{ static const _stp_val_array _stp_keyctl_default_keyrings_list[] = { V(KEY_REQKEY_DEFL_NO_CHANGE), V(KEY_REQKEY_DEFL_DEFAULT), V(KEY_REQKEY_DEFL_THREAD_KEYRING), V(KEY_REQKEY_DEFL_PROCESS_KEYRING), V(KEY_REQKEY_DEFL_SESSION_KEYRING), V(KEY_REQKEY_DEFL_USER_KEYRING), V(KEY_REQKEY_DEFL_USER_SESSION_KEYRING), V(KEY_REQKEY_DEFL_GROUP_KEYRING), {0, NULL} }; %} function _stp_keyctl_default_keyrings_str:string(id:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str2(_stp_keyctl_default_keyrings_list, (int)STAP_ARG_id, STAP_RETVALUE, MAXSTRINGLEN, 10); %} %{ #include <linux/key.h> static const _stp_val_array _stp_keyctl_perm_list[] = { #if defined(CONFIG_KEYS) V(KEY_POS_VIEW), V(KEY_POS_READ), V(KEY_POS_WRITE), V(KEY_POS_SEARCH), V(KEY_POS_LINK), V(KEY_POS_SETATTR), V(KEY_POS_ALL), V(KEY_USR_VIEW), V(KEY_USR_READ), V(KEY_USR_WRITE), V(KEY_USR_SEARCH), V(KEY_USR_LINK), V(KEY_USR_SETATTR), V(KEY_USR_ALL), V(KEY_GRP_VIEW), V(KEY_GRP_READ), V(KEY_GRP_WRITE), V(KEY_GRP_SEARCH), V(KEY_GRP_LINK), V(KEY_GRP_SETATTR), V(KEY_GRP_ALL), V(KEY_OTH_VIEW), V(KEY_OTH_READ), V(KEY_OTH_WRITE), V(KEY_OTH_SEARCH), V(KEY_OTH_LINK), V(KEY_OTH_SETATTR), V(KEY_OTH_ALL), #endif /* CONFIG_KEYS */ {0, NULL} }; %} function _stp_keyctl_perm_str:string(mask:long) %{ /* pure */ /* unprivileged */ uint32_t mask = (uint32_t)STAP_ARG_mask; _stp_lookup_or_str2(_stp_keyctl_perm_list, mask, STAP_RETVALUE, MAXSTRINGLEN, 10); %} %{ #include <linux/module.h> #ifndef MODULE_INIT_IGNORE_MODVERSIONS #define MODULE_INIT_IGNORE_MODVERSIONS 1 #endif #ifndef MODULE_INIT_IGNORE_VERMAGIC #define MODULE_INIT_IGNORE_VERMAGIC 2 #endif static const _stp_val_array _stp_finit_module_flags_list[] = { V(MODULE_INIT_IGNORE_MODVERSIONS), V(MODULE_INIT_IGNORE_VERMAGIC), {0, NULL} }; %} function _finit_module_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ _stp_lookup_or_str(_stp_finit_module_flags_list, (unsigned int)STAP_ARG_flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) #include <linux/prctl.h> #else #include <uapi/linux/prctl.h> #endif static const _stp_val_array _stp_prctl_option_list[] = { V(PR_SET_PDEATHSIG), V(PR_GET_PDEATHSIG), V(PR_GET_DUMPABLE), V(PR_SET_DUMPABLE), V(PR_GET_UNALIGN), V(PR_SET_UNALIGN), V(PR_GET_KEEPCAPS), V(PR_SET_KEEPCAPS), V(PR_GET_FPEMU), V(PR_SET_FPEMU), V(PR_GET_FPEXC), V(PR_SET_FPEXC), V(PR_GET_TIMING), V(PR_SET_TIMING), V(PR_SET_NAME), V(PR_GET_NAME), V(PR_GET_ENDIAN), V(PR_SET_ENDIAN), #ifdef PR_GET_SECCOMP V(PR_GET_SECCOMP), #endif #ifdef PR_SET_SECCOMP V(PR_SET_SECCOMP), #endif #ifdef PR_CAPBSET_READ V(PR_CAPBSET_READ), #endif #ifdef PR_CAPBSET_DROP V(PR_CAPBSET_DROP), #endif #ifdef PR_GET_TSC V(PR_GET_TSC), #endif #ifdef PR_SET_TSC V(PR_SET_TSC), #endif #ifdef PR_GET_SECUREBITS V(PR_GET_SECUREBITS), #endif #ifdef PR_SET_SECUREBITS V(PR_SET_SECUREBITS), #endif #ifdef PR_SET_TIMERSLACK V(PR_SET_TIMERSLACK), #endif #ifdef PR_GET_TIMERSLACK V(PR_GET_TIMERSLACK), #endif #ifdef PR_TASK_PERF_EVENTS_DISABLE V(PR_TASK_PERF_EVENTS_DISABLE), #endif #ifdef PR_TASK_PERF_EVENTS_ENABLE V(PR_TASK_PERF_EVENTS_ENABLE), #endif #ifdef PR_MCE_KILL V(PR_MCE_KILL), #endif #ifdef PR_MCE_KILL_GET V(PR_MCE_KILL_GET), #endif #ifdef PR_SET_MM V(PR_SET_MM), #endif #ifdef PR_SET_PTRACER V(PR_SET_PTRACER), #endif #ifdef PR_SET_CHILD_SUBREAPER V(PR_SET_CHILD_SUBREAPER), #endif #ifdef PR_GET_CHILD_SUBREAPER V(PR_GET_CHILD_SUBREAPER), #endif #ifdef PR_SET_NO_NEW_PRIVS V(PR_SET_NO_NEW_PRIVS), #endif #ifdef PR_GET_NO_NEW_PRIVS V(PR_GET_NO_NEW_PRIVS), #endif #ifdef PR_GET_TID_ADDRESS V(PR_GET_TID_ADDRESS), #endif #ifdef PR_SET_THP_DISABLE V(PR_SET_THP_DISABLE), #endif #ifdef PR_GET_THP_DISABLE V(PR_GET_THP_DISABLE), #endif #ifdef PR_MPX_ENABLE_MANAGEMENT V(PR_MPX_ENABLE_MANAGEMENT), #endif #ifdef PR_MPX_DISABLE_MANAGEMENT V(PR_MPX_DISABLE_MANAGEMENT), #endif {0, NULL} }; // Options that get passed to PR_SET_UNALIGN and returned by PR_GET_UNALIGN. static const _stp_val_array _stp_prctl_unalign_option_list[] = { V(PR_UNALIGN_NOPRINT), V(PR_UNALIGN_SIGBUS), {0, NULL} }; // Options that get passed to PR_SET_FPEMU and returned by PR_GET_FPEMU. static const _stp_val_array _stp_prctl_fpemu_option_list[] = { V(PR_FPEMU_NOPRINT), V(PR_FPEMU_SIGFPE), {0, NULL} }; // Options that get passed to PR_SET_FPEXC and returned by PR_GET_FPEXC. static const _stp_val_array _stp_prctl_fpexc_option_list[] = { V(PR_FP_EXC_SW_ENABLE), V(PR_FP_EXC_DIV), V(PR_FP_EXC_OVF), V(PR_FP_EXC_UND), V(PR_FP_EXC_RES), V(PR_FP_EXC_INV), V(PR_FP_EXC_DISABLED), V(PR_FP_EXC_NONRECOV), V(PR_FP_EXC_ASYNC), V(PR_FP_EXC_PRECISE), {0, NULL} }; // Options that get passed to PR_SET_TIMING and returned by PR_GET_TIMING. static const _stp_val_array _stp_prctl_timing_option_list[] = { V(PR_TIMING_STATISTICAL), V(PR_TIMING_TIMESTAMP), {0, NULL} }; // Options that get passed to PR_SET_ENDIAN and returned by PR_GET_ENDIAN. static const _stp_val_array _stp_prctl_endian_option_list[] = { V(PR_ENDIAN_BIG), V(PR_ENDIAN_LITTLE), V(PR_ENDIAN_PPC_LITTLE), {0, NULL} }; #ifdef PR_SET_TSC // Options that get passed to PR_SET_TSC and returned by PR_GET_TSC. static const _stp_val_array _stp_prctl_tsc_option_list[] = { V(PR_TSC_ENABLE), V(PR_TSC_SIGSEGV), {0, NULL} }; #endif #ifdef PR_MCE_KILL // Options that get passed to PR_MCE_KILL and returned by PR_MCE_KILL_GET. static const _stp_val_array _stp_prctl_mce_kill_option_list[] = { V(PR_MCE_KILL_CLEAR), V(PR_MCE_KILL_SET), {0, NULL} }; // Options for PR_MCE_KILL with PR_MCE_KILL_SET. static const _stp_val_array _stp_prctl_mce_kill_option2_list[] = { V(PR_MCE_KILL_LATE), V(PR_MCE_KILL_EARLY), V(PR_MCE_KILL_DEFAULT), {0, NULL} }; #endif #ifdef PR_SET_MM // Options that get passed to PR_SET_MM. static const _stp_val_array _stp_prctl_mm_option_list[] = { V(PR_SET_MM_START_CODE), V(PR_SET_MM_END_CODE), V(PR_SET_MM_START_DATA), V(PR_SET_MM_END_DATA), V(PR_SET_MM_START_STACK), V(PR_SET_MM_START_BRK), V(PR_SET_MM_BRK), #ifdef PR_SET_MM_ARG_START V(PR_SET_MM_ARG_START), #endif #ifdef PR_SET_MM_ARG_END V(PR_SET_MM_ARG_END), #endif #ifdef PR_SET_MM_ENV_START V(PR_SET_MM_ENV_START), #endif #ifdef PR_SET_MM_ENV_END V(PR_SET_MM_ENV_END), #endif #ifdef PR_SET_MM_AUXV V(PR_SET_MM_AUXV), #endif #ifdef PR_SET_MM_EXE_FILE V(PR_SET_MM_EXE_FILE), #endif #ifdef PR_SET_MM_MAP V(PR_SET_MM_MAP), #endif #ifdef PR_SET_MM_MAP_SIZE V(PR_SET_MM_MAP_SIZE), #endif {0, NULL} }; #endif #ifdef PR_SET_PTRACER // Options that get passed to PR_SET_PTRACER. static const _stp_val_array _stp_prctl_ptracer_option_list[] = { V(PR_SET_PTRACER_ANY), {0, NULL} }; #endif #include <linux/capability.h> static const _stp_val_array _stp_linux_capability_list[] = { V(CAP_CHOWN), V(CAP_DAC_OVERRIDE), V(CAP_DAC_READ_SEARCH), V(CAP_FOWNER), V(CAP_FSETID), V(CAP_KILL), V(CAP_SETGID), V(CAP_SETUID), V(CAP_SETPCAP), V(CAP_LINUX_IMMUTABLE), V(CAP_NET_BIND_SERVICE), V(CAP_NET_BROADCAST), V(CAP_NET_ADMIN), V(CAP_NET_RAW), V(CAP_IPC_LOCK), V(CAP_IPC_OWNER), V(CAP_SYS_MODULE), V(CAP_SYS_RAWIO), V(CAP_SYS_CHROOT), V(CAP_SYS_PTRACE), V(CAP_SYS_PACCT), V(CAP_SYS_ADMIN), V(CAP_SYS_BOOT), V(CAP_SYS_NICE), V(CAP_SYS_RESOURCE), V(CAP_SYS_TIME), V(CAP_SYS_TTY_CONFIG), V(CAP_MKNOD), V(CAP_LEASE), V(CAP_AUDIT_WRITE), V(CAP_AUDIT_CONTROL), #ifdef CAP_SETFCAP V(CAP_SETFCAP), #endif #ifdef CAP_MAC_OVERRIDE V(CAP_MAC_OVERRIDE), #endif #ifdef CAP_MAC_ADMIN V(CAP_MAC_ADMIN), #endif #ifdef CAP_SYSLOG V(CAP_SYSLOG), #endif #ifdef CAP_WAKE_ALARM V(CAP_WAKE_ALARM), #endif #ifdef CAP_BLOCK_SUSPEND V(CAP_BLOCK_SUSPEND), #endif #ifdef CAP_AUDIT_READ V(CAP_AUDIT_READ), #endif {0, NULL} }; #ifdef PR_SET_SECUREBITS #include <linux/securebits.h> #ifndef SECBIT_NOROOT #define SECBIT_NOROOT (issecure_mask(SECURE_NOROOT)) #endif #ifndef SECBIT_NOROOT_LOCKED #define SECBIT_NOROOT_LOCKED (issecure_mask(SECURE_NOROOT_LOCKED)) #endif #ifndef SECBIT_NO_SETUID_FIXUP #define SECBIT_NO_SETUID_FIXUP (issecure_mask(SECURE_NO_SETUID_FIXUP)) #endif #ifndef SECBIT_NO_SETUID_FIXUP_LOCKED #define SECBIT_NO_SETUID_FIXUP_LOCKED \ (issecure_mask(SECURE_NO_SETUID_FIXUP_LOCKED)) #endif #ifndef SECBIT_KEEP_CAPS #define SECBIT_KEEP_CAPS (issecure_mask(SECURE_KEEP_CAPS)) #endif #ifndef SECBIT_KEEP_CAPS_LOCKED #define SECBIT_KEEP_CAPS_LOCKED (issecure_mask(SECURE_KEEP_CAPS_LOCKED)) #endif static const _stp_val_array _stp_linux_securebits_list[] = { V(SECBIT_NOROOT), V(SECBIT_NOROOT_LOCKED), V(SECBIT_NO_SETUID_FIXUP), V(SECBIT_NO_SETUID_FIXUP_LOCKED), V(SECBIT_KEEP_CAPS), V(SECBIT_KEEP_CAPS_LOCKED), {0, NULL} }; #endif %} function _prctl_argstr:string(option:long, arg2:long, arg3:long, arg4:long, arg5:long) %{ /* pure */ /* unprivileged */ int len; _stp_lookup_str(_stp_prctl_option_list, (unsigned int)STAP_ARG_option, STAP_RETVALUE, MAXSTRINGLEN); switch ((unsigned int)STAP_ARG_option) { // Options that take no arguments: case PR_GET_DUMPABLE: case PR_GET_TIMING: case PR_GET_KEEPCAPS: #ifdef PR_GET_SECCOMP case PR_GET_SECCOMP: #endif #ifdef PR_TASK_PERF_EVENTS_DISABLE case PR_TASK_PERF_EVENTS_DISABLE: #endif #ifdef PR_TASK_PERF_EVENTS_ENABLE case PR_TASK_PERF_EVENTS_ENABLE: #endif #ifdef PR_GET_TIMERSLACK case PR_GET_TIMERSLACK: #endif #ifdef PR_MCE_KILL_GET case PR_MCE_KILL_GET: #endif #ifdef PR_GET_NO_NEW_PRIVS case PR_GET_NO_NEW_PRIVS: #endif #ifdef PR_GET_THP_DISABLE case PR_GET_THP_DISABLE: #endif #ifdef PR_MPX_ENABLE_MANAGEMENT case PR_MPX_ENABLE_MANAGEMENT: #endif #ifdef PR_MPX_DISABLE_MANAGEMENT case PR_MPX_DISABLE_MANAGEMENT: #endif #ifdef PR_GET_SECUREBITS case PR_GET_SECUREBITS: #endif // We're done. break; // Options that use arg2: case PR_SET_UNALIGN: strlcat(STAP_RETVALUE, ", ", MAXSTRINGLEN); len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_prctl_unalign_option_list, (unsigned long)STAP_ARG_arg2, STAP_RETVALUE + len, MAXSTRINGLEN - len); break; case PR_SET_FPEMU: strlcat(STAP_RETVALUE, ", ", MAXSTRINGLEN); len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_prctl_fpemu_option_list, (unsigned long)STAP_ARG_arg2, STAP_RETVALUE + len, MAXSTRINGLEN - len); break; case PR_SET_FPEXC: strlcat(STAP_RETVALUE, ", ", MAXSTRINGLEN); len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_prctl_fpexc_option_list, (unsigned long)STAP_ARG_arg2, STAP_RETVALUE + len, MAXSTRINGLEN - len); break; case PR_SET_TIMING: strlcat(STAP_RETVALUE, ", ", MAXSTRINGLEN); len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_prctl_timing_option_list, (unsigned long)STAP_ARG_arg2, STAP_RETVALUE + len, MAXSTRINGLEN - len); break; case PR_SET_ENDIAN: strlcat(STAP_RETVALUE, ", ", MAXSTRINGLEN); len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_prctl_endian_option_list, (unsigned long)STAP_ARG_arg2, STAP_RETVALUE + len, MAXSTRINGLEN - len); break; #ifdef PR_SET_TSC case PR_SET_TSC: strlcat(STAP_RETVALUE, ", ", MAXSTRINGLEN); len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_prctl_tsc_option_list, (unsigned long)STAP_ARG_arg2, STAP_RETVALUE + len, MAXSTRINGLEN - len); break; #endif #ifdef PR_SET_PTRACER case PR_SET_PTRACER: strlcat(STAP_RETVALUE, ", ", MAXSTRINGLEN); len = strlen(STAP_RETVALUE); // Notice we passing arg2 as a signed long // here. PR_SET_PTRACER_ANY is -1. _stp_lookup_str2(_stp_prctl_ptracer_option_list, (_stp_is_compat_task() ? (long)(int)STAP_ARG_arg2 : (long)STAP_ARG_arg2), STAP_RETVALUE + len, MAXSTRINGLEN - len, 10); break; #endif #if defined(PR_CAPBSET_READ) && defined(PR_CAPBSET_DROP) case PR_CAPBSET_READ: case PR_CAPBSET_DROP: strlcat(STAP_RETVALUE, ", ", MAXSTRINGLEN); len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_linux_capability_list, (unsigned long)STAP_ARG_arg2, STAP_RETVALUE + len, MAXSTRINGLEN - len); break; #endif #ifdef PR_SET_SECUREBITS case PR_SET_SECUREBITS: strlcat(STAP_RETVALUE, ", ", MAXSTRINGLEN); len = strlen(STAP_RETVALUE); _stp_lookup_or_str(_stp_linux_securebits_list, (unsigned long)STAP_ARG_arg2, STAP_RETVALUE + len, MAXSTRINGLEN - len); break; #endif case PR_SET_PDEATHSIG: case PR_GET_PDEATHSIG: case PR_GET_UNALIGN: case PR_GET_FPEMU: case PR_GET_FPEXC: case PR_SET_NAME: case PR_GET_NAME: case PR_GET_ENDIAN: #ifdef PR_GET_TSC case PR_GET_TSC: #endif #ifdef PR_GET_TID_ADDRESS case PR_GET_TID_ADDRESS: #endif #ifdef PR_GET_CHILD_SUBREAPER case PR_GET_CHILD_SUBREAPER: #endif #ifdef PR_SET_THP_DISABLE case PR_SET_THP_DISABLE: #endif len = strlen(STAP_RETVALUE); _stp_snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", 0x%lx", (unsigned long)STAP_ARG_arg2); break; case PR_SET_DUMPABLE: case PR_SET_KEEPCAPS: #ifdef PR_SET_CHILD_SUBREAPER case PR_SET_CHILD_SUBREAPER: #endif #ifdef PR_SET_NO_NEW_PRIVS case PR_SET_NO_NEW_PRIVS: #endif #ifdef PR_SET_TIMERSLACK case PR_SET_TIMERSLACK: #endif len = strlen(STAP_RETVALUE); _stp_snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", %lu", (unsigned long)STAP_ARG_arg2); break; // Options that use arg[23]: #ifdef PR_MCE_KILL case PR_MCE_KILL: strlcat(STAP_RETVALUE, ", ", MAXSTRINGLEN); len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_prctl_mce_kill_option_list, (unsigned long)STAP_ARG_arg2, STAP_RETVALUE + len, MAXSTRINGLEN - len); switch ((unsigned long)STAP_ARG_arg2) { case PR_MCE_KILL_SET: strlcat(STAP_RETVALUE, ", ", MAXSTRINGLEN); len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_prctl_mce_kill_option2_list, (unsigned long)STAP_ARG_arg3, STAP_RETVALUE + len, MAXSTRINGLEN - len); break; case PR_MCE_KILL_CLEAR: break; default: len = strlen(STAP_RETVALUE); _stp_snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", 0x%lx", (unsigned long)STAP_ARG_arg3); break; } break; #endif #ifdef PR_SET_SECCOMP case PR_SET_SECCOMP: strlcat(STAP_RETVALUE, ", ", MAXSTRINGLEN); len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_seccomp_mode_list, (unsigned long)STAP_ARG_arg2, STAP_RETVALUE + len, MAXSTRINGLEN - len); len = strlen(STAP_RETVALUE); _stp_snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", 0x%lx", (unsigned long)STAP_ARG_arg3); break; #endif #ifdef PR_SET_MM case PR_SET_MM: strlcat(STAP_RETVALUE, ", ", MAXSTRINGLEN); len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_prctl_mm_option_list, (unsigned long)STAP_ARG_arg2, STAP_RETVALUE + len, MAXSTRINGLEN - len); len = strlen(STAP_RETVALUE); _stp_snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", 0x%lx", (unsigned long)STAP_ARG_arg3); break; #endif // Options that use arg[2-5] default: len = strlen(STAP_RETVALUE); _stp_snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", 0x%lx, 0x%lx, 0x%lx, 0x%lx", (unsigned long)STAP_ARG_arg2, (unsigned long)STAP_ARG_arg3, (unsigned long)STAP_ARG_arg4, (unsigned long)STAP_ARG_arg5); break; } %} %{ // RHEL5 x86_64 (2.6.18-398.el5) has __NR_timerfd_create but no // timerfd.h. #ifdef STAPCONF_TIMERFD_H #include <linux/timerfd.h> #endif static const _stp_val_array _stp_timerfd_flags_list[] = { #ifdef TFD_TIMER_ABSTIME V(TFD_TIMER_ABSTIME), #endif #ifdef TFD_TIMER_CANCEL_ON_SET V(TFD_TIMER_CANCEL_ON_SET), #endif #ifdef TFD_CLOEXEC V(TFD_CLOEXEC), #endif #ifdef TFD_NONBLOCK V(TFD_NONBLOCK), #endif {0, NULL} }; %} function _stp_timerfd_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ _stp_lookup_or_str(_stp_timerfd_flags_list, (unsigned int)STAP_ARG_flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ // RHEL5 linux/pipe_fs_i.h has SPLICE* defs. RHEL6+ has it in // separate linux/splice.h, which does not exist on RHEL5. #include <linux/pipe_fs_i.h> #ifndef SPLICE_F_MOVE #include <linux/splice.h> #endif static const _stp_val_array _stp_splice_flags_list[] = { #ifdef SPLICE_F_MOVE V(SPLICE_F_MOVE), #endif #ifdef SPLICE_F_NONBLOCK V(SPLICE_F_NONBLOCK), #endif #ifdef SPLICE_F_MORE V(SPLICE_F_MORE), #endif #ifdef SPLICE_F_GIFT V(SPLICE_F_GIFT), #endif {0, NULL} }; %} function _stp_splice_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ _stp_lookup_or_str(_stp_splice_flags_list, (unsigned int)STAP_ARG_flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/falloc.h> static const _stp_val_array _stp_fallocate_mode_list[] = { V(FALLOC_FL_KEEP_SIZE), #ifdef FALLOC_FL_PUNCH_HOLE V(FALLOC_FL_PUNCH_HOLE), #endif #ifdef FALLOC_FL_NO_HIDE_STALE V(FALLOC_FL_NO_HIDE_STALE), #endif #ifdef FALLOC_FL_COLLAPSE_RANGE V(FALLOC_FL_COLLAPSE_RANGE), #endif #ifdef FALLOC_FL_ZERO_RANGE V(FALLOC_FL_ZERO_RANGE), #endif {0, NULL} }; %} function _stp_fallocate_mode_str:string(mode:long) %{ /* pure */ /* unprivileged */ _stp_lookup_or_str(_stp_fallocate_mode_list, (unsigned int)STAP_ARG_mode, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #ifdef __NR_arch_prctl #include <asm/prctl.h> #endif static const _stp_val_array _stp_arch_prctl_func_list[] = { #ifdef ARCH_SET_FS V(ARCH_SET_FS), #endif #ifdef ARCH_GET_FS V(ARCH_GET_FS), #endif #ifdef ARCH_SET_GS V(ARCH_SET_GS), #endif #ifdef ARCH_GET_GS V(ARCH_GET_GS), #endif {0, NULL} }; %} function _stp_arch_prctl_func_str:string(func:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str2(_stp_arch_prctl_func_list, (int)STAP_ARG_func, STAP_RETVALUE, MAXSTRINGLEN, 10); %} %{ static const _stp_val_array _stp_adjtimex_modes_list[] = { V(ADJ_OFFSET), V(ADJ_FREQUENCY), V(ADJ_MAXERROR), V(ADJ_ESTERROR), V(ADJ_STATUS), V(ADJ_TIMECONST), V(ADJ_TICK), V(ADJ_OFFSET_SINGLESHOT), {0, NULL} }; %} function _struct_timex_u:string(uaddr:long) %{ /* pure */ struct timex ts; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; int len; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char*)&ts, ptr, sizeof(struct timex)) == 0) { memset(STAP_RETVALUE, 0, MAXSTRINGLEN); STAP_RETVALUE[0] = '{'; _stp_lookup_or_str(_stp_adjtimex_modes_list, (unsigned int)ts.modes, STAP_RETVALUE + 1, MAXSTRINGLEN - 1); len = strlen(STAP_RETVALUE); snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", constant=%lu, esterror=%lu, freq=%lu, maxerror=%lu, offset=%lu, precision=%lu, status=%d, tick=%lu, tolerance=%lu}", ts.constant, ts.esterror, ts.freq, ts.maxerror, ts.offset, ts.precision, ts.status, ts.tick, ts.tolerance); } else { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); } } %} function _struct_compat_timex_u:string(uaddr:long) %{ /* pure */ #ifdef CONFIG_COMPAT struct compat_timex ts; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; int len; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char*)&ts, ptr, sizeof(struct compat_timex)) == 0) { memset(STAP_RETVALUE, 0, MAXSTRINGLEN); STAP_RETVALUE[0] = '{'; _stp_lookup_or_str(_stp_adjtimex_modes_list, (unsigned int)ts.modes, STAP_RETVALUE + 1, MAXSTRINGLEN - 1); len = strlen(STAP_RETVALUE); snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", constant=%u, esterror=%u, freq=%u, maxerror=%u, offset=%u, precision=%u, status=%d, tick=%u, tolerance=%u}", ts.constant, ts.esterror, ts.freq, ts.maxerror, ts.offset, ts.precision, ts.status, ts.tick, ts.tolerance); } else { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); } } #endif %} %{ #include <linux/fs.h> static const _stp_val_array _stp_sync_file_range_list[] = { #ifdef SYNC_FILE_RANGE_WAIT_BEFORE V(SYNC_FILE_RANGE_WAIT_BEFORE), #endif #ifdef SYNC_FILE_RANGE_WRITE V(SYNC_FILE_RANGE_WRITE), #endif #ifdef SYNC_FILE_RANGE_WAIT_AFTER V(SYNC_FILE_RANGE_WAIT_AFTER), #endif {0, NULL} }; %} function _sync_file_range_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ unsigned int flags = (unsigned int)STAP_ARG_flags; _stp_lookup_or_str(_stp_sync_file_range_list, flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <asm/siginfo.h> static const _stp_val_array _stp_siginfo_si_code_list[] = { V(SI_USER), V(SI_KERNEL), V(SI_QUEUE), V(SI_TIMER), V(SI_MESGQ), V(SI_ASYNCIO), V(SI_SIGIO), V(SI_TKILL), V(SI_DETHREAD), {0, NULL} }; /* SIGILL si_codes */ static const _stp_val_array _stp_sigill_si_code_list[] = { V(ILL_ILLOPC), V(ILL_ILLOPN), V(ILL_ILLADR), V(ILL_ILLTRP), V(ILL_PRVOPC), V(ILL_PRVREG), V(ILL_COPROC), V(ILL_BADSTK), {0, NULL} }; /* SIGFPE si_codes */ static const _stp_val_array _stp_sigfpe_si_code_list[] = { V(FPE_INTDIV), V(FPE_INTOVF), V(FPE_FLTDIV), V(FPE_FLTOVF), V(FPE_FLTUND), V(FPE_FLTRES), V(FPE_FLTINV), V(FPE_FLTSUB), {0, NULL} }; /* SIGSEGV si_codes */ static const _stp_val_array _stp_sigsegv_si_code_list[] = { V(SEGV_MAPERR), V(SEGV_ACCERR), #ifdef SEGV_BNDERR V(SEGV_BNDERR), #endif {0, NULL} }; /* SIGBUS si_codes */ static const _stp_val_array _stp_sigbus_si_code_list[] = { V(BUS_ADRALN), V(BUS_ADRERR), V(BUS_OBJERR), #ifdef BUS_MCEERR_AR V(BUS_MCEERR_AR), #endif #ifdef BUS_MCEERR_AO V(BUS_MCEERR_AO), #endif {0, NULL} }; /* SIGTRAP si_codes */ static const _stp_val_array _stp_sigtrap_si_code_list[] = { V(TRAP_BRKPT), V(TRAP_TRACE), #ifdef TRAP_BRANCH V(TRAP_BRANCH), #endif #ifdef TRAP_HWBKPT V(TRAP_HWBKPT), #endif {0, NULL} }; /* SIGCHLD si_codes */ static const _stp_val_array _stp_sigchld_si_code_list[] = { V(CLD_EXITED), V(CLD_KILLED), V(CLD_DUMPED), V(CLD_TRAPPED), V(CLD_STOPPED), V(CLD_CONTINUED), {0, NULL} }; /* SIGPOLL si_codes */ static const _stp_val_array _stp_sigpoll_si_code_list[] = { V(POLL_IN), V(POLL_OUT), V(POLL_MSG), V(POLL_ERR), V(POLL_PRI), V(POLL_HUP), {0, NULL} }; /* SIGSYS si_codes */ static const _stp_val_array _stp_sigsys_si_code_list[] = { #ifdef SYS_SECCOMP V(SYS_SECCOMP), #endif {0, NULL} }; %} function _stp_siginfo_u:string(uaddr:long) %{ /* pure */ siginfo_t sinfo; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; int len; if (ptr == NULL) { strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); return; } if (_stp_copy_from_user((void *)&sinfo, ptr, sizeof(sinfo)) != 0) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); return; } strlcpy(STAP_RETVALUE, "{si_signo=", MAXSTRINGLEN); len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_signal_list, sinfo.si_signo, STAP_RETVALUE + len, MAXSTRINGLEN - len); len = strlen(STAP_RETVALUE); strlcpy(STAP_RETVALUE + len, ", si_code=", MAXSTRINGLEN - len); len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_siginfo_si_code_list, sinfo.si_code, STAP_RETVALUE + len, MAXSTRINGLEN - len); // OK, this is odd. If si_code didn't match anything in // _stp_siginfo_si_code_list, we need to decode si_code based // on the si_signo value. if (*(STAP_RETVALUE + len) == '0') { const _stp_val_array *array = NULL; switch (sinfo.si_signo) { case SIGILL: array = _stp_sigill_si_code_list; break; case SIGFPE: array = _stp_sigfpe_si_code_list; break; case SIGSEGV: array = _stp_sigsegv_si_code_list; break; case SIGBUS: array = _stp_sigbus_si_code_list; break; case SIGTRAP: array = _stp_sigtrap_si_code_list; break; case SIGCHLD: array = _stp_sigchld_si_code_list; break; case SIGPOLL: array = _stp_sigpoll_si_code_list; break; case SIGSYS: array = _stp_sigsys_si_code_list; break; default: // Do nothing. The original si_code lookup // added a hex version. break; } if (array) _stp_lookup_str(array, sinfo.si_code, STAP_RETVALUE + len, MAXSTRINGLEN - len); } len = strlen(STAP_RETVALUE); #ifdef SI_FROMUSER if (SI_FROMUSER(&sinfo)) { switch (sinfo.si_code) { case SI_TIMER: snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", si_tid=%#x, si_overrun=%d", sinfo.si_tid, sinfo.si_overrun); break; default: snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", si_pid=%lu, si_uid=%lu", (unsigned long)sinfo.si_pid, (unsigned long)sinfo.si_uid); break; } } else #endif /* SI_FROMUSER */ { switch (sinfo.si_signo) { case SIGCHLD: snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", si_pid=%lu, si_uid=%lu, si_status=", (unsigned long)sinfo.si_pid, (unsigned long)sinfo.si_uid); len = strlen(STAP_RETVALUE); if (sinfo.si_code == CLD_EXITED) snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, "%d", sinfo.si_status); else _stp_lookup_str(_stp_signal_list, sinfo.si_status, STAP_RETVALUE + len, MAXSTRINGLEN - len); break; case SIGILL: case SIGFPE: case SIGSEGV: case SIGBUS: snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", si_addr=%#lx", (unsigned long)sinfo.si_addr); break; case SIGPOLL: if (sinfo.si_code == POLL_IN || sinfo.si_code == POLL_OUT || sinfo.si_code == POLL_MSG) snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", si_band=%ld", (long)sinfo.si_band); break; #if defined(SIGSYS) && defined(__ARCH_SIGSYS) case SIGSYS: snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", si_call_addr=%#lx, si_syscall=%d, si_arch=%u", (unsigned long)(sinfo.si_call_addr), sinfo.si_syscall, sinfo.si_arch); break; #endif default: if (sinfo.si_pid || sinfo.si_uid) snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", si_pid=%lu, si_uid=%lu", (unsigned long)sinfo.si_pid, (unsigned long)sinfo.si_uid); break; } } len = strlen(STAP_RETVALUE); strlcat(STAP_RETVALUE, "}", MAXSTRINGLEN); %} %{ #ifdef CONFIG_COMPAT #include <linux/compat.h> #if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) #include "linux/compat_structs.h" #endif #endif %} function _stp_compat_siginfo_u:string(uaddr:long) %{ /* pure */ #ifdef CONFIG_COMPAT compat_siginfo_t sinfo; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; int len; if (ptr == NULL) { strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); return; } if (_stp_copy_from_user((void *)&sinfo, ptr, sizeof(sinfo)) != 0) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); return; } strlcpy(STAP_RETVALUE, "{si_signo=", MAXSTRINGLEN); len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_signal_list, sinfo.si_signo, STAP_RETVALUE + len, MAXSTRINGLEN - len); len = strlen(STAP_RETVALUE); strlcpy(STAP_RETVALUE + len, ", si_code=", MAXSTRINGLEN - len); len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_siginfo_si_code_list, sinfo.si_code, STAP_RETVALUE + len, MAXSTRINGLEN - len); // OK, this is odd. If si_code didn't match anything in // _stp_siginfo_si_code_list, we need to decode si_code based // on the si_signo value. if (*(STAP_RETVALUE + len) == '0') { const _stp_val_array *array = NULL; switch (sinfo.si_signo) { case SIGILL: array = _stp_sigill_si_code_list; break; case SIGFPE: array = _stp_sigfpe_si_code_list; break; case SIGSEGV: array = _stp_sigsegv_si_code_list; break; case SIGBUS: array = _stp_sigbus_si_code_list; break; case SIGTRAP: array = _stp_sigtrap_si_code_list; break; case SIGCHLD: array = _stp_sigchld_si_code_list; break; case SIGPOLL: array = _stp_sigpoll_si_code_list; break; case SIGSYS: array = _stp_sigsys_si_code_list; break; default: // Do nothing. The original si_code lookup // added a hex version. break; } if (array) _stp_lookup_str(array, sinfo.si_code, STAP_RETVALUE + len, MAXSTRINGLEN - len); } len = strlen(STAP_RETVALUE); #ifdef SI_FROMUSER if (SI_FROMUSER(&sinfo)) { switch (sinfo.si_code) { case SI_TIMER: snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", si_tid=%#x, si_overrun=%d", sinfo.si_tid, sinfo.si_overrun); break; default: snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", si_pid=%lu, si_uid=%lu", (unsigned long)sinfo.si_pid, (unsigned long)sinfo.si_uid); break; } } else #endif /* SI_FROMUSER */ { switch (sinfo.si_signo) { case SIGCHLD: snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", si_pid=%lu, si_uid=%lu, si_status=", (unsigned long)sinfo.si_pid, (unsigned long)sinfo.si_uid); len = strlen(STAP_RETVALUE); if (sinfo.si_code == CLD_EXITED) snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, "%d", sinfo.si_status); else _stp_lookup_str(_stp_signal_list, sinfo.si_status, STAP_RETVALUE + len, MAXSTRINGLEN - len); break; case SIGILL: case SIGFPE: case SIGSEGV: case SIGBUS: snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", si_addr=%#lx", (unsigned long)sinfo.si_addr); break; case SIGPOLL: if (sinfo.si_code == POLL_IN || sinfo.si_code == POLL_OUT || sinfo.si_code == POLL_MSG) snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", si_band=%ld", (long)sinfo.si_band); break; // Checking for SIGSYS/__ARCH_SIGSYS is fine for the "real" siginfo_t, // but the compat version can be without the SIGSYS fields, so we'll // have to add an arch test. #if defined(SIGSYS) && defined(__ARCH_SIGSYS) \ && !defined(__s390x__) && !defined(__powerpc64__) case SIGSYS: snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", si_call_addr=%#lx, si_syscall=%d, si_arch=%u", (unsigned long)sinfo.si_call_addr, sinfo.si_syscall, sinfo.si_arch); break; #endif default: if (sinfo.si_pid || sinfo.si_uid) snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", si_pid=%lu, si_uid=%lu", (unsigned long)sinfo.si_pid, (unsigned long)sinfo.si_uid); break; } } len = strlen(STAP_RETVALUE); strlcat(STAP_RETVALUE, "}", MAXSTRINGLEN); #endif /* CONFIG_COMPAT */ %} %{ #include <linux/times.h> %} function _struct_tms_u:string(uaddr:long) %{ /* pure */ struct tms tm; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char*)&tm, ptr, sizeof(struct tms)) == 0) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{tms_utime=%lu, tms_stime=%lu, tms_cutime=%lu, tms_cstime=%lu}", tm.tms_utime, tm.tms_stime, tm.tms_cutime, tm.tms_cstime); } else { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); } } %} %{ #include <linux/kernel.h> %} function _struct_sysinfo_u:string(uaddr:long) %{ /* pure */ struct sysinfo si; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char*)&si, ptr, sizeof(struct sysinfo)) == 0) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{uptime=%ld, loads=[%lu, %lu, %lu], totalram=%lu, freeram=%lu, " "sharedram=%lu, bufferram=%lu, totalswap=%lu, freeswap=%lu, procs=%u}", si.uptime, si.loads[0], si.loads[1], si.loads[2], si.totalram, si.freeram, si.sharedram, si.bufferram, si.totalswap, si.freeswap, si.procs); } else { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); } } %} %{ #include <linux/kexec.h> static const _stp_val_array _stp_kexec_flags_list[] = { #if defined(CONFIG_KEXEC) V(KEXEC_ON_CRASH), #ifdef KEXEC_PRESERVE_CONTEXT V(KEXEC_PRESERVE_CONTEXT), #endif V(KEXEC_ARCH_DEFAULT), V(KEXEC_ARCH_386), V(KEXEC_ARCH_X86_64), V(KEXEC_ARCH_PPC), V(KEXEC_ARCH_PPC64), V(KEXEC_ARCH_IA_64), #ifdef KEXEC_ARCH_ARM V(KEXEC_ARCH_ARM), #endif V(KEXEC_ARCH_S390), V(KEXEC_ARCH_SH), #ifdef KEXEC_ARCH_MIPS_LE V(KEXEC_ARCH_MIPS_LE), #endif #ifdef KEXEC_ARCH_MIPS V(KEXEC_ARCH_MIPS), #endif #endif /* CONFIG_KEXEC */ {0, NULL} }; static const _stp_val_array _stp_kexec_file_load_flags_list[] = { #ifdef KEXEC_FILE_UNLOAD V(KEXEC_FILE_UNLOAD), #endif #ifdef KEXEC_FILE_ON_CRASH V(KEXEC_FILE_ON_CRASH), #endif #ifdef KEXEC_FILE_NO_INITRAMFS V(KEXEC_FILE_NO_INITRAMFS), #endif {0, NULL} }; %} function _kexec_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ unsigned long flags = (unsigned long)STAP_ARG_flags; _stp_lookup_or_str(_stp_kexec_flags_list, flags, STAP_RETVALUE, MAXSTRINGLEN); %} function _kexec_file_load_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ unsigned long flags = (unsigned long)STAP_ARG_flags; _stp_lookup_or_str(_stp_kexec_file_load_flags_list, flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #include <linux/signal.h> static const _stp_val_array _stp_sigaltstack_flags_list[] = { V(SS_ONSTACK), V(SS_DISABLE), {0, NULL} }; %} function _stp_sigaltstack_u:string(uaddr:long) %{ /* pure */ stack_t stk; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; int len; if (ptr == NULL || _stp_copy_from_user((void *)&stk, ptr, sizeof(stk)) != 0) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); return; } snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{ss_sp=0x%lx, ss_flags=", (unsigned long)stk.ss_sp); len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_sigaltstack_flags_list, stk.ss_flags, STAP_RETVALUE + len, MAXSTRINGLEN - len); len = strlen(STAP_RETVALUE); snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", ss_size=%lu}", (unsigned long)stk.ss_size); %} function _stp_compat_sigaltstack_u:string(uaddr:long) %{ /* pure */ #ifdef CONFIG_COMPAT #if defined(CONFIG_GENERIC_SIGALTSTACK) \ || LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) compat_stack_t stk; #elif defined(__x86_64__) stack_ia32_t stk; #elif defined(__s390x__) stack_t32 stk; #elif defined(__powerpc64__) stack_32_t stk; #endif char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; int len; if (ptr == NULL || _stp_copy_from_user((void *)&stk, ptr, sizeof(stk)) != 0) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); return; } snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{ss_sp=0x%lx, ss_flags=", (unsigned long)stk.ss_sp); len = strlen(STAP_RETVALUE); _stp_lookup_str(_stp_sigaltstack_flags_list, stk.ss_flags, STAP_RETVALUE + len, MAXSTRINGLEN - len); len = strlen(STAP_RETVALUE); snprintf(STAP_RETVALUE + len, MAXSTRINGLEN - len, ", ss_size=%lu}", (unsigned long)stk.ss_size); #endif %} %{ #include <linux/fs.h> static const _stp_val_array _stp_renameat2_flags_list[] = { #ifdef RENAME_NOREPLACE V(RENAME_NOREPLACE), #endif #ifdef RENAME_EXCHANGE V(RENAME_EXCHANGE), #endif #ifdef RENAME_WHITEOUT V(RENAME_WHITEOUT), #endif {0, NULL} }; %} function _renameat2_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ unsigned int flags = (unsigned int)STAP_ARG_flags; _stp_lookup_or_str(_stp_renameat2_flags_list, flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ // fanotify_init() and fanotify_mark() were enabled in kernel version // 2.6.37 (but present in some earlier kernels). #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) \ && defined(__NR_fanotify_init) && defined(__NR_fanotify_mark) #include <linux/fanotify.h> static const _stp_val_array _stp_fanotify_init_class_flags_list[] = { V(FAN_CLASS_NOTIF), V(FAN_CLASS_CONTENT), V(FAN_CLASS_PRE_CONTENT), {0, NULL} }; static const _stp_val_array _stp_fanotify_init_extra_flags_list[] = { V(FAN_CLOEXEC), V(FAN_NONBLOCK), V(FAN_UNLIMITED_QUEUE), V(FAN_UNLIMITED_MARKS), {0, NULL} }; static const _stp_val_array _stp_fanotify_mark_flags_list[] = { V(FAN_MARK_ADD), V(FAN_MARK_REMOVE), V(FAN_MARK_FLUSH), V(FAN_MARK_DONT_FOLLOW), V(FAN_MARK_ONLYDIR), V(FAN_MARK_MOUNT), V(FAN_MARK_IGNORED_MASK), V(FAN_MARK_IGNORED_SURV_MODIFY), {0, NULL} }; /* Note that FAN_CLOSE is (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE). So, * we really can't use it. */ static const _stp_val_array _stp_fanotify_mark_mask_list[] = { V(FAN_ACCESS), V(FAN_MODIFY), V(FAN_CLOSE_WRITE), V(FAN_CLOSE_NOWRITE), V(FAN_OPEN), V(FAN_Q_OVERFLOW), V(FAN_OPEN_PERM), V(FAN_ACCESS_PERM), V(FAN_ONDIR), V(FAN_EVENT_ON_CHILD), {0, NULL} }; #endif %} function _fanotify_init_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) \ && defined(__NR_fanotify_init) && defined(__NR_fanotify_mark) unsigned int flags = (unsigned int)STAP_ARG_flags; unsigned int flags_part1 = flags & FAN_ALL_CLASS_BITS; unsigned int flags_part2 = flags & ~FAN_ALL_CLASS_BITS; _stp_lookup_str(_stp_fanotify_init_class_flags_list, flags_part1, STAP_RETVALUE, MAXSTRINGLEN); if (flags_part2) { strlcat(STAP_RETVALUE, "|", MAXSTRINGLEN); _stp_lookup_or_str(_stp_fanotify_init_extra_flags_list, flags_part2, STAP_RETVALUE, MAXSTRINGLEN); } #endif %} function _fanotify_mark_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) \ && defined(__NR_fanotify_init) && defined(__NR_fanotify_mark) unsigned int flags = (unsigned int)STAP_ARG_flags; _stp_lookup_or_str(_stp_fanotify_mark_flags_list, flags, STAP_RETVALUE, MAXSTRINGLEN); #endif %} function _fanotify_mark_mask_str:string(mask:long) %{ /* pure */ /* unprivileged */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) \ && defined(__NR_fanotify_init) && defined(__NR_fanotify_mark) __u64 mask = (__u64)STAP_ARG_mask; _stp_lookup_or_str(_stp_fanotify_mark_mask_list, mask, STAP_RETVALUE, MAXSTRINGLEN); #endif %} %{ #if defined(__NR_perf_event_open) && defined(CONFIG_PERF_EVENTS) #include <linux/perf_event.h> static const _stp_val_array _stp_perf_event_open_flags_list[] = { V(PERF_FLAG_FD_NO_GROUP), V(PERF_FLAG_FD_OUTPUT), #ifdef PERF_FLAG_PID_CGROUP V(PERF_FLAG_PID_CGROUP), #endif #ifdef PERF_FLAG_FD_CLOEXEC V(PERF_FLAG_FD_CLOEXEC), #endif {0, NULL} }; #endif %} function _perf_event_open_flags_str:string(flags:long) %{ /* pure */ /* unprivileged */ #if defined(__NR_perf_event_open) && defined(CONFIG_PERF_EVENTS) unsigned long flags = (unsigned long)STAP_ARG_flags; _stp_lookup_or_str(_stp_perf_event_open_flags_list, flags, STAP_RETVALUE, MAXSTRINGLEN); #endif %} %{ #ifdef CONFIG_CHECKPOINT_RESTORE #include <linux/kcmp.h> #endif static const _stp_val_array _stp_kcmp_type_list[] = { #ifdef CONFIG_CHECKPOINT_RESTORE V(KCMP_FILE), V(KCMP_VM), V(KCMP_FILES), V(KCMP_FS), V(KCMP_SIGHAND), V(KCMP_IO), V(KCMP_SYSVSEM), V(KCMP_TYPES), #endif {0, NULL} }; %} function _kcmp_type_str:string(type:long) %{ /* pure */ /* unprivileged */ unsigned long type = (unsigned long)STAP_ARG_type; _stp_lookup_str(_stp_kcmp_type_list, (unsigned int)STAP_ARG_type, STAP_RETVALUE, MAXSTRINGLEN); %} function _struct_sched_attr_u:string(uaddr:long) %{ /* pure */ /* struct sched_attr introduced in kernel commit d50dde5a10 along with SCHED_ATTR_SIZE_VER0 */ #ifdef SCHED_ATTR_SIZE_VER0 struct sched_attr sa; char *ptr = (char *)(uintptr_t)STAP_ARG_uaddr; if (ptr == NULL) strlcpy(STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char*)&sa, ptr, sizeof(struct sched_attr)) == 0) { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{size=%u, sched_policy=%u, sched_flags=%llu, " "sched_nice=%d, sched_priority=%u, sched_runtime=%llu, " "sched_deadline=%llu, sched_period=%llu}", sa.size, sa.sched_policy, sa.sched_flags, sa.sched_nice, sa.sched_priority, sa.sched_runtime, sa.sched_deadline, sa.sched_period); } else { snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", (unsigned long)ptr); } } #endif %} %{ #ifdef CONFIG_SECCOMP #include <linux/seccomp.h> #endif static const _stp_val_array _stp_seccomp_op_list[] = { #ifdef SECCOMP_SET_MODE_STRICT V(SECCOMP_SET_MODE_STRICT), #endif #ifdef SECCOMP_SET_MODE_FILTER V(SECCOMP_SET_MODE_FILTER), #endif {0, NULL} }; %} function _seccomp_op_str:string(op:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_seccomp_op_list, (unsigned int)STAP_ARG_op, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #ifdef CONFIG_BPF_SYSCALL #include <uapi/linux/bpf.h> #endif static const _stp_val_array _stp_bpf_cmd_list[] = { #ifdef CONFIG_BPF_SYSCALL V(BPF_MAP_CREATE), V(BPF_MAP_LOOKUP_ELEM), V(BPF_MAP_UPDATE_ELEM), V(BPF_MAP_DELETE_ELEM), V(BPF_MAP_GET_NEXT_KEY), V(BPF_PROG_LOAD), #endif {0, NULL} }; %} function _bpf_cmd_str:string(cmd:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_bpf_cmd_list, (int)STAP_ARG_cmd, STAP_RETVALUE, MAXSTRINGLEN); %} %{ #ifdef CONFIG_MEMBARRIER #include <linux/membarrier.h> #endif static const _stp_val_array _stp_membarrier_cmd_list[] = { #ifdef CONFIG_MEMBARRIER V(MEMBARRIER_CMD_QUERY), V(MEMBARRIER_CMD_SHARED), #endif {0, NULL} }; %} function _membarrier_cmd_str:string(cmd:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_membarrier_cmd_list, (unsigned int)STAP_ARG_cmd, STAP_RETVALUE, MAXSTRINGLEN); %} %{ static const _stp_val_array _stp_userfaultfd_flags_list[] = { #ifdef O_NONBLOCK V(O_NONBLOCK), #endif #ifdef O_CLOEXEC V(O_CLOEXEC), #endif {0, NULL} }; %} function _userfaultfd_flags_str:string (f:long) %{ /* pure */ /* unprivileged */ unsigned int flags = (unsigned int)STAP_ARG_f; _stp_lookup_or_str(_stp_userfaultfd_flags_list, flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ static const _stp_val_array _stp_preadv2_flags_list[] = { #ifdef RWF_HIPRI V(RWF_HIPRI), #endif {0, NULL} }; %} function _preadv2_flags_str:string (f:long) %{ /* pure */ /* unprivileged */ unsigned int flags = (unsigned int)STAP_ARG_f; _stp_lookup_or_str(_stp_preadv2_flags_list, flags, STAP_RETVALUE, MAXSTRINGLEN); %} %{ static const _stp_val_array _stp_statx_mask_list[] = { #ifdef AT_STATX_SYNC_TYPE V(AT_STATX_SYNC_TYPE), V(AT_STATX_SYNC_AS_STAT), V(AT_STATX_FORCE_SYNC), V(AT_STATX_DONT_SYNC), #endif {0, NULL} }; %} function _statx_mask_str:string(cmd:long) %{ /* pure */ /* unprivileged */ _stp_lookup_str(_stp_statx_mask_list, (int)STAP_ARG_cmd, STAP_RETVALUE, MAXSTRINGLEN); %} /* Some syscall interjection mechanisms give us a pt_regs* structure for the syscall parameters/context. */ function __set_syscall_pt_regs(r) %{ /* guru */ CONTEXT->sregs = (void*)(uintptr_t) STAP_ARG_r; %} function _stp_syscall_nr:long () %{ /* pure */ if (CONTEXT->sregs) { /* NB: same abi? */ STAP_RETVALUE = _stp_syscall_get_nr(current, CONTEXT->sregs); } else { struct pt_regs *regs = _stp_current_pt_regs(); if (!regs) { CONTEXT->last_error = ("Cannot access syscall number" " (no registers available)"); return; } STAP_RETVALUE = _stp_syscall_get_nr(current, regs); } %}