and what information it gets passed. */
int probe_type;
+/* Common status of probe. _STP_PROBE_STATE_ flags. */
+int probe_flags;
+
/* Number of "actions" this probe handler is still allowed to do.
Setup in common_probe_entryfn_prologue to either MAXACTION or
Checked by code generated by c_unparser::record_actions (), which will
/* Last statement (token) executed. Often set together with last_error. */
const char *last_stmt;
-/* status of pt_regs regs field. _STP_REGS_ flags. */
-int regflags;
/* Set when probe handler gets pt_regs handed to it. This can be either
- the kernel registers or the user space registers. The regflags field
+ the kernel registers or the user space registers. The probe_flags field
will indicate which and whether the user registers are complete. */
struct pt_regs *regs;
#ifndef _REGS_H_ /* -*- linux-c -*- */
#define _REGS_H_
-/* Defines for the struct context regsflags field.
- _STP_REGS_USER regsflags bit to indicate regs fully from user. */
-#define _STP_REGS_USER_FLAG 1
-
#if defined (STAPCONF_X86_UNIREGS) && (defined (__x86_64__) || defined (__i386__))
#define REG_IP(regs) regs->ip
#define STP_OVERLOAD
#endif
+/* Defines for CONTEXT probe_type. */
/* begin, end or never probe, triggered by stap module itself. */
#define _STP_PROBE_HANDLER_BEEN 1
/* user space instruction probe, trigger by utrace signal report. */
#define _STP_PROBE_HANDLER_HWBKPT 15
/* kernel tracepoint probe, triggered by tracepoint event call. */
#define _STP_PROBE_HANDLER_TRACEPOINT 16
+
+/* Defines for CONTEXT probe_flags. */
+/* Probe occured in user space, also indicate regs fully from user. */
+#define _STP_PROBE_STATE_USER_MODE 1
ri = NULL;
if (stack_flags == _STP_STACK_KERNEL) {
- if (! c->regs || (c->regflags & _STP_REGS_USER_FLAG)) {
+ if (! c->regs
+ || (c->probe_flags & _STP_PROBE_STATE_USER_MODE)) {
/* For the kernel we can use an inexact fallback.
When compiled with frame pointers we can do
a pretty good guess at the stack value,
}
} else if (stack_flags == _STP_STACK_USER) {
/* use task_pt_regs, regs might be kernel regs, or not set. */
- if (c->regs && (c->regflags & _STP_REGS_USER_FLAG)) {
+ if (c->regs && (c->probe_flags & _STP_PROBE_STATE_USER_MODE)) {
regs = c->regs;
uregs_valid = 1;
} else {
common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "p->probe",
"_STP_PROBE_HANDLER_ITRACE");
s.op->newline() << "c->regs = regs;";
- s.op->newline() << "c->regflags |= _STP_REGS_USER_FLAG;";
+ s.op->newline() << "c->probe_flags |= _STP_PROBE_STATE_USER_MODE;";
// call probe function
s.op->newline() << "(*p->probe->ph) (c);";
s.op->newline() << "if ((stp->attr.type == PERF_TYPE_HARDWARE";
s.op->newline() << " || stp->attr.type == PERF_TYPE_HW_CACHE)";
s.op->newline() << " && user_mode(regs))";
- s.op->newline(1)<< "c->regflags |= _STP_REGS_USER_FLAG;";
+ s.op->newline(1)<< "c->probe_flags |= _STP_PROBE_STATE_USER_MODE;";
s.op->newline(-1) << "(*stp->probe->ph) (c);";
common_probe_entryfn_epilogue (s.op);
s.op->newline() << "c->regs = regs;";
// Timer interrupts save all registers, so if the interrupt happened
// in user space we can rely on it being the full user pt_regs.
- s.op->newline() << "if (user_mode(regs)) c->regflags |= _STP_REGS_USER_FLAG;";
+ s.op->newline() << "if (user_mode(regs)) c->probe_flags |= _STP_PROBE_STATE_USER_MODE;";
for (unsigned i=0; i<probes.size(); i++)
{
common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "p->probe",
"_STP_PROBE_HANDLER_UTRACE_SYSCALL");
s.op->newline() << "c->regs = regs;";
- s.op->newline() << "c->regflags |= _STP_REGS_USER_FLAG;";
+ s.op->newline() << "c->probe_flags |= _STP_PROBE_STATE_USER_MODE;";
// call probe function
s.op->newline() << "(*p->probe->ph) (c);";
THIS->__retvalue = value;
%}
-function _stp_probing_kernel:long () %{ /* pure */
- THIS->__retvalue = !user_mode(CONTEXT->regs);
-%}
+function _stp_probing_kernel:long () {
+ return !user_mode();
+}
/* Return the named register value as a signed value. */
function register:long (name:string) {
_stp_snprint_addr(THIS->__retvalue, MAXSTRINGLEN,
REG_IP(CONTEXT->regs),
_STP_SYM_SYMBOL,
- (CONTEXT->regflags & _STP_REGS_USER_FLAG
+ (CONTEXT->probe_flags & _STP_PROBE_STATE_USER_MODE
? current : NULL));
if (THIS->__retvalue[0] == '.') /* powerpc symbol has a dot*/
strlcpy(THIS->__retvalue,THIS->__retvalue + 1,MAXSTRINGLEN);
*dst++ = *ptr++;
*dst = 0;
} else if (CONTEXT->regs
- && ! (CONTEXT->regflags & _STP_REGS_USER_FLAG)) {
+ && ! (CONTEXT->probe_flags & _STP_PROBE_STATE_USER_MODE)) {
struct _stp_module *m;
m = _stp_kmod_sec_lookup (REG_IP(CONTEXT->regs), NULL);
if (m && m->name)
*/
function user_mode:long ()
%{ /* pure */ /* unprivileged */
- if (CONTEXT->regs && (CONTEXT->regflags & _STP_REGS_USER_FLAG)) {
- THIS->__retvalue = 1;
- } else {
- THIS->__retvalue = 0;
- }
+ THIS->__retvalue = (CONTEXT->probe_flags
+ & _STP_PROBE_STATE_USER_MODE) ? 1 : 0;
%}
/**
THIS->__retvalue = value;
%}
-function _stp_probing_kernel:long () %{ /* pure */
- THIS->__retvalue = !user_mode(CONTEXT->regs);
-%}
+function _stp_probing_kernel:long () {
+ return !user_mode();
+}
/*
* esp and ss aren't saved on a breakpoint in kernel mode, so
THIS->__retvalue = 0;
%}
-function _stp_probing_kernel: long () %{ /* pure */
- THIS->__retvalue = !user_mode(CONTEXT->regs);
-%}
+function _stp_probing_kernel: long () {
+ return !user_mode();
+}
function _stp_get_register_by_offset:long (offset:long) %{ /* pure */
long value;
%}
function _utrace_syscall_nr:long () %{ /* pure */ /* myproc-unprivileged */
- if (! CONTEXT->regs || ! (CONTEXT->regflags & _STP_REGS_USER_FLAG)) {
+ if (! CONTEXT->regs
+ || ! (CONTEXT->probe_flags & _STP_PROBE_STATE_USER_MODE)) {
CONTEXT->last_error = "invalid call without context registers";
} else {
THIS->__retvalue = syscall_get_nr(current, CONTEXT->regs);
function _utrace_syscall_arg:long (n:long) %{ /* pure */ /* myproc-unprivileged */
unsigned long arg = 0;
- if (! CONTEXT->regs || ! (CONTEXT->regflags & _STP_REGS_USER_FLAG)) {
+ if (! CONTEXT->regs
+ || ! (CONTEXT->probe_flags & _STP_PROBE_STATE_USER_MODE)) {
CONTEXT->last_error = "invalid call without context registers";
} else {
syscall_get_arguments(current, CONTEXT->regs, (int)THIS->n, 1, &arg);
* getting sign extended. This caused return values to not match
* up with the same values passes as arguments.
*/
- if (! CONTEXT->regs || ! (CONTEXT->regflags & _STP_REGS_USER_FLAG)) {
+ if (! CONTEXT->regs
+ || ! (CONTEXT->probe_flags & _STP_PROBE_STATE_USER_MODE)) {
CONTEXT->last_error = "invalid call without context registers";
} else {
THIS->__retvalue = (unsigned long)syscall_get_return_value(current,
o->newline() << "c->probe_type = " << probe_type << ";";
// reset Individual Probe State union
o->newline() << "memset(&c->ips, 0, sizeof(c->ips));";
- o->newline() << "c->regflags = 0;";
+ o->newline() << "c->probe_flags = 0;";
o->newline() << "#ifdef STAP_NEED_REGPARM"; // i386 or x86_64 register.stp
o->newline() << "c->regparm = 0;";
o->newline() << "#endif";
s.op->newline() << "goto probe_epilogue;";
s.op->newline(-1) << "}";
s.op->newline() << "c->regs = regs;";
- s.op->newline() << "c->regflags |= _STP_REGS_USER_FLAG;";
+ s.op->newline() << "c->probe_flags |= _STP_PROBE_STATE_USER_MODE;";
// Make it look like the IP is set as it would in the actual user
// task when calling real probe handler. Reset IP regs on return, so
s.op->newline(-1) << "}";
s.op->newline() << "c->regs = regs;";
- s.op->newline() << "c->regflags |= _STP_REGS_USER_FLAG;";
+ s.op->newline() << "c->probe_flags |= _STP_PROBE_STATE_USER_MODE;";
// Make it look like the IP is set as it would in the actual user
// task when calling real probe handler. Reset IP regs on return, so