2 // Copyright (C) 2005-2011 Red Hat Inc.
3 // Copyright (C) 2005-2007 Intel Corporation.
4 // Copyright (C) 2008 James.Bottomley@HansenPartnership.com
6 // This file is part of systemtap, and is free software. You can
7 // redistribute it and/or modify it under the terms of the GNU General
8 // Public License (GPL); either version 2, or (at your option) any
14 #include "task_finder.h"
15 #include "translate.h"
23 using namespace __gnu_cxx
;
26 static const string
TOK_PROCESS("process");
27 static const string
TOK_BEGIN("begin");
28 static const string
TOK_END("end");
29 static const string
TOK_THREAD("thread");
30 static const string
TOK_SYSCALL("syscall");
31 static const string
TOK_RETURN("return");
34 // ------------------------------------------------------------------------
35 // utrace user-space probes
36 // ------------------------------------------------------------------------
38 // Note that these flags don't match up exactly with UTRACE_EVENT
39 // flags (and that's OK).
40 enum utrace_derived_probe_flags
{
42 UDPF_BEGIN
, // process begin
43 UDPF_END
, // process end
44 UDPF_THREAD_BEGIN
, // thread begin
45 UDPF_THREAD_END
, // thread end
46 UDPF_SYSCALL
, // syscall entry
47 UDPF_SYSCALL_RETURN
, // syscall exit
51 struct utrace_derived_probe
: public derived_probe
58 enum utrace_derived_probe_flags flags
;
59 bool target_symbol_seen
;
61 utrace_derived_probe (systemtap_session
&s
, probe
* p
, probe_point
* l
,
62 bool hp
, string
&pn
, int64_t pd
,
63 enum utrace_derived_probe_flags f
);
64 void join_group (systemtap_session
& s
);
66 void emit_privilege_assertion (translator_output
*);
67 void print_dupe_stamp(ostream
& o
);
68 void getargs (std::list
<std::string
> &arg_set
) const;
72 struct utrace_derived_probe_group
: public generic_dpg
<utrace_derived_probe
>
75 map
<string
, vector
<utrace_derived_probe
*> > probes_by_path
;
76 typedef map
<string
, vector
<utrace_derived_probe
*> >::iterator p_b_path_iterator
;
77 map
<int64_t, vector
<utrace_derived_probe
*> > probes_by_pid
;
78 typedef map
<int64_t, vector
<utrace_derived_probe
*> >::iterator p_b_pid_iterator
;
80 bool flags_seen
[UDPF_NFLAGS
];
82 void emit_probe_decl (systemtap_session
& s
, utrace_derived_probe
*p
);
85 utrace_derived_probe_group(): num_probes(0), flags_seen() { }
87 void enroll (utrace_derived_probe
* probe
);
88 void emit_module_decls (systemtap_session
& s
);
89 void emit_module_init (systemtap_session
& s
);
90 void emit_module_exit (systemtap_session
& s
);
94 struct utrace_var_expanding_visitor
: public var_expanding_visitor
96 utrace_var_expanding_visitor(systemtap_session
& s
, probe_point
* l
,
98 enum utrace_derived_probe_flags f
):
99 sess (s
), base_loc (l
), probe_name (pn
), flags (f
),
100 target_symbol_seen (false), add_block(NULL
), add_probe(NULL
) {}
102 systemtap_session
& sess
;
103 probe_point
* base_loc
;
105 enum utrace_derived_probe_flags flags
;
106 bool target_symbol_seen
;
109 std::map
<std::string
, symbol
*> return_ts_map
;
111 void visit_target_symbol_arg (target_symbol
* e
);
112 void visit_target_symbol_context (target_symbol
* e
);
113 void visit_target_symbol_cached (target_symbol
* e
);
114 void visit_target_symbol (target_symbol
* e
);
119 utrace_derived_probe::utrace_derived_probe (systemtap_session
&s
,
120 probe
* p
, probe_point
* l
,
121 bool hp
, string
&pn
, int64_t pd
,
122 enum utrace_derived_probe_flags f
):
123 derived_probe (p
, l
, true /* .components soon rewritten */ ),
124 has_path(hp
), path(pn
), has_library(false), pid(pd
), flags(f
),
125 target_symbol_seen(false)
127 // FIXME: How to test for new utrace?
129 if (s
.kernel_config
["CONFIG_UTRACE"] != string("y"))
130 throw semantic_error (_("process probes not available without kernel CONFIG_UTRACE"));
133 // Expand local variables in the probe body
134 utrace_var_expanding_visitor
v (s
, l
, name
, flags
);
135 v
.replace (this->body
);
136 target_symbol_seen
= v
.target_symbol_seen
;
138 // If during target-variable-expanding the probe, we added a new block
139 // of code, add it to the start of the probe.
141 this->body
= new block(v
.add_block
, this->body
);
142 // If when target-variable-expanding the probe, we added a new
143 // probe, add it in a new file to the list of files to be processed.
146 stapfile
*f
= new stapfile
;
147 f
->probes
.push_back(v
.add_probe
);
148 s
.files
.push_back(f
);
151 // Reset the sole element of the "locations" vector as a
152 // "reverse-engineered" form of the incoming (q.base_loc) probe
153 // point. This allows a user to see what program etc.
154 // number any particular match of the wildcards.
156 vector
<probe_point::component
*> comps
;
158 comps
.push_back (new probe_point::component(TOK_PROCESS
, new literal_string(path
)));
160 comps
.push_back (new probe_point::component(TOK_PROCESS
, new literal_number(pid
)));
162 comps
.push_back (new probe_point::component(TOK_PROCESS
));
166 case UDPF_THREAD_BEGIN
:
167 comps
.push_back (new probe_point::component(TOK_THREAD
));
168 comps
.push_back (new probe_point::component(TOK_BEGIN
));
170 case UDPF_THREAD_END
:
171 comps
.push_back (new probe_point::component(TOK_THREAD
));
172 comps
.push_back (new probe_point::component(TOK_END
));
175 comps
.push_back (new probe_point::component(TOK_SYSCALL
));
177 case UDPF_SYSCALL_RETURN
:
178 comps
.push_back (new probe_point::component(TOK_SYSCALL
));
179 comps
.push_back (new probe_point::component(TOK_RETURN
));
182 comps
.push_back (new probe_point::component(TOK_BEGIN
));
185 comps
.push_back (new probe_point::component(TOK_END
));
192 this->sole_location()->components
= comps
;
197 utrace_derived_probe::join_group (systemtap_session
& s
)
199 if (! s
.utrace_derived_probes
)
201 s
.utrace_derived_probes
= new utrace_derived_probe_group ();
203 s
.utrace_derived_probes
->enroll (this);
205 enable_task_finder(s
);
210 utrace_derived_probe::emit_privilege_assertion (translator_output
* o
)
212 // Process end probes can fire for unprivileged users even if the process
213 // does not belong to the user. On example is that process.end will fire
214 // at the end of a process which executes execve on an executable which
215 // has the setuid bit set. When the setuid executable ends, the process.end
216 // will fire even though the owner of the process is different than the
218 // Unprivileged users must use check is_myproc() from within any
219 // process.end variant in their script before doing anything "dangerous".
220 if (flags
== UDPF_END
)
223 // Other process probes should only fire for unprivileged users in the
224 // context of processes which they own. Generate an assertion to this effect
226 emit_process_owner_assertion (o
);
230 utrace_derived_probe::print_dupe_stamp(ostream
& o
)
232 // Process end probes can fire for unprivileged users even if the process
233 // does not belong to the user. On example is that process.end will fire
234 // at the end of a process which executes execve on an executable which
235 // has the setuid bit set. When the setuid executable ends, the process.end
236 // will fire even though the owner of the process is different than the
238 // Unprivileged users must use check is_myproc() from within any
239 // process.end variant in their script before doing anything "dangerous".
241 // Other process probes should only fire for unprivileged users in the
242 // context of processes which they own.
243 if (flags
== UDPF_END
)
244 print_dupe_stamp_unprivileged (o
);
246 print_dupe_stamp_unprivileged_process_owner (o
);
250 utrace_derived_probe::getargs(std::list
<std::string
> &arg_set
) const
252 arg_set
.push_back("$syscall:long");
253 arg_set
.push_back("$arg1:long");
254 arg_set
.push_back("$arg2:long");
255 arg_set
.push_back("$arg3:long");
256 arg_set
.push_back("$arg4:long");
257 arg_set
.push_back("$arg5:long");
258 arg_set
.push_back("$arg6:long");
262 utrace_var_expanding_visitor::visit_target_symbol_cached (target_symbol
* e
)
264 // Get the full name of the target symbol.
265 stringstream ts_name_stream
;
266 e
->print(ts_name_stream
);
267 string ts_name
= ts_name_stream
.str();
269 // Check and make sure we haven't already seen this target
270 // variable in this return probe. If we have, just return our
272 map
<string
, symbol
*>::iterator i
= return_ts_map
.find(ts_name
);
273 if (i
!= return_ts_map
.end())
279 // We've got to do several things here to handle target
280 // variables in return probes.
282 // (1) Synthesize a global array which is the cache of the
283 // target variable value. We don't need a nesting level counter
284 // like the dwarf_var_expanding_visitor::visit_target_symbol()
285 // does since a particular thread can only be in one system
286 // calls at a time. The array will look like this:
288 // _utrace_tvar_{name}_{num}
289 string aname
= (string("_utrace_tvar_")
291 + "_" + lex_cast(tick
++));
292 vardecl
* vd
= new vardecl
;
295 sess
.globals
.push_back (vd
);
297 // (2) Create a new code block we're going to insert at the
298 // beginning of this probe to get the cached value into a
299 // temporary variable. We'll replace the target variable
300 // reference with the temporary variable reference. The code
301 // will look like this:
303 // _utrace_tvar_tid = tid()
304 // _utrace_tvar_{name}_{num}_tmp
305 // = _utrace_tvar_{name}_{num}[_utrace_tvar_tid]
306 // delete _utrace_tvar_{name}_{num}[_utrace_tvar_tid]
308 // (2a) Synthesize the tid temporary expression, which will look
311 // _utrace_tvar_tid = tid()
312 symbol
* tidsym
= new symbol
;
313 tidsym
->name
= string("_utrace_tvar_tid");
314 tidsym
->tok
= e
->tok
;
316 if (add_block
== NULL
)
318 add_block
= new block
;
319 add_block
->tok
= e
->tok
;
321 // Synthesize a functioncall to grab the thread id.
322 functioncall
* fc
= new functioncall
;
324 fc
->function
= string("tid");
326 // Assign the tid to '_utrace_tvar_tid'.
327 assignment
* a
= new assignment
;
333 expr_statement
* es
= new expr_statement
;
336 add_block
->statements
.push_back (es
);
339 // (2b) Synthesize an array reference and assign it to a
340 // temporary variable (that we'll use as replacement for the
341 // target variable reference). It will look like this:
343 // _utrace_tvar_{name}_{num}_tmp
344 // = _utrace_tvar_{name}_{num}[_utrace_tvar_tid]
346 arrayindex
* ai_tvar
= new arrayindex
;
347 ai_tvar
->tok
= e
->tok
;
349 symbol
* sym
= new symbol
;
354 ai_tvar
->indexes
.push_back(tidsym
);
356 symbol
* tmpsym
= new symbol
;
357 tmpsym
->name
= aname
+ "_tmp";
358 tmpsym
->tok
= e
->tok
;
360 assignment
* a
= new assignment
;
366 expr_statement
* es
= new expr_statement
;
370 add_block
->statements
.push_back (es
);
372 // (2c) Delete the array value. It will look like this:
374 // delete _utrace_tvar_{name}_{num}[_utrace_tvar_tid]
376 delete_statement
* ds
= new delete_statement
;
379 add_block
->statements
.push_back (ds
);
381 // (3) We need an entry probe that saves the value for us in the
382 // global array we created. Create the entry probe, which will
385 // probe process(PATH_OR_PID).syscall {
386 // _utrace_tvar_tid = tid()
387 // _utrace_tvar_{name}_{num}[_utrace_tvar_tid] = ${param}
390 // Why the temporary for tid()? If we end up caching more
391 // than one target variable, we can reuse the temporary instead
392 // of calling tid() multiple times.
394 if (add_probe
== NULL
)
396 add_probe
= new probe
;
397 add_probe
->tok
= e
->tok
;
399 // We need the name of the current probe point, minus the
400 // ".return". Create a new probe point, copying all the
401 // components, stopping when we see the ".return"
403 probe_point
* pp
= new probe_point
;
404 for (unsigned c
= 0; c
< base_loc
->components
.size(); c
++)
406 if (base_loc
->components
[c
]->functor
== "return")
409 pp
->components
.push_back(base_loc
->components
[c
]);
411 pp
->optional
= base_loc
->optional
;
412 add_probe
->locations
.push_back(pp
);
414 add_probe
->body
= new block
;
415 add_probe
->body
->tok
= e
->tok
;
417 // Synthesize a functioncall to grab the thread id.
418 functioncall
* fc
= new functioncall
;
420 fc
->function
= string("tid");
422 // Assign the tid to '_utrace_tvar_tid'.
423 assignment
* a
= new assignment
;
429 expr_statement
* es
= new expr_statement
;
432 add_probe
->body
= new block(add_probe
->body
, es
);
434 vardecl
* vd
= new vardecl
;
436 vd
->name
= tidsym
->name
;
438 vd
->set_arity(0, e
->tok
);
439 add_probe
->locals
.push_back(vd
);
442 // Save the value, like this:
444 // _utrace_tvar_{name}_{num}[_utrace_tvar_tid] = ${param}
451 es
= new expr_statement
;
455 add_probe
->body
= new block(add_probe
->body
, es
);
457 // (4) Provide the '_utrace_tvar_{name}_{num}_tmp' variable to
458 // our parent so it can be used as a substitute for the target
462 // (5) Remember this replacement since we might be able to reuse
463 // it later if the same return probe references this target
465 return_ts_map
[ts_name
] = tmpsym
;
471 utrace_var_expanding_visitor::visit_target_symbol_arg (target_symbol
* e
)
473 if (flags
!= UDPF_SYSCALL
)
474 throw semantic_error (_("only \"process(PATH_OR_PID).syscall\" support $argN or $$parms."), e
->tok
);
476 if (e
->name
== "$$parms")
478 // copy from tracepoint
479 token
* pf_tok
= new token(*e
->tok
);
480 pf_tok
->content
= "sprintf";
481 print_format
* pf
= print_format::create(pf_tok
);
483 target_symbol_seen
= true;
485 for (unsigned i
= 0; i
< 6; ++i
)
488 pf
->raw_components
+= " ";
489 pf
->raw_components
+= "$arg" + lex_cast(i
+1);
490 target_symbol
*tsym
= new target_symbol
;
492 tsym
->name
= "$arg" + lex_cast(i
+1);
493 tsym
->saved_conversion_error
= 0;
494 pf
->raw_components
+= "=%#x"; //FIXME: missing type info
496 functioncall
* n
= new functioncall
; //same as the following
498 n
->function
= "_utrace_syscall_arg";
500 literal_number
*num
= new literal_number(i
);
502 n
->args
.push_back(num
);
504 pf
->args
.push_back(n
);
506 pf
->components
= print_format::string_to_components(pf
->raw_components
);
512 string argnum_s
= e
->name
.substr(4,e
->name
.length()-4);
516 argnum
= lex_cast
<int>(argnum_s
);
518 catch (const runtime_error
& f
) // non-integral $arg suffix: e.g. $argKKKSDF
520 throw semantic_error (_("invalid syscall argument number (1-6)"), e
->tok
);
523 e
->assert_no_components("utrace");
525 // FIXME: max argnument number should not be hardcoded.
526 if (argnum
< 1 || argnum
> 6)
527 throw semantic_error (_("invalid syscall argument number (1-6)"), e
->tok
);
529 bool lvalue
= is_active_lvalue(e
);
531 throw semantic_error(_("utrace '$argN' variable is read-only"), e
->tok
);
533 // Remember that we've seen a target variable.
534 target_symbol_seen
= true;
536 // We're going to substitute a synthesized '_utrace_syscall_arg'
537 // function call for the '$argN' reference.
538 functioncall
* n
= new functioncall
;
540 n
->function
= "_utrace_syscall_arg";
541 n
->referent
= 0; // NB: must not resolve yet, to ensure inclusion in session
543 literal_number
*num
= new literal_number(argnum
- 1);
545 n
->args
.push_back(num
);
552 utrace_var_expanding_visitor::visit_target_symbol_context (target_symbol
* e
)
554 const string
& sname
= e
->name
;
556 e
->assert_no_components("utrace");
558 bool lvalue
= is_active_lvalue(e
);
560 throw semantic_error(_F("utrace '%s' variable is read-only", sname
.c_str()), e
->tok
);
563 if (sname
== "$return")
565 if (flags
!= UDPF_SYSCALL_RETURN
)
566 throw semantic_error (_("only \"process(PATH_OR_PID).syscall.return\" support $return."), e
->tok
);
567 fname
= "_utrace_syscall_return";
569 else if (sname
== "$syscall")
571 // If we've got a syscall entry probe, we can just call the
573 if (flags
== UDPF_SYSCALL
) {
574 fname
= "_utrace_syscall_nr";
576 // If we're in a syscal return probe, we can't really access
577 // $syscall. So, similar to what
578 // dwarf_var_expanding_visitor::visit_target_symbol() does,
579 // we'll create an syscall entry probe to cache $syscall, then
580 // we'll access the cached value in the syscall return probe.
582 visit_target_symbol_cached (e
);
584 // Remember that we've seen a target variable.
585 target_symbol_seen
= true;
591 throw semantic_error (_("unknown target variable"), e
->tok
);
594 // Remember that we've seen a target variable.
595 target_symbol_seen
= true;
597 // We're going to substitute a synthesized '_utrace_syscall_nr'
598 // function call for the '$syscall' reference.
599 functioncall
* n
= new functioncall
;
602 n
->referent
= 0; // NB: must not resolve yet, to ensure inclusion in session
608 utrace_var_expanding_visitor::visit_target_symbol (target_symbol
* e
)
610 assert(e
->name
.size() > 0 && e
->name
[0] == '$');
614 if (flags
!= UDPF_SYSCALL
&& flags
!= UDPF_SYSCALL_RETURN
)
615 throw semantic_error (_("only \"process(PATH_OR_PID).syscall\""
616 " and \"process(PATH_OR_PID).syscall.return\" probes support target symbols"),
620 throw semantic_error(_("cannot take address of utrace variable"), e
->tok
);
622 if (startswith(e
->name
, "$arg") || e
->name
== "$$parms")
623 visit_target_symbol_arg(e
);
624 else if (e
->name
== "$syscall" || e
->name
== "$return")
625 visit_target_symbol_context(e
);
627 throw semantic_error (_("invalid target symbol for utrace probe,"
628 " $syscall, $return, $argN or $$parms expected"),
631 catch (const semantic_error
&er
)
640 struct utrace_builder
: public derived_probe_builder
643 virtual void build(systemtap_session
& sess
,
645 probe_point
* location
,
646 literal_map_t
const & parameters
,
647 vector
<derived_probe
*> & finished_results
)
652 bool has_path
= get_param (parameters
, TOK_PROCESS
, path
);
653 bool has_pid
= get_param (parameters
, TOK_PROCESS
, pid
);
654 enum utrace_derived_probe_flags flags
= UDPF_NONE
;
656 if (has_null_param (parameters
, TOK_THREAD
))
658 if (has_null_param (parameters
, TOK_BEGIN
))
659 flags
= UDPF_THREAD_BEGIN
;
660 else if (has_null_param (parameters
, TOK_END
))
661 flags
= UDPF_THREAD_END
;
663 else if (has_null_param (parameters
, TOK_SYSCALL
))
665 if (has_null_param (parameters
, TOK_RETURN
))
666 flags
= UDPF_SYSCALL_RETURN
;
668 flags
= UDPF_SYSCALL
;
670 else if (has_null_param (parameters
, TOK_BEGIN
))
672 else if (has_null_param (parameters
, TOK_END
))
675 // If we didn't get a path or pid, this means to probe everything.
676 // Convert this to a pid-based probe.
677 if (! has_path
&& ! has_pid
)
686 path
= find_executable (path
);
687 sess
.unwindsym_modules
.insert (path
);
691 // We can't probe 'init' (pid 1). XXX: where does this limitation come from?
693 throw semantic_error (_("process pid must be greater than 1"),
694 location
->components
.front()->tok
);
696 // XXX: could we use /proc/$pid/exe in unwindsym_modules and elsewhere?
699 finished_results
.push_back(new utrace_derived_probe(sess
, base
, location
,
707 utrace_derived_probe_group::enroll (utrace_derived_probe
* p
)
710 probes_by_path
[p
->path
].push_back(p
);
712 probes_by_pid
[p
->pid
].push_back(p
);
714 flags_seen
[p
->flags
] = true;
716 // XXX: multiple exec probes (for instance) for the same path (or
717 // pid) should all share a utrace report function, and have their
718 // handlers executed sequentially.
723 utrace_derived_probe_group::emit_probe_decl (systemtap_session
& s
,
724 utrace_derived_probe
*p
)
726 s
.op
->newline() << "{";
727 s
.op
->line() << " .tgt={";
731 s
.op
->line() << " .procname=\"" << p
->path
<< "\",";
732 s
.op
->line() << " .pid=0,";
736 s
.op
->line() << " .procname=NULL,";
737 s
.op
->line() << " .pid=" << p
->pid
<< ",";
740 s
.op
->line() << " .callback=&_stp_utrace_probe_cb,";
741 s
.op
->line() << " .mmap_callback=NULL,";
742 s
.op
->line() << " .munmap_callback=NULL,";
743 s
.op
->line() << " .mprotect_callback=NULL,";
744 s
.op
->line() << " },";
745 s
.op
->line() << " .probe=" << common_probe_init (p
) << ",";
750 // Notice that we'll just call the probe directly when we get
751 // notified, since the task_finder layer stops the thread for us.
752 case UDPF_BEGIN
: // process begin
753 s
.op
->line() << " .flags=(UDPF_BEGIN),";
755 case UDPF_THREAD_BEGIN
: // thread begin
756 s
.op
->line() << " .flags=(UDPF_THREAD_BEGIN),";
759 // Notice we're not setting up a .ops/.report_death handler for
760 // either UDPF_END or UDPF_THREAD_END. Instead, we'll just call
761 // the probe directly when we get notified.
762 case UDPF_END
: // process end
763 s
.op
->line() << " .flags=(UDPF_END),";
765 case UDPF_THREAD_END
: // thread end
766 s
.op
->line() << " .flags=(UDPF_THREAD_END),";
769 // For UDPF_SYSCALL/UDPF_SYSCALL_RETURN probes, the .report_death
770 // handler isn't strictly necessary. However, it helps to keep
771 // our attaches/detaches symmetrical. Since the task_finder layer
772 // stops the thread, that works around bug 6841.
774 s
.op
->line() << " .flags=(UDPF_SYSCALL),";
775 s
.op
->line() << " .ops={ .report_syscall_entry=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death },";
776 s
.op
->line() << " .events=(UTRACE_EVENT(SYSCALL_ENTRY)|UTRACE_EVENT(DEATH)),";
778 case UDPF_SYSCALL_RETURN
:
779 s
.op
->line() << " .flags=(UDPF_SYSCALL_RETURN),";
780 s
.op
->line() << " .ops={ .report_syscall_exit=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death },";
781 s
.op
->line() << " .events=(UTRACE_EVENT(SYSCALL_EXIT)|UTRACE_EVENT(DEATH)),";
785 s
.op
->line() << " .flags=(UDPF_NONE),";
786 s
.op
->line() << " .ops={ },";
787 s
.op
->line() << " .events=0,";
790 throw semantic_error ("bad utrace probe flag");
793 s
.op
->line() << " .engine_attached=0,";
794 s
.op
->line() << " },";
799 utrace_derived_probe_group::emit_module_decls (systemtap_session
& s
)
801 if (probes_by_path
.empty() && probes_by_pid
.empty())
805 s
.op
->newline() << "/* ---- utrace probes ---- */";
807 s
.op
->newline() << "enum utrace_derived_probe_flags {";
809 s
.op
->newline() << "UDPF_NONE,";
810 s
.op
->newline() << "UDPF_BEGIN,";
811 s
.op
->newline() << "UDPF_END,";
812 s
.op
->newline() << "UDPF_THREAD_BEGIN,";
813 s
.op
->newline() << "UDPF_THREAD_END,";
814 s
.op
->newline() << "UDPF_SYSCALL,";
815 s
.op
->newline() << "UDPF_SYSCALL_RETURN,";
816 s
.op
->newline() << "UDPF_NFLAGS";
817 s
.op
->newline(-1) << "};";
819 s
.op
->newline() << "struct stap_utrace_probe {";
821 s
.op
->newline() << "struct stap_task_finder_target tgt;";
822 s
.op
->newline() << "struct stap_probe * const probe;";
823 s
.op
->newline() << "int engine_attached;";
824 s
.op
->newline() << "enum utrace_derived_probe_flags flags;";
825 s
.op
->newline() << "struct utrace_engine_ops ops;";
826 s
.op
->newline() << "unsigned long events;";
827 s
.op
->newline(-1) << "};";
830 // Output handler function for UDPF_BEGIN, UDPF_THREAD_BEGIN,
831 // UDPF_END, and UDPF_THREAD_END
832 if (flags_seen
[UDPF_BEGIN
] || flags_seen
[UDPF_THREAD_BEGIN
]
833 || flags_seen
[UDPF_END
] || flags_seen
[UDPF_THREAD_END
])
835 s
.op
->newline() << "static void stap_utrace_probe_handler(struct task_struct *tsk, struct stap_utrace_probe *p) {";
838 common_probe_entryfn_prologue (s
.op
, "STAP_SESSION_RUNNING", "p->probe",
839 "_STP_PROBE_HANDLER_UTRACE");
841 // call probe function
842 s
.op
->newline() << "(*p->probe->ph) (c);";
843 common_probe_entryfn_epilogue (s
.op
);
845 s
.op
->newline() << "return;";
846 s
.op
->newline(-1) << "}";
849 // Output handler function for SYSCALL_ENTRY and SYSCALL_EXIT events
850 if (flags_seen
[UDPF_SYSCALL
] || flags_seen
[UDPF_SYSCALL_RETURN
])
852 s
.op
->newline() << "#ifdef UTRACE_ORIG_VERSION";
853 s
.op
->newline() << "static u32 stap_utrace_probe_syscall(struct utrace_engine *engine, struct task_struct *tsk, struct pt_regs *regs) {";
854 s
.op
->newline() << "#else";
855 s
.op
->newline() << "#if (defined(UTRACE_API_VERSION) && (UTRACE_API_VERSION >= 20091216)) || defined(STP_TASK_FINDER2)";
856 s
.op
->newline() << "static u32 stap_utrace_probe_syscall(u32 action, struct utrace_engine *engine, struct pt_regs *regs) {";
857 s
.op
->newline() << "#else";
858 s
.op
->newline() << "static u32 stap_utrace_probe_syscall(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *tsk, struct pt_regs *regs) {";
859 s
.op
->newline() << "#endif";
860 s
.op
->newline() << "#endif";
863 s
.op
->newline() << "struct stap_utrace_probe *p = (struct stap_utrace_probe *)engine->data;";
865 common_probe_entryfn_prologue (s
.op
, "STAP_SESSION_RUNNING", "p->probe",
866 "_STP_PROBE_HANDLER_UTRACE_SYSCALL");
867 s
.op
->newline() << "c->uregs = regs;";
868 s
.op
->newline() << "c->probe_flags |= _STP_PROBE_STATE_USER_MODE;";
870 // call probe function
871 s
.op
->newline() << "(*p->probe->ph) (c);";
872 common_probe_entryfn_epilogue (s
.op
);
874 s
.op
->newline() << "if ((atomic_read (&session_state) != STAP_SESSION_STARTING) && (atomic_read (&session_state) != STAP_SESSION_RUNNING)) {";
876 s
.op
->newline() << "debug_task_finder_detach();";
877 s
.op
->newline() << "return UTRACE_DETACH;";
878 s
.op
->newline(-1) << "}";
879 s
.op
->newline() << "return UTRACE_RESUME;";
880 s
.op
->newline(-1) << "}";
883 // Output task_finder callback routine that gets called for all
884 // utrace probe types.
885 s
.op
->newline() << "static int _stp_utrace_probe_cb(struct stap_task_finder_target *tgt, struct task_struct *tsk, int register_p, int process_p) {";
887 s
.op
->newline() << "int rc = 0;";
888 s
.op
->newline() << "struct stap_utrace_probe *p = container_of(tgt, struct stap_utrace_probe, tgt);";
889 s
.op
->newline() << "struct utrace_engine *engine;";
891 s
.op
->newline() << "if (register_p) {";
894 s
.op
->newline() << "switch (p->flags) {";
897 // When receiving a UTRACE_EVENT(CLONE) event, we can't call the
898 // begin/thread.begin probe directly. So, we'll just attach an
899 // engine that waits for the thread to quiesce. When the thread
900 // quiesces, then call the probe.
901 if (flags_seen
[UDPF_BEGIN
])
903 s
.op
->newline() << "case UDPF_BEGIN:";
905 s
.op
->newline() << "if (process_p) {";
907 s
.op
->newline() << "stap_utrace_probe_handler(tsk, p);";
908 s
.op
->newline(-1) << "}";
909 s
.op
->newline() << "break;";
912 if (flags_seen
[UDPF_THREAD_BEGIN
])
914 s
.op
->newline() << "case UDPF_THREAD_BEGIN:";
916 s
.op
->newline() << "if (! process_p) {";
918 s
.op
->newline() << "stap_utrace_probe_handler(tsk, p);";
919 s
.op
->newline(-1) << "}";
920 s
.op
->newline() << "break;";
924 // For end/thread_end probes, do nothing at registration time.
925 // We'll handle these in the 'register_p == 0' case.
926 if (flags_seen
[UDPF_END
] || flags_seen
[UDPF_THREAD_END
])
928 s
.op
->newline() << "case UDPF_END:";
929 s
.op
->newline() << "case UDPF_THREAD_END:";
931 s
.op
->newline() << "break;";
935 // Attach an engine for SYSCALL_ENTRY and SYSCALL_EXIT events.
936 if (flags_seen
[UDPF_SYSCALL
] || flags_seen
[UDPF_SYSCALL_RETURN
])
938 s
.op
->newline() << "case UDPF_SYSCALL:";
939 s
.op
->newline() << "case UDPF_SYSCALL_RETURN:";
941 s
.op
->newline() << "rc = stap_utrace_attach(tsk, &p->ops, p, p->events);";
942 s
.op
->newline() << "if (rc == 0) {";
944 s
.op
->newline() << "p->engine_attached = 1;";
945 s
.op
->newline(-1) << "}";
946 s
.op
->newline() << "break;";
950 s
.op
->newline() << "default:";
952 s
.op
->newline() << "_stp_error(\"unhandled flag value %d at %s:%d\", p->flags, __FUNCTION__, __LINE__);";
953 s
.op
->newline() << "break;";
955 s
.op
->newline(-1) << "}";
956 s
.op
->newline(-1) << "}";
958 // Since this engine could be attached to multiple threads, don't
959 // call stap_utrace_detach_ops() here, only call
960 // stap_utrace_detach() as necessary.
961 s
.op
->newline() << "else {";
963 s
.op
->newline() << "switch (p->flags) {";
965 // For end probes, go ahead and call the probe directly.
966 if (flags_seen
[UDPF_END
])
968 s
.op
->newline() << "case UDPF_END:";
970 s
.op
->newline() << "if (process_p) {";
972 s
.op
->newline() << "stap_utrace_probe_handler(tsk, p);";
973 s
.op
->newline(-1) << "}";
974 s
.op
->newline() << "break;";
977 if (flags_seen
[UDPF_THREAD_END
])
979 s
.op
->newline() << "case UDPF_THREAD_END:";
981 s
.op
->newline() << "if (! process_p) {";
983 s
.op
->newline() << "stap_utrace_probe_handler(tsk, p);";
984 s
.op
->newline(-1) << "}";
985 s
.op
->newline() << "break;";
989 // For begin/thread_begin probes, we don't need to do anything.
990 if (flags_seen
[UDPF_BEGIN
] || flags_seen
[UDPF_THREAD_BEGIN
])
992 s
.op
->newline() << "case UDPF_BEGIN:";
993 s
.op
->newline() << "case UDPF_THREAD_BEGIN:";
995 s
.op
->newline() << "break;";
999 if (flags_seen
[UDPF_SYSCALL
] || flags_seen
[UDPF_SYSCALL_RETURN
])
1001 s
.op
->newline() << "case UDPF_SYSCALL:";
1002 s
.op
->newline() << "case UDPF_SYSCALL_RETURN:";
1004 s
.op
->newline() << "stap_utrace_detach(tsk, &p->ops);";
1005 s
.op
->newline() << "break;";
1009 s
.op
->newline() << "default:";
1011 s
.op
->newline() << "_stp_error(\"unhandled flag value %d at %s:%d\", p->flags, __FUNCTION__, __LINE__);";
1012 s
.op
->newline() << "break;";
1014 s
.op
->newline(-1) << "}";
1015 s
.op
->newline(-1) << "}";
1016 s
.op
->newline() << "return rc;";
1017 s
.op
->newline(-1) << "}";
1019 s
.op
->newline() << "static struct stap_utrace_probe stap_utrace_probes[] = {";
1022 // Set up 'process(PATH)' probes
1023 if (! probes_by_path
.empty())
1025 for (p_b_path_iterator it
= probes_by_path
.begin();
1026 it
!= probes_by_path
.end(); it
++)
1028 for (unsigned i
= 0; i
< it
->second
.size(); i
++)
1030 utrace_derived_probe
*p
= it
->second
[i
];
1031 emit_probe_decl(s
, p
);
1036 // Set up 'process(PID)' probes
1037 if (! probes_by_pid
.empty())
1039 for (p_b_pid_iterator it
= probes_by_pid
.begin();
1040 it
!= probes_by_pid
.end(); it
++)
1042 for (unsigned i
= 0; i
< it
->second
.size(); i
++)
1044 utrace_derived_probe
*p
= it
->second
[i
];
1045 emit_probe_decl(s
, p
);
1049 s
.op
->newline(-1) << "};";
1054 utrace_derived_probe_group::emit_module_init (systemtap_session
& s
)
1056 if (probes_by_path
.empty() && probes_by_pid
.empty())
1059 s
.op
->newline() << "/* ---- utrace probes ---- */";
1060 s
.op
->newline() << "for (i=0; i<ARRAY_SIZE(stap_utrace_probes); i++) {";
1061 s
.op
->newline(1) << "struct stap_utrace_probe *p = &stap_utrace_probes[i];";
1062 s
.op
->newline() << "probe_point = p->probe->pp;"; // for error messages
1063 s
.op
->newline() << "rc = stap_register_task_finder_target(&p->tgt);";
1065 // NB: if (rc), there is no need (XXX: nor any way) to clean up any
1066 // finders already registered, since mere registration does not
1067 // cause any utrace or memory allocation actions. That happens only
1068 // later, once the task finder engine starts running. So, for a
1069 // partial initialization requiring unwind, we need do nothing.
1070 s
.op
->newline() << "if (rc) break;";
1072 s
.op
->newline(-1) << "}";
1077 utrace_derived_probe_group::emit_module_exit (systemtap_session
& s
)
1079 if (probes_by_path
.empty() && probes_by_pid
.empty()) return;
1082 s
.op
->newline() << "/* ---- utrace probes ---- */";
1083 s
.op
->newline() << "for (i=0; i<ARRAY_SIZE(stap_utrace_probes); i++) {";
1084 s
.op
->newline(1) << "struct stap_utrace_probe *p = &stap_utrace_probes[i];";
1086 s
.op
->newline() << "if (p->engine_attached) {";
1087 s
.op
->newline(1) << "stap_utrace_detach_ops(&p->ops);";
1089 s
.op
->newline(-1) << "}";
1090 s
.op
->newline(-1) << "}";
1095 register_tapset_utrace(systemtap_session
& s
)
1097 match_node
* root
= s
.pattern_root
;
1098 derived_probe_builder
*builder
= new utrace_builder();
1100 vector
<match_node
*> roots
;
1101 roots
.push_back(root
->bind(TOK_PROCESS
));
1102 roots
.push_back(root
->bind_str(TOK_PROCESS
));
1103 roots
.push_back(root
->bind_num(TOK_PROCESS
));
1105 for (unsigned i
= 0; i
< roots
.size(); ++i
)
1107 roots
[i
]->bind(TOK_BEGIN
)
1108 ->bind_privilege(pr_all
)
1110 roots
[i
]->bind(TOK_END
)
1111 ->bind_privilege(pr_all
)
1113 roots
[i
]->bind(TOK_THREAD
)->bind(TOK_BEGIN
)
1114 ->bind_privilege(pr_all
)
1116 roots
[i
]->bind(TOK_THREAD
)->bind(TOK_END
)
1117 ->bind_privilege(pr_all
)
1119 roots
[i
]->bind(TOK_SYSCALL
)
1120 ->bind_privilege(pr_all
)
1122 roots
[i
]->bind(TOK_SYSCALL
)->bind(TOK_RETURN
)
1123 ->bind_privilege(pr_all
)
1128 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */