// context tapset
// Copyright (C) 2005-2009 Red Hat Inc.
// Copyright (C) 2006 Intel Corporation.
//
// This file is part of systemtap, and is free software. You can
// redistribute it and/or modify it under the terms of the GNU General
// Public License (GPL); either version 2, or (at your option) any
// later version.
//
// Context functions provide additional information about where an event occurred. These functions can
//provide information such as a backtrace to where the event occurred and the current register values for the
//processor.
//
%{
#include
#if defined(__powerpc__)
#if !defined(task_pt_regs)
#define task_pt_regs(tsk) ((struct pt_regs *)(tsk)->thread.regs)
#endif
#endif
%}
/**
* sfunction print_regs - Print a register dump.
*/
function print_regs () %{
if (CONTEXT->regs) {
_stp_print_regs (CONTEXT->regs);
}
%}
/**
* sfunction execname - Returns the execname of a target process (or group of processes).
*/
function execname:string () %{ /* pure */ /* unprivileged */
strlcpy (THIS->__retvalue, current->comm, MAXSTRINGLEN);
%}
/**
* sfunction pid - Returns the ID of a target process.
*/
function pid:long () %{ /* pure */ /* unprivileged */
THIS->__retvalue = current->tgid;
%}
/**
* sfunction tid - Returns the thread ID of a target process.
*/
function tid:long () %{ /* pure */ /* unprivileged */
THIS->__retvalue = current->pid;
%}
/**
* sfunction ppid - Returns the process ID of a target process's parent process.
*/
function ppid:long () %{ /* pure */ /* unprivileged */
#if defined(STAPCONF_REAL_PARENT)
THIS->__retvalue = current->real_parent->tgid;
#else
THIS->__retvalue = current->parent->tgid;
#endif
%}
/**
* sfunction pgrp - Returns the process group ID of the current process.
*/
function pgrp:long () %{ /* pure */ /* unprivileged */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
struct signal_struct *ss = kread( &(current->signal) );
THIS->__retvalue = kread ( &(ss->pgrp) );
CATCH_DEREF_FAULT();
#else
THIS->__retvalue = task_pgrp_nr_ns(current, &init_pid_ns);
#endif
%}
/**
* sfunction sid - Returns the session ID of the current process.
*
* The session ID of a process is the process group ID of the session
* leader. Session ID is stored in the signal_struct since Kernel 2.6.0.
*/
function sid:long () %{ /* pure */ /* unprivileged */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
struct signal_struct *ss = kread( &(current->signal) );
THIS->__retvalue = kread ( &(ss->session) );
CATCH_DEREF_FAULT();
#else
THIS->__retvalue = task_session_nr_ns(current, &init_pid_ns);
#endif
%}
/**
* sfunction pexecname - Returns the execname of a target process's parent process.
*/
function pexecname:string () %{ /* pure */ /* unprivileged */
#if defined(STAPCONF_REAL_PARENT)
strlcpy (THIS->__retvalue, current->real_parent->comm, MAXSTRINGLEN);
#else
strlcpy (THIS->__retvalue, current->parent->comm, MAXSTRINGLEN);
#endif
%}
/**
* sfunction gid - Returns the group ID of a target process.
*/
function gid:long () %{ /* pure */ /* unprivileged */
#ifdef STAPCONF_TASK_UID
THIS->__retvalue = current->gid;
#else
THIS->__retvalue = current_gid();
#endif
%}
/**
* sfunction egid - Returns the effective gid of a target process.
*/
function egid:long () %{ /* pure */ /* unprivileged */
#ifdef STAPCONF_TASK_UID
THIS->__retvalue = current->egid;
#else
THIS->__retvalue = current_egid();
#endif
%}
/**
* sfunction uid - Returns the user ID of a target process.
*/
function uid:long () %{ /* pure */ /* unprivileged */
#ifdef STAPCONF_TASK_UID
THIS->__retvalue = current->uid;
#else
THIS->__retvalue = current_uid();
#endif
%}
/**
* sfunction euid - Return the effective uid of a target process.
*/
function euid:long () %{ /* pure */ /* unprivileged */
#ifdef STAPCONF_TASK_UID
THIS->__retvalue = current->euid;
#else
THIS->__retvalue = current_euid();
#endif
%}
/**
* sfunction is_myproc - Determines if the current probe point has occurred in the user's own process.
*
* Return 1 if the current probe point has occurred in the user's own process.
*/
function is_myproc:long () %{ /* pure */ /* unprivileged */
THIS->__retvalue = is_myproc();
%}
// cpuid() is not documented
function cpuid:long () %{ /* pure */
THIS->__retvalue = smp_processor_id();
%}
/**
* sfunction cpu - Returns the current cpu number.
*/
function cpu:long () %{ /* pure */ /* unprivileged */
THIS->__retvalue = smp_processor_id();
%}
/**
* sfunction pp - Return the probe point associated with the currently running probe handler,
* including alias and wildcard expansion effects
* Context:
* The current probe point.
*/
function pp:string () %{ /* pure */ /* unprivileged */
strlcpy (THIS->__retvalue, CONTEXT->probe_point, MAXSTRINGLEN);
%}
/**
* sfunction registers_valid - Determines validity of register() and u_register() in current context.
*
* Return 1 if register() and u_register() can be used
* in the current context, or 0 otherwise.
* For example, registers_valid() returns 0
* when called from a begin or end probe.
*/
function registers_valid:long () %{ /* pure */ /* unprivileged */
THIS->__retvalue = (CONTEXT->regs != NULL);
%}
/**
* sfunction user_mode - Determines if probe point occurs in user-mode.
*
* Return 1 if the probe point occurred in user-mode.
*/
function user_mode:long () %{ /* pure */ /* unprivileged */
if (CONTEXT->regs) {
#if defined(__i386__) || defined(__x86_64__)
THIS->__retvalue = (uint64_t) user_mode_vm (CONTEXT->regs);
#else
THIS->__retvalue = (uint64_t) user_mode (CONTEXT->regs);
#endif
} else {
THIS->__retvalue = 0;
}
%}
/**
* sfunction is_return - Whether the current probe context is a return probe.
*
* Description: Returns 1 if the current probe context is a return probe,
* returns 0 otherwise.
*/
function is_return:long () %{ /* pure */
if (CONTEXT->pi)
THIS->__retvalue = 1;
else
THIS->__retvalue = 0;
%}
/**
* sfunction target - Return the process ID of the target process.
*/
function target:long () %{ /* pure */ /* unprivileged */
THIS->__retvalue = _stp_target;
%}
/**
* sfunction module_name - The module name of the current script.
*
* Returns the name of the stap module. Either generated randomly
* (stap_[0-9a-f]+_[0-9a-f]+) or set by stap -m .
*/
function module_name:string () %{ /* pure */ /* unprivileged */
strlcpy(THIS->__retvalue, THIS_MODULE->name, MAXSTRINGLEN);
%}
/**
* sfunction stp_pid - The process id of the stapio process.
*
* Returns the process id of the stapio process that launched
* this script.
*/
function stp_pid:long () %{ /* pure */
THIS->__retvalue = _stp_pid;
%}
/**
* sfunction stack_size - Return the size of the kernel stack.
*/
function stack_size:long () %{ /* pure */
THIS->__retvalue = THREAD_SIZE;
%}
/**
* sfunction stack_used - Returns the amount of kernel stack used.
*
* Determines how many bytes are currently used in the kernel stack.
*/
function stack_used:long () %{ /* pure */
char a;
THIS->__retvalue = THREAD_SIZE - ((long)&a & (THREAD_SIZE-1));
%}
/**
* sfunction stack_unused - Returns the amount of kernel stack currently available.
*
* Determines how many bytes are currently available in the kernel stack.
*/
function stack_unused:long () %{ /* pure */
char a;
THIS->__retvalue = (long)&a & (THREAD_SIZE-1);
%}
/**
* sfunction uaddr - User space address of current running task. EXPERIMENTAL.
*
* Description: Returns the address in userspace that the current
* task was at when the probe occurred. When the current running task
* isn't a user space thread, or the address cannot be found, zero
* is returned. Can be used to see where the current task is combined
* with usymname() or symdata(). Often the task will be in the VDSO
* where it entered the kernel. FIXME - need VDSO tracking support #10080.
*/
function uaddr:long () %{ /* pure */ /* unprivileged */
int64_t addr = 0;
assert_is_myproc();
if (current->mm)
{
struct pt_regs *uregs;
uregs = task_pt_regs(current);
if (uregs)
addr = (int64_t) REG_IP(uregs);
}
THIS->__retvalue = addr;
%}
/**
* sfunction cmdline_args - Fetch command line arguments from current process
*
* @n: First argument to get (zero is the command itself)
* @m: Last argument to get (or minus one for all arguments after n)
* @delim: String to use to delimit arguments when more than one.
*
* Description: Returns arguments from the current process starting
* with argument number n, up to argument m. If there are less than n
* arguments, or the arguments cannot be retrieved from the current
* process, the empty string is returned. If m is smaller than n then
* all arguments starting from argument n are returned. Argument zero
* is traditionally the command itself.
*/
function cmdline_args:string(n:long, m:long, delim:string)
{
args = "";
mm = @cast(task_current(), "task_struct", "kernel")->mm;
if (mm)
{
arg_start = @cast(mm, "mm_struct", "kernel")->arg_start;
arg_end = @cast(mm, "mm_struct", "kernel")->arg_end;
if (arg_start != 0 && arg_end != 0)
{
nr = 0;
len = arg_end - arg_start;
arg = user_string2(arg_start, "");
while (arg != "" && len > 0)
{
if (nr == n)
args = arg;
else if (nr > n)
args .= delim . arg;
arg_len = strlen(arg);
arg_start += arg_len + 1;
len -= arg_len + 1;
if (len > 0 && nr != m)
arg = user_string2(arg_start, "");
else
arg = "";
nr++;
}
}
}
return args;
}
/**
* sfunction cmdline_arg - Fetch a command line argument.
*
* @n: Argument to get (zero is the command itself)
*
* Description: Returns argument the requested argument from the
* current process or the empty string when there are not that many
* arguments or there is a problem retrieving the argument. Argument
* zero is traditionally the command itself.
*/
function cmdline_arg:string(n:long)
{
return cmdline_args(n, n, "");
}
/**
* sfunction cmdline_str - Fetch all command line arguments from current process
*
* Description: Returns all arguments from the current process
* delimited by spaces. Returns the empty string when the arguments
* cannot be retrieved.
*/
function cmdline_str:string()
{
return cmdline_args(0, -1, " ");
}