// context tapset
// Copyright (C) 2016-2021 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.

/**
 * sfunction execname - Returns the execname of a target process (or group of processes)
 *
 * Description: Returns the execname of a target process (or group of processes).
 */
function execname:string ()
%{ /* bpf */ /* pure */ /* unprivileged */ /* stable */
  /* buf = bpf_stk_alloc(BPF_MAXSTRINGLEN);
     buf[0] = 0x0; // guarantee NUL byte
     rc = get_current_comm(buf, BPF_MAXSTRINGLEN); */
  alloc, $buf, BPF_MAXSTRINGLEN;
  0x62, $buf, -, -, 0x0; /* stw [$buf+0], 0x0 -- guarantee NUL byte */
  call, $rc, get_current_comm, $buf, BPF_MAXSTRINGLEN;

  /* if (rc < 0) return err_msg;
     return buf; */
  0xc5, $rc, -, _err, 0; /* jslt $rc, 0, _err */
  0xbf, $$, $buf, -, -; /* mov $$, $buf */
  0x05, -, -, _done, -; /* ja _done */

  label, _err;
  0xbf, $$, "<unknown>", -, -; /* mov $$, <unknown> */

  label, _done;
%}

// TODO: pexecname ()

/**
 * sfunction pid - Returns the ID of a thread group
 * 
 * Description: This function returns the userspace pid / kernel tgid
 * of a target process.
 */
function pid:long ()
%{ /* bpf */ /* pure */ /* unprivileged */ /* stable */
   /* BPF_FUNC_get_current_pid_tgid returns tgid << 32 | pid */
   0x85, 0, 0, 0, 14;   /* call BPF_FUNC_get_current_pid_tgid */
   0xbf, $$, 0, 0, 0;   /* movx $$, r0 */
   0x77, $$, 0, 0, 32   /* rshk $$, 32 */
%}

// TODO: ns_pid:long ()

/**
 * sfunction tid - Returns the thread ID of a target process
 * 
 * Description: This function returns the userspace tid / kernel pid
 * of a target process.
 */
function tid:long ()
%{ /* bpf */ /* pure */ /* unprivileged */ /* stable */
   /* BPF_FUNC_get_current_pid_tgid returns tgid << 32 | pid */
   0x85, 0, 0, 0, 14;   /* call BPF_FUNC_get_current_pid_tgid */
   0xbc, $$, 0, 0, 0    /* movwx $$, r0 */
%}

// TODO: ns_tid:long ()
// TODO: ppid:long ()
// TODO: ns_ppid:long ()
// TODO: pgrp:long ()
// TODO: ns_pgrp:long ()
// TODO: sid:long ()
// TODO: ns_sid:long ()

/**
 * sfunction gid - Returns the group ID of a target process
 * 
 * Description: This function returns the group ID of a target process.
 */
function gid:long ()
%{ /* bpf */ /* pure */ /* unprivileged */ /* stable */
   /* BPF_FUNC_get_current_uid_gid returns gid << 32 | uid */
   0x85, 0, 0, 0, 15;	/* call BPF_FUNC_get_current_uid_gid */
   0xbf, $$, 0, 0, 0;   /* movx $$, r0 */
   0x77, $$, 0, 0, 32	/* rshk $$, 32 */
%}

// TODO: ns_gid:long ()
// TODO: egid:long ()
// TODO: ns_egid:long ()

/**
 * sfunction uid - Returns the user ID of a target process
 *
 * Description: This function returns the user ID of the target process.
 */
function uid:long ()
%{ /* bpf */ /* pure */ /* unprivileged */ /* stable */
   /* BPF_FUNC_get_current_uid_gid returns gid << 32 | uid */
   0x85, 0, 0, 0, 15;	/* call BPF_FUNC_get_current_uid_gid */
   0xbc, $$, 0, 0, 0	/* movwx $$, r0 */
%}

// TODO: ns_uid:long ()
// TODO: euid:long ()
// TODO: ns_euid:long ()
// XXX: is_myproc () is only relevant for unprivileged use of eBPF (still theoretical).

// TODO: Old systemtap-compat scripts should not be running on eBPF backend in the first place?
/**
 * sfunction cpuid - Returns the current cpu number
 * 
 * Description: This function returns the current cpu number.
 * Deprecated in SystemTap 1.4 and removed in SystemTap 1.5.
 */
%( systemtap_v <= "1.4" %?
  function cpuid:long ()
  %{ /* bpf */ /* pure */
     0x85, 0, 0, 0, 8;	/* call BPF_FUNC_get_smp_processor_id */
     0xbf, $$, 0, 0, 0	/* movx $$, r0 */
  %}
%)

/**
 * sfunction cpu - Returns the current cpu number
 *
 * Description: This function returns the current cpu number.
 */
function cpu:long ()
%{ /* bpf */ /* pure */ /* unprivileged */ /* stable */
   0x85, 0, 0, 0, 8;	/* call BPF_FUNC_get_smp_processor_id */
   0xbf, $$, 0, 0, 0	/* movx $$, r0 */
%}

// TODO: registers_valid:long ()
// TODO: user_mode:long ()
// TODO: is_return:long ()
// TODO: target:long ()
// TODO: module_name:string ()
// XXX: module_size:string () -- not clear if this should refer to the entire .bo or to just the current eBPF routine.
// TODO: stp_pid:long ()
// XXX: remote_id:long (), remote_uri:string() -- pending an evaluation of remote eBPF execution.
// XXX: stack_size() -- not clear if this should be the eBPF stack size or the kernel stack size.
// XXX: stack_used(),stack_unused() probably a fairly ill-defined idea with the eBPF stack.
// TODO: Other context functions for info about things like eBPF maps.

// TODO: addr:long ()
// TODO: uaddr:long ()
// XXX: cmdline_args:string(n:long, m:long, delim:string) -- requires string concatenation & loops.
// TODO: cmdline_arg:string(n:long)
// XXX: cmdline_string:string() -- requires string concatenation & loops.

global _stp_target

/**
 * Description: This function copies the system's target PID set with
 * either -x or -c in stabpf.  This function only works with the user-space
 * bpf interpreter, so it runs during initialization to copy target PID value
 * into a systemtap global which can be read from other more constrained
 * contexts.
 */
function _stp_get_target:long ()
%{ /* bpf */ /* pure */ /* unprivileged */ /* userspace */
   0x85, 0, 0, 0, -5;	/* call BPF_FUNC_get_target */
   0xbf, $$, 0, 0, 0	/* movx $$, r0 */
%}

probe init
{
  _stp_target = _stp_get_target()
}

/**
 * sfunction target - Return the process ID of the target process
 *
 * Description: This function returns the process ID of the target
 * process.  This is useful in conjunction with the -x PID or
 * -c CMD command-line options to stap. An example of its use is
 * to create scripts that filter on a specific process.
 *
 * -x <pid>
 * target() returns the pid specified by -x
 *
 * -c <command>
 * target() returns the pid for the executed command specified by -c
 */
function target:long ()
{
	return _stp_target
}
