// context tapset // Copyright (C) 2005, 2006, 2007 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 /// /// The context functions provide additional information about the where /// the event occurred. /// These functions can provide information such as a backtrace /// where the event occured /// and the current register values for the processor. /// /// /// print_regs() /// print_regs /// /// Print a register dump. /// /// function print_regs () %{ if (CONTEXT->regs) { _stp_print_regs (CONTEXT->regs); } %} /// /// print_backtrace() /// print_backtrace /// /// Equivalent to print_stack(backtrace()), /// except that deeper stack nesting may be supported. Return nothing. /// /// function print_backtrace () %{ if (CONTEXT->regs) { _stp_stack_print(CONTEXT->regs, 1, CONTEXT->pi, MAXTRACE); } else { _stp_printf("Systemtap probe: %s\n", CONTEXT->probe_point); } %} /// /// backtrace:string() /// backtrace /// /// Return a string of hex addresses that are a backtrace of the /// stack. It may be truncated due to maximum string length. /// /// function backtrace:string () %{ /* pure */ if (CONTEXT->regs) _stp_stack_snprint (THIS->__retvalue, MAXSTRINGLEN, CONTEXT->regs, 0, CONTEXT->pi, MAXTRACE); else strlcpy (THIS->__retvalue, "", MAXSTRINGLEN); %} /// /// execname:string() /// execname /// /// Return the name of the current process. /// /// function execname:string () %{ /* pure */ strlcpy (THIS->__retvalue, current->comm, MAXSTRINGLEN); %} /// /// pid:long () /// pid /// /// Return the id of the current process. /// /// function pid:long () %{ /* pure */ THIS->__retvalue = current->tgid; %} /// /// tid:long() /// tid /// /// Return the id of the current thread. /// /// function tid:long () %{ /* pure */ THIS->__retvalue = current->pid; %} /// /// ppid:long() /// ppid /// /// Return the id of the parent process. /// /// function ppid:long () %{ /* pure */ #if defined(STAPCONF_REAL_PARENT) THIS->__retvalue = current->real_parent->tgid; #else THIS->__retvalue = current->parent->tgid; #endif %} /// /// pexecname:string() /// pexecname /// /// Return the name of the parent process. /// /// function pexecname:string () %{ /* pure */ #if defined(STAPCONF_REAL_PARENT) strlcpy (THIS->__retvalue, current->real_parent->comm, MAXSTRINGLEN); #else strlcpy (THIS->__retvalue, current->parent->comm, MAXSTRINGLEN); #endif %} /// /// gid:long() /// gid /// /// Return the gid of the current process. /// /// function gid:long () %{ /* pure */ THIS->__retvalue = current->gid; %} /// /// egid:long() /// egid /// /// Return the effective gid of the current process. /// /// function egid:long () %{ /* pure */ THIS->__retvalue = current->egid; %} /// /// uid:long() /// uid /// /// Return the uid of the current process. /// /// function uid:long () %{ /* pure */ THIS->__retvalue = current->uid; %} /// /// euid:long() /// euid /// /// Return the effective uid of the current process. /// /// function euid:long () %{ /* pure */ THIS->__retvalue = current->euid; %} // cpuid() is not documented function cpuid:long () %{ /* pure */ THIS->__retvalue = smp_processor_id(); %} /// /// cpu:long() /// cpu /// /// Return the current cpu number. /// /// function cpu:long () %{ /* pure */ THIS->__retvalue = smp_processor_id(); %} /// /// print_stack(stk:string) /// print_stack /// /// Perform a symbolic lookup of the addresses in the given string, /// which is assumed to be the result of a prior call to /// . /// Print one line per address, including the address, the /// name of the function containing the address, and an estimate of /// its position within that function. Return nothing. /// /// function print_stack(stk:string) %{ char *ptr = THIS->stk; char *tok = strsep(&ptr, " "); while (tok && *tok) { _stp_print_char(' '); _stp_symbol_print (simple_strtol(tok, NULL, 16)); _stp_print_char('\n'); tok = strsep(&ptr, " "); } %} /// /// pp:string() /// pp /// /// Return the probe point associated with the currently running /// probe handler, including alias and wildcard expansion effects. /// /// function pp:string () %{ /* pure */ strlcpy (THIS->__retvalue, CONTEXT->probe_point, MAXSTRINGLEN); %} /// /// probefunc:string() /// probefunc /// /// Return the probe point's function name, if known. /// /// function probefunc:string () %{ /* pure */ char *ptr, *start; start = strstr(CONTEXT->probe_point, "function(\""); ptr = start + 10; if (!start) { start = strstr(CONTEXT->probe_point, "inline(\""); ptr = start + 8; } if (start) { int len = MAXSTRINGLEN; char *dst = THIS->__retvalue; while (*ptr != '@' && --len > 0 && *ptr) *dst++ = *ptr++; *dst = 0; } else if (CONTEXT->regs && #if defined (__ia64__) ((unsigned long)REG_IP(CONTEXT->regs) >= (unsigned long)KERNEL_START)) { #else ((unsigned long)REG_IP(CONTEXT->regs) >= (unsigned long)PAGE_OFFSET)) { #endif _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, REG_IP(CONTEXT->regs)); if (THIS->__retvalue[0] == '.') /* powerpc symbol has a dot*/ strlcpy(THIS->__retvalue,THIS->__retvalue + 1,MAXSTRINGLEN); } else { THIS->__retvalue[0] = '\0'; } %} /// /// probemod:string() /// probemod /// /// Return the probe point's module name, if known. /// /// function probemod:string () %{ /* pure */ char *ptr, *start; start = strstr(CONTEXT->probe_point, "module(\""); ptr = start + 8; if (start) { int len = MAXSTRINGLEN; char *dst = THIS->__retvalue; while (*ptr != '"' && --len && *ptr) *dst++ = *ptr++; *dst = 0; } else { /* XXX: need a PC- and symbol-table-based fallback. */ THIS->__retvalue[0] = '\0'; } %} /// /// registers_valid:long() /// registers_valid /// /// 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 */ THIS->__retvalue = (CONTEXT->regs != NULL); %} /// /// user_mode:long() /// user_mode /// /// Return 1 if the probe point occurred in user-mode. /// /// function user_mode:long () %{ /* pure */ /* currently a user-mode address? */ 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; } %} /// /// is_return:long() /// is_return /// /// Return 1 if the probe point is a return probe. /// Deprecated. /// /// function is_return:long () %{ /* pure */ if (CONTEXT->pi) THIS->__retvalue = 1; else THIS->__retvalue = 0; %} /// /// target:long() /// target /// /// Return the pid of the target process. /// /// function target:long () %{ /* pure */ THIS->__retvalue = _stp_target; %} /// /// module_name:string() /// module_name /// /// FIXME: need description. /// /// function module_name:string () %{ /* pure */ strlcpy(THIS->__retvalue, THIS_MODULE->name, MAXSTRINGLEN); %} /// /// stp_pid:long() /// stp_pid /// /// FIXME: need description. /// /// function stp_pid:long () %{ /* pure */ THIS->__retvalue = _stp_pid; %} /// /// stack_size:long() /// stack_size /// /// Return the size of the kernel stack. /// /// function stack_size:long () %{ /* pure */ THIS->__retvalue = THREAD_SIZE; %} /// /// stack_used:long () /// stack_used /// /// Return 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)); %} /// /// stack_unused:long() /// stack_unused /// /// Return how many bytes are currently available in the kernel stack. /// /// function stack_unused:long () %{ /* pure */ char a; THIS->__retvalue = (long)&a & (THREAD_SIZE-1); %} /// /// caller_addr:long() /// caller_addr /// /// Return the address of the calling function. /// Works only for return probes at this time. /// /// /// function caller_addr:long () %{ /* pure */ if (CONTEXT->pi) THIS->__retvalue = (int64_t)(long)_stp_ret_addr_r(CONTEXT->pi); else THIS->__retvalue = 0; %} /// /// caller:string() /// caller /// /// Return the address and name of the calling function. /// Works only for return probes at this time. /// /// function caller:string() %{ /* pure */ if (CONTEXT->pi) _stp_symbol_snprint( THIS->__retvalue, MAXSTRINGLEN, (unsigned long)_stp_ret_addr_r(CONTEXT->pi)); else strlcpy(THIS->__retvalue,"unknown",MAXSTRINGLEN); %} ///