struct utrace_engine_ops — tracing engine callbacks
struct utrace_engine_ops { u32 (* report_quiesce) (u32 action, struct utrace_engine *engine,unsigned long event); u32 (* report_signal) (u32 action, struct utrace_engine *engine,struct pt_regs *regs,siginfo_t *info,const struct k_sigaction *orig_ka,struct k_sigaction *return_ka); u32 (* report_clone) (u32 action, struct utrace_engine *engine,unsigned long clone_flags,struct task_struct *child); u32 (* report_jctl) (u32 action, struct utrace_engine *engine,int type, int notify); u32 (* report_exec) (u32 action, struct utrace_engine *engine,const struct linux_binfmt *fmt,const struct linux_binprm *bprm,struct pt_regs *regs); u32 (* report_syscall_entry) (u32 action, struct utrace_engine *engine,struct pt_regs *regs); u32 (* report_syscall_exit) (u32 action, struct utrace_engine *engine,struct pt_regs *regs); u32 (* report_exit) (u32 action, struct utrace_engine *engine,long orig_code, long *code); u32 (* report_death) (struct utrace_engine *engine,bool group_dead, int signal); void (* report_reap) (struct utrace_engine *engine,struct task_struct *task); void (* release) (void *data); };
Requested by UTRACE_EVENT
(QUIESCE
).
This does not indicate any event, but just that current
is in a
safe place for examination. This call is made before each specific
event callback, except for report_reap
. The event
argument gives
the UTRACE_EVENT
(which
) value for the event occurring. This
callback might be made for events engine
has not requested, if
some other engine is tracing the event; calling utrace_set_events
call here can request the immediate callback for this occurrence of
event
. event
is zero when there is no other event, current
is
now ready to check for signals and return to user mode, and some
engine has used UTRACE_REPORT
or UTRACE_INTERRUPT
to request this
callback. For this case, if report_signal
is not NULL
, the
report_quiesce
callback may be replaced with a report_signal
callback passing UTRACE_SIGNAL_REPORT
in its action
argument,
whenever current
is entering the signal-check path anyway.
Requested by UTRACE_EVENT
(SIGNAL_
*) or UTRACE_EVENT
(QUIESCE
).
Use utrace_signal_action
and utrace_resume_action
on action
.
The signal action is UTRACE_SIGNAL_REPORT
when some engine has
used UTRACE_REPORT
or UTRACE_INTERRUPT
; the callback can choose
to stop or to deliver an artificial signal, before pending signals.
It's UTRACE_SIGNAL_HANDLER
instead when signal handler setup just
finished (after a previous UTRACE_SIGNAL_DELIVER
return); this
serves in lieu of any UTRACE_SIGNAL_REPORT
callback requested by
UTRACE_REPORT
or UTRACE_INTERRUPT
, and is also implicitly
requested by UTRACE_SINGLESTEP
or UTRACE_BLOCKSTEP
into the
signal delivery. The other signal actions indicate a signal about
to be delivered; the previous engine's return value sets the signal
action seen by the the following engine's callback. The info
data
can be changed at will, including info
->si_signo. The settings in
return_ka
determines what UTRACE_SIGNAL_DELIVER
does. orig_ka
is what was in force before other tracing engines intervened, and
it's NULL
when this report began as UTRACE_SIGNAL_REPORT
or
UTRACE_SIGNAL_HANDLER
. For a report without a new signal, info
is left uninitialized and must be set completely by an engine that
chooses to deliver a signal; if there was a previous report_signal
callback ending in UTRACE_STOP
and it was just resumed using
UTRACE_REPORT
or UTRACE_INTERRUPT
, then info
is left unchanged
from the previous callback. In this way, the original signal can
be left in info
while returning UTRACE_STOP
|UTRACE_SIGNAL_IGN
and then found again when resuming with UTRACE_INTERRUPT
.
The UTRACE_SIGNAL_HOLD
flag bit can be OR'd into the return value,
and might be in action
if the previous engine returned it. This
flag asks that the signal in info
be pushed back on current
's queue
so that it will be seen again after whatever action is taken now.
Requested by UTRACE_EVENT
(CLONE
).
Event reported for parent, before the new task child
might run.
clone_flags
gives the flags used in the clone system call, or
equivalent flags for a fork
or vfork
system call. This
function can use utrace_attach_task
on child
. Then passing
UTRACE_STOP
to utrace_control
on child
here keeps the child
stopped before it ever runs in user mode, UTRACE_REPORT
or
UTRACE_INTERRUPT
ensures a callback from child
before it
starts in user mode.
Requested by UTRACE_EVENT
(JCTL
).
Job control event; type
is CLD_STOPPED
or CLD_CONTINUED
,
indicating whether we are stopping or resuming now. If notify
is nonzero, current
is the last thread to stop and so will send
SIGCHLD
to its parent after this callback; notify
reflects
what the parent's SIGCHLD
has in si_code
, which can sometimes
be CLD_STOPPED
even when type
is CLD_CONTINUED
.
Requested by UTRACE_EVENT
(EXEC
).
An execve system call has succeeded and the new program is about to
start running. The initial user register state is handy to be tweaked
directly in regs
. fmt
and bprm
gives the details of this exec.
Requested by UTRACE_EVENT
(SYSCALL_ENTRY
).
Thread has entered the kernel to request a system call.
The user register state is handy to be tweaked directly in regs
.
The action
argument contains an enum utrace_syscall_action,
use utrace_syscall_action
to extract it. The return value
overrides the last engine's action for the system call.
If the final action is UTRACE_SYSCALL_ABORT
, no system call
is made. The details of the system call being attempted can
be fetched here with syscall_get_nr
and syscall_get_arguments
.
The parameter registers can be changed with syscall_set_arguments
.
See above about the UTRACE_SYSCALL_RESUMED
flag in action
.
Use UTRACE_REPORT
in the return value to guarantee you get
another callback (with UTRACE_SYSCALL_RESUMED
flag) in case
current
stops with UTRACE_STOP
before attempting the system call.
Requested by UTRACE_EVENT
(SYSCALL_EXIT
).
Thread is about to leave the kernel after a system call request.
The user register state is handy to be tweaked directly in regs
.
The results of the system call attempt can be examined here using
syscall_get_error
and syscall_get_return_value
. It is safe
here to call syscall_set_return_value
or syscall_rollback
.
Requested by UTRACE_EVENT
(EXIT
).
Thread is exiting and cannot be prevented from doing so,
but all its state is still live. The code
value will be
the wait result seen by the parent, and can be changed by
this engine or others. The orig_code
value is the real
status, not changed by any tracing engine. Returning UTRACE_STOP
here keeps current
stopped before it cleans up its state and dies,
so it can be examined by other processes. When current
is allowed
to run, it will die and get to the report_death
callback.
Requested by UTRACE_EVENT
(DEATH
).
Thread is really dead now. It might be reaped by its parent at
any time, or self-reap immediately. Though the actual reaping
may happen in parallel, a report_reap
callback will always be
ordered after a report_death
callback.
Requested by UTRACE_EVENT
(REAP
).
Called when someone reaps the dead task (parent, init, or self).
This means the parent called wait, or else this was a detached
thread or a process whose parent ignores SIGCHLD.
No more callbacks are made after this one.
The engine is always detached.
There is nothing more a tracing engine can do about this thread.
After this callback, the engine
pointer will become invalid.
The task
pointer may become invalid if get_task_struct
hasn't
been used to keep it alive.
An engine should always request this callback if it stores the
engine
pointer or stores any pointer in engine
->data, so it
can clean up its data structures.
Unlike other callbacks, this can be called from the parent's context
rather than from the traced thread itself--it must not delay the
parent by blocking.
If not NULL
, this is called after the last utrace_engine_put
call for a struct utrace_engine, which could be implicit after
a UTRACE_DETACH
return from another callback. Its argument is
the engine's data
member.
Each report_
*() callback corresponds to an UTRACE_EVENT
(*) bit.
utrace_set_events
calls on engine
choose which callbacks will
be made to engine
from task
.
Most callbacks take an action
argument, giving the resume action
chosen by other tracing engines. All callbacks take an engine
argument. The report_reap
callback takes a task
argument that
might or might not be current
. All other report_
* callbacks
report an event in the current
task.
For some calls, action
also includes bits specific to that event
and utrace_resume_action
is used to extract the resume action.
This shows what would happen if engine
wasn't there, or will if
the callback's return value uses UTRACE_RESUME
. This always
starts as UTRACE_RESUME
when no other tracing is being done on
this task.
All return values contain enum utrace_resume_action bits. For
some calls, other bits specific to that kind of event are added to
the resume action bits with OR. These are the same bits used in
the action
argument. The resume action returned by a callback
does not override previous engines' choices, it only says what
engine
wants done. What current
actually does is the action that's
most constrained among the choices made by all attached engines.
See utrace_control
for more information on the actions.
When UTRACE_STOP
is used in report_syscall_entry
, then current
stops before attempting the system call. In this case, another
report_syscall_entry
callback will follow after current
resumes if
UTRACE_REPORT
or UTRACE_INTERRUPT
was returned by some callback
or passed to utrace_control
. In a second or later callback,
UTRACE_SYSCALL_RESUMED
is set in the action
argument to indicate
a repeat callback still waiting to attempt the same system call
invocation. This repeat callback gives each engine an opportunity
to reexamine registers another engine might have changed while
current
was held in UTRACE_STOP
.
In other cases, the resume action does not take effect until current
is ready to check for signals and return to user mode. If there
are more callbacks to be made, the last round of calls determines
the final action. A report_quiesce
callback with event
zero, or
a report_signal
callback, will always be the last one made before
current
resumes. Only UTRACE_STOP
is “sticky”--if engine
returned
UTRACE_STOP
then current
stays stopped unless engine
returns
different from a following callback.
The report_death
and report_reap
callbacks do not take action
arguments, and only UTRACE_DETACH
is meaningful in the return value
from a report_death
callback. None of the resume actions applies
to a dead thread.
All report_
*() hooks are called with no locks held, in a generally
safe environment when we will be returning to user mode soon (or just
entered the kernel). It is fine to block for memory allocation and
the like, but all hooks are asynchronous and must not block on
external events! If you want the thread to block, use UTRACE_STOP
in your hook's return value; then later wake it up with utrace_control
.