// context-symbols tapset
// Copyright (C) 2005-2008 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.
//
%{
#ifndef STP_NEED_SYMBOL_DATA
#define STP_NEED_SYMBOL_DATA 1
#endif
%}
/**
* sfunction print_stack - Print out stack from string.
* @stk: String with list of hexadecimal addresses.
*
* Perform a symbolic lookup of the addresses in the given string,
* which is assumed to be the result of a prior call to
* backtrace().
*
* 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, " ");
}
%}
/**
* sfunction 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), current, 0);
if (THIS->__retvalue[0] == '.') /* powerpc symbol has a dot*/
strlcpy(THIS->__retvalue,THIS->__retvalue + 1,MAXSTRINGLEN);
} else {
THIS->__retvalue[0] = '\0';
}
%}
/**
* sfunction 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 if (CONTEXT->regs) {
struct _stp_module *m;
m = _stp_mod_sec_lookup (REG_IP(CONTEXT->regs), current, NULL);
if (m && m->name)
strlcpy (THIS->__retvalue, m->name, MAXSTRINGLEN);
else
strlcpy (THIS->__retvalue, "", MAXSTRINGLEN);
} else
strlcpy (THIS->__retvalue, "", MAXSTRINGLEN);
%}
/**
* sfunction modname - Return the kernel module name loaded at the address.
* @addr: The address.
*
* Description: Returns the module name associated with the given
* address if known. If not known it will return the string "".
* If the address was not in a kernel module, but in the kernel itself,
* then the string "kernel" will be returned.
*/
function modname:string (addr: long) %{ /* pure */
struct _stp_module *m;
m = _stp_mod_sec_lookup (THIS->addr, current, NULL);
if (m && m->name)
strlcpy (THIS->__retvalue, m->name, MAXSTRINGLEN);
else
strlcpy (THIS->__retvalue, "", MAXSTRINGLEN);
%}
/**
* sfunction symname - Return the symbol associated with the given address.
* @addr: The address to translate.
*
* Description: Returns the (function) symbol name associated with the
* given address if known. If not known it will return the hex string
* representation of addr.
*/
function symname:string (addr: long) %{ /* pure */
_stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr,
NULL, 0);
%}
/**
* sfunction symdata - Return the symbol and module offset for the address.
* @addr: The address to translate.
*
* Description: Returns the (function) symbol name associated with the
* given address if known, plus the module name (between brackets) and
* the offset inside the module, plus the size of the symbol function.
* If any element is not known it will be omitted and if the symbol name
* is unknown it will return the hex string for the given address.
*/
function symdata:string (addr: long) %{ /* pure */
_stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr,
NULL, 1);
%}