Sindbad~EG File Manager
%{
// 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
/* deprecation: struct compat_*time* aliases moved to this header */
#if defined(STAPCONF_TIME32_H)
#include <linux/time32.h>
/* further deprecation: struct compat_*time* aliases renamed to old_*time* */
#elif defined(STAPCONF_TIME32_OLD_H)
#include <linux/time32.h>
#define compat_time_t old_time32_t
#define compat_timeval old_timeval32
#define timeval old_timeval32
#define compat_timespec old_timespec32
#define timespec old_timespec32
#define compat_itimerspec old_itimerspec32
#define itimerspec old_itimerspec32
#define ns_to_compat_timeval ns_to_old_timeval32
#define get_compat_itimerspec64 get_old_itimerspec32
#define put_compat_itimerspec64 put_old_itimerspec32
#define compat_get_timespec64 get_old_timespec32
#define compat_put_timespec64 put_old_timespec32
/* in kernel/time/itimer.c */
struct old_itimerval32 {
struct old_timeval32 it_interval;
struct old_timeval32 it_value;
};
#define compat_itimerval old_itimerval32
#define itimerval old_itimerval32
#define timex old_timex32
#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 );
fallthrough;
case 3: set->sig[2] = compat->sig[4] | (((long)compat->sig[5]) << 32 );
fallthrough;
case 2: set->sig[1] = compat->sig[2] | (((long)compat->sig[3]) << 32 );
fallthrough;
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[2]; /* maximum enforced below */
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]",
(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);
}
%}
function _struct_compat_timeval_u:string(uaddr:long, n:long)
%{ /* pure */
#ifdef CONFIG_COMPAT
int n = (int)STAP_ARG_n;
struct compat_timeval tv[2]; /* maximum enforced below */
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
#if defined(STAPCONF_COMPAT_UTIMBUF)
struct compat_utimbuf ubuf;
#else
struct old_utimbuf32 ubuf;
#endif
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
#if defined(STAPCONF_COMPAT_UTIMBUF)
struct compat_utimbuf ubuf;
#else
struct old_utimbuf32 ubuf;
#endif
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[2]; /* maximum enforced below */
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,
(long)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[2]; /* maximum, enforced below */
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);
%}
%{
static const _stp_val_array _stp_faccessat2_flags_list[] = {
{0x100, "AT_SYMLINK_NOFOLLOW"},
{0x200, "AT_EACCESS"},
{0, NULL}
};
%}
function _faccessat2_flags_str:string(flags:long)
%{ /* pure */ /* unprivileged */
unsigned int flags = (unsigned int)STAP_ARG_flags;
_stp_lookup_or_str(_stp_faccessat2_flags_list, flags, 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
#ifdef O_CLOEXEC
V(O_CLOEXEC),
#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);
%}
%{
#ifdef STAPCONF_UAPI_LINUX_MOUNT_H
#include <uapi/linux/mount.h>
#endif
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),
#ifdef SO_RCVTIMEO
V(SO_RCVTIMEO),
#endif
#ifdef SO_SNDTIMEO
V(SO_SNDTIMEO),
#endif
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),
#ifdef SO_TIMESTAMP
V(SO_TIMESTAMP),
#endif
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
#ifdef SO_INCOMING_CPU
V(SO_INCOMING_CPU),
#endif
#ifdef SO_ATTACH_BPF
V(SO_ATTACH_BPF),
#endif
#ifdef SO_DETACH_BPF
V(SO_DETACH_BPF),
#endif
#ifdef SO_ATTACH_REUSEPORT_CBPF
V(SO_ATTACH_REUSEPORT_CBPF),
#endif
#ifdef SO_ATTACH_REUSEPORT_EBPF
V(SO_ATTACH_REUSEPORT_EBPF),
#endif
#ifdef SO_CNX_ADVICE
V(SO_CNX_ADVICE),
#endif
#ifdef SCM_TIMESTAMPING_OPT_STATS
V(SCM_TIMESTAMPING_OPT_STATS),
#endif
#ifdef SO_MEMINFO
V(SO_MEMINFO),
#endif
#ifdef SO_INCOMING_NAPI_ID
V(SO_INCOMING_NAPI_ID),
#endif
#ifdef SO_COOKIE
V(SO_COOKIE),
#endif
#ifdef SCM_TIMESTAMPING_PKTINFO
V(SCM_TIMESTAMPING_PKTINFO),
#endif
#ifdef SO_PEERGROUPS
V(SO_PEERGROUPS),
#endif
#ifdef SO_ZEROCOPY
V(SO_ZEROCOPY),
#endif
#ifdef SO_TXTIME
V(SO_TXTIME),
#endif
#ifdef SCM_TXTIME
V(SCM_TXTIME),
#endif
#ifdef SO_BINDTOIFINDEX
V(SO_BINDTOIFINDEX),
#endif
#ifdef SO_TIMESTAMP_OLD
V(SO_TIMESTAMP_OLD),
#endif
#ifdef SO_TIMESTAMPNS_OLD
V(SO_TIMESTAMPNS_OLD),
#endif
#ifdef SO_TIMESTAMPING_OLD
V(SO_TIMESTAMPING_OLD),
#endif
#ifdef SO_TIMESTAMP_NEW
V(SO_TIMESTAMP_NEW),
#endif
#ifdef SO_TIMESTAMPNS_NEW
V(SO_TIMESTAMPNS_NEW),
#endif
#ifdef SO_TIMESTAMPING_NEW
V(SO_TIMESTAMPING_NEW),
#endif
#ifdef SO_RCVTIMEO_NEW
V(SO_RCVTIMEO_NEW),
#endif
#ifdef SO_SNDTIMEO_NEW
V(SO_SNDTIMEO_NEW),
#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__) && !defined(__riscv)
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);
fallthrough;
case 3: act.sa_mask.sig[2] = act32.sa_mask.sig[4]
| (((long)act32.sa_mask.sig[5]) << 32);
fallthrough;
case 2: act.sa_mask.sig[1] = act32.sa_mask.sig[2]
| (((long)act32.sa_mask.sig[3]) << 32);
fallthrough;
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}",
(long)ts.constant, (long)ts.esterror, (long)ts.freq, (long)ts.maxerror, (long)ts.offset, (long)ts.precision, ts.status, (long)ts.tick, (long)ts.tolerance);
}
else
{
snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx",
(unsigned long)ptr);
}
}
%}
function _struct_compat_timex_u:string(uaddr:long)
%{ /* pure */
#if defined(CONFIG_COMPAT)
#if defined(CONFIG_COMPAT_32BIT_TIME) && (LINUX_VERSION_CODE >= KERNEL_VERSION(5,1,0))
#define compat_timex old_timex32
#endif
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);
}
}
#if defined(CONFIG_COMPAT_32BIT_TIME) && (LINUX_VERSION_CODE >= KERNEL_VERSION(5,1,0))
#undef compat_timex
#endif
#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;
/* deprecation: linux commit 23c9deeb3285d */
#ifndef FAN_ALL_CLASS_BITS
#define FAN_ALL_CLASS_BITS (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | FAN_CLASS_PRE_CONTENT)
#endif
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);
%}
function _pkey_alloc_init_val_str:string(init_val:long)
%{ /* pure */ /* unprivileged */
static const _stp_val_array pkey_alloc_init_val_list[] = {
V(PKEY_DISABLE_ACCESS),
V(PKEY_DISABLE_WRITE),
{0, NULL}
};
_stp_lookup_or_str(pkey_alloc_init_val_list, (unsigned int)STAP_ARG_init_val,
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);
}
%}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists