// context tapset
// Copyright (C) 2012 Red Hat, Inc.
//
// This file is part of systemtap, and is free software.  You can
// redistribute it and/or modify it under the terms of the GNU General
// Public License (GPL); either version 2, or (at your option) any
// later version.

// NB: functionally equivalent to linux/context.stp

%{
#include <sched.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
%}

global _stp_dyninst_remote = ""

function execname:string ()
%{
	/* Need a 16-byte buffer, which will be 0-terminated only if shorter.
	 * Use 17 bytes to make sure we always have termination.  */
	char arg2[17] = {0};
	if (prctl(PR_GET_NAME, (unsigned long)arg2, 0, 0, 0) == 0)
		strlcpy (STAP_RETVALUE, arg2, MAXSTRINGLEN);
%}

function pid:long ()
%{ /* pure */ /* unprivileged */
	STAP_RETVALUE = getpid();
%}

function tid:long ()
%{ /* pure */ /* unprivileged */
        /* NB: no glibc wrapper available */
	STAP_RETVALUE = syscall(SYS_gettid);
%}

function ppid:long()
%{ /* pure */ /* unprivileged */
	STAP_RETVALUE = getppid();
%}

function pgrp:long ()
%{ /* pure */ /* unprivileged */
	STAP_RETVALUE = getpgrp();
%}

function sid:long ()
%{ /* pure */ /* unprivileged */
	STAP_RETVALUE = getsid(0);
%}

// TODO function pexecname:string ()

function gid:long ()
%{ /* pure */ /* unprivileged */
	STAP_RETVALUE = getgid();
%}

function egid:long ()
%{ /* pure */ /* unprivileged */
	STAP_RETVALUE = getegid();
%}

function uid:long ()
%{ /* pure */ /* unprivileged */
	STAP_RETVALUE = getuid();
%}

function euid:long ()
%{ /* pure */ /* unprivileged */
	STAP_RETVALUE = geteuid();
%}


// TODO function is_myproc:long ()
// NB: dyninst by nature is myproc-only, *except if you're root*

function cpu:long ()
%{ /* pure */ /* unprivileged */
	STAP_RETVALUE = _stp_sched_getcpu();
%}


function registers_valid:long ()
%{ /* pure */ /* unprivileged */
	STAP_RETVALUE = (CONTEXT->uregs != NULL);
%}

function user_mode:long ()
{
	return 1;
}

function is_return:long ()
%{ /* pure */ /* unprivileged */
	if (CONTEXT->probe_type == stp_probe_type_uretprobe)
		STAP_RETVALUE = 1;
	else
		STAP_RETVALUE = 0;
%}

function target:long ()
%{ /* pure */ /* unprivileged */
	STAP_RETVALUE = stp_session_attributes()->target;
%}

function module_name:string ()
%{ /* pure */ /* unprivileged */
	strlcpy(STAP_RETVALUE, stp_session_attributes()->module_name, MAXSTRINGLEN);
%}

function stp_pid:long ()
%{ /* pure */ /* unprivileged */
	STAP_RETVALUE = stp_session_attributes()->stp_pid;
%}

function remote_id:long ()
{
	return strtol(substr(_stp_dyninst_remote,0,1), 10)
}

function remote_uri:string ()
{
        return substr(_stp_dyninst_remote, 2, %{ STP_REMOTE_URI_LEN %})
}

// TODO function stack_size:long ()

// TODO function stack_used:long ()

// TODO function stack_unused:long ()

function addr:long ()
{
	return uaddr()
}

function uaddr:long ()
%{ /* pure */ /* unprivileged */
	STAP_RETVALUE = (intptr_t)(CONTEXT->uregs ? REG_IP(CONTEXT->uregs) : 0);
%}

// TODO function cmdline_args:string(n:long, m:long, delim:string)

// TODO function cmdline_arg:string(n:long)

// TODO function cmdline_str:string()
