]> sourceware.org Git - systemtap.git/blob - tapset-utrace.cxx
Merge branch 'master' into dsmith/task_finder2
[systemtap.git] / tapset-utrace.cxx
1 // utrace tapset
2 // Copyright (C) 2005-2011 Red Hat Inc.
3 // Copyright (C) 2005-2007 Intel Corporation.
4 // Copyright (C) 2008 James.Bottomley@HansenPartnership.com
5 //
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
9 // later version.
10
11
12 #include "session.h"
13 #include "tapsets.h"
14 #include "task_finder.h"
15 #include "translate.h"
16 #include "util.h"
17
18 #include <cstring>
19 #include <string>
20
21
22 using namespace std;
23 using namespace __gnu_cxx;
24
25
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");
32
33
34 // ------------------------------------------------------------------------
35 // utrace user-space probes
36 // ------------------------------------------------------------------------
37
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 {
41 UDPF_NONE,
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
48 UDPF_NFLAGS
49 };
50
51 struct utrace_derived_probe: public derived_probe
52 {
53 bool has_path;
54 string path;
55 bool has_library;
56 string library;
57 int64_t pid;
58 enum utrace_derived_probe_flags flags;
59 bool target_symbol_seen;
60
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);
65
66 void emit_privilege_assertion (translator_output*);
67 void print_dupe_stamp(ostream& o);
68 void getargs (std::list<std::string> &arg_set) const;
69 };
70
71
72 struct utrace_derived_probe_group: public generic_dpg<utrace_derived_probe>
73 {
74 private:
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;
79 unsigned num_probes;
80 bool flags_seen[UDPF_NFLAGS];
81
82 void emit_probe_decl (systemtap_session& s, utrace_derived_probe *p);
83
84 public:
85 utrace_derived_probe_group(): num_probes(0), flags_seen() { }
86
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);
91 };
92
93
94 struct utrace_var_expanding_visitor: public var_expanding_visitor
95 {
96 utrace_var_expanding_visitor(systemtap_session& s, probe_point* l,
97 const string& pn,
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) {}
101
102 systemtap_session& sess;
103 probe_point* base_loc;
104 string probe_name;
105 enum utrace_derived_probe_flags flags;
106 bool target_symbol_seen;
107 block *add_block;
108 probe *add_probe;
109 std::map<std::string, symbol *> return_ts_map;
110
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);
115 };
116
117
118
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)
126 {
127 // FIXME: How to test for new utrace?
128 #if 0
129 if (s.kernel_config["CONFIG_UTRACE"] != string("y"))
130 throw semantic_error (_("process probes not available without kernel CONFIG_UTRACE"));
131 #endif
132
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;
137
138 // If during target-variable-expanding the probe, we added a new block
139 // of code, add it to the start of the probe.
140 if (v.add_block)
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.
144 if (v.add_probe)
145 {
146 stapfile *f = new stapfile;
147 f->probes.push_back(v.add_probe);
148 s.files.push_back(f);
149 }
150
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.
155
156 vector<probe_point::component*> comps;
157 if (hp)
158 comps.push_back (new probe_point::component(TOK_PROCESS, new literal_string(path)));
159 else if (pid != 0)
160 comps.push_back (new probe_point::component(TOK_PROCESS, new literal_number(pid)));
161 else
162 comps.push_back (new probe_point::component(TOK_PROCESS));
163
164 switch (flags)
165 {
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));
169 break;
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));
173 break;
174 case UDPF_SYSCALL:
175 comps.push_back (new probe_point::component(TOK_SYSCALL));
176 break;
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));
180 break;
181 case UDPF_BEGIN:
182 comps.push_back (new probe_point::component(TOK_BEGIN));
183 break;
184 case UDPF_END:
185 comps.push_back (new probe_point::component(TOK_END));
186 break;
187 default:
188 assert (0);
189 }
190
191 // Overwrite it.
192 this->sole_location()->components = comps;
193 }
194
195
196 void
197 utrace_derived_probe::join_group (systemtap_session& s)
198 {
199 if (! s.utrace_derived_probes)
200 {
201 s.utrace_derived_probes = new utrace_derived_probe_group ();
202 }
203 s.utrace_derived_probes->enroll (this);
204
205 enable_task_finder(s);
206 }
207
208
209 void
210 utrace_derived_probe::emit_privilege_assertion (translator_output* o)
211 {
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
217 // original owner.
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)
221 return;
222
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
225 // as a safety net.
226 emit_process_owner_assertion (o);
227 }
228
229 void
230 utrace_derived_probe::print_dupe_stamp(ostream& o)
231 {
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
237 // original owner.
238 // Unprivileged users must use check is_myproc() from within any
239 // process.end variant in their script before doing anything "dangerous".
240 //
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);
245 else
246 print_dupe_stamp_unprivileged_process_owner (o);
247 }
248
249 void
250 utrace_derived_probe::getargs(std::list<std::string> &arg_set) const
251 {
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");
259 }
260
261 void
262 utrace_var_expanding_visitor::visit_target_symbol_cached (target_symbol* e)
263 {
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();
268
269 // Check and make sure we haven't already seen this target
270 // variable in this return probe. If we have, just return our
271 // last replacement.
272 map<string, symbol *>::iterator i = return_ts_map.find(ts_name);
273 if (i != return_ts_map.end())
274 {
275 provide (i->second);
276 return;
277 }
278
279 // We've got to do several things here to handle target
280 // variables in return probes.
281
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:
287 //
288 // _utrace_tvar_{name}_{num}
289 string aname = (string("_utrace_tvar_")
290 + e->name.substr(1)
291 + "_" + lex_cast(tick++));
292 vardecl* vd = new vardecl;
293 vd->name = aname;
294 vd->tok = e->tok;
295 sess.globals.push_back (vd);
296
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:
302 //
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]
307
308 // (2a) Synthesize the tid temporary expression, which will look
309 // like this:
310 //
311 // _utrace_tvar_tid = tid()
312 symbol* tidsym = new symbol;
313 tidsym->name = string("_utrace_tvar_tid");
314 tidsym->tok = e->tok;
315
316 if (add_block == NULL)
317 {
318 add_block = new block;
319 add_block->tok = e->tok;
320
321 // Synthesize a functioncall to grab the thread id.
322 functioncall* fc = new functioncall;
323 fc->tok = e->tok;
324 fc->function = string("tid");
325
326 // Assign the tid to '_utrace_tvar_tid'.
327 assignment* a = new assignment;
328 a->tok = e->tok;
329 a->op = "=";
330 a->left = tidsym;
331 a->right = fc;
332
333 expr_statement* es = new expr_statement;
334 es->tok = e->tok;
335 es->value = a;
336 add_block->statements.push_back (es);
337 }
338
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:
342 //
343 // _utrace_tvar_{name}_{num}_tmp
344 // = _utrace_tvar_{name}_{num}[_utrace_tvar_tid]
345
346 arrayindex* ai_tvar = new arrayindex;
347 ai_tvar->tok = e->tok;
348
349 symbol* sym = new symbol;
350 sym->name = aname;
351 sym->tok = e->tok;
352 ai_tvar->base = sym;
353
354 ai_tvar->indexes.push_back(tidsym);
355
356 symbol* tmpsym = new symbol;
357 tmpsym->name = aname + "_tmp";
358 tmpsym->tok = e->tok;
359
360 assignment* a = new assignment;
361 a->tok = e->tok;
362 a->op = "=";
363 a->left = tmpsym;
364 a->right = ai_tvar;
365
366 expr_statement* es = new expr_statement;
367 es->tok = e->tok;
368 es->value = a;
369
370 add_block->statements.push_back (es);
371
372 // (2c) Delete the array value. It will look like this:
373 //
374 // delete _utrace_tvar_{name}_{num}[_utrace_tvar_tid]
375
376 delete_statement* ds = new delete_statement;
377 ds->tok = e->tok;
378 ds->value = ai_tvar;
379 add_block->statements.push_back (ds);
380
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
383 // look like this:
384 //
385 // probe process(PATH_OR_PID).syscall {
386 // _utrace_tvar_tid = tid()
387 // _utrace_tvar_{name}_{num}[_utrace_tvar_tid] = ${param}
388 // }
389 //
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.
393
394 if (add_probe == NULL)
395 {
396 add_probe = new probe;
397 add_probe->tok = e->tok;
398
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"
402 // component.
403 probe_point* pp = new probe_point;
404 for (unsigned c = 0; c < base_loc->components.size(); c++)
405 {
406 if (base_loc->components[c]->functor == "return")
407 break;
408 else
409 pp->components.push_back(base_loc->components[c]);
410 }
411 pp->optional = base_loc->optional;
412 add_probe->locations.push_back(pp);
413
414 add_probe->body = new block;
415 add_probe->body->tok = e->tok;
416
417 // Synthesize a functioncall to grab the thread id.
418 functioncall* fc = new functioncall;
419 fc->tok = e->tok;
420 fc->function = string("tid");
421
422 // Assign the tid to '_utrace_tvar_tid'.
423 assignment* a = new assignment;
424 a->tok = e->tok;
425 a->op = "=";
426 a->left = tidsym;
427 a->right = fc;
428
429 expr_statement* es = new expr_statement;
430 es->tok = e->tok;
431 es->value = a;
432 add_probe->body = new block(add_probe->body, es);
433
434 vardecl* vd = new vardecl;
435 vd->tok = e->tok;
436 vd->name = tidsym->name;
437 vd->type = pe_long;
438 vd->set_arity(0, e->tok);
439 add_probe->locals.push_back(vd);
440 }
441
442 // Save the value, like this:
443 //
444 // _utrace_tvar_{name}_{num}[_utrace_tvar_tid] = ${param}
445 a = new assignment;
446 a->tok = e->tok;
447 a->op = "=";
448 a->left = ai_tvar;
449 a->right = e;
450
451 es = new expr_statement;
452 es->tok = e->tok;
453 es->value = a;
454
455 add_probe->body = new block(add_probe->body, es);
456
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
459 // symbol.
460 provide (tmpsym);
461
462 // (5) Remember this replacement since we might be able to reuse
463 // it later if the same return probe references this target
464 // symbol again.
465 return_ts_map[ts_name] = tmpsym;
466 return;
467 }
468
469
470 void
471 utrace_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
472 {
473 if (flags != UDPF_SYSCALL)
474 throw semantic_error (_("only \"process(PATH_OR_PID).syscall\" support $argN or $$parms."), e->tok);
475
476 if (e->name == "$$parms")
477 {
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);
482
483 target_symbol_seen = true;
484
485 for (unsigned i = 0; i < 6; ++i)
486 {
487 if (i > 0)
488 pf->raw_components += " ";
489 pf->raw_components += "$arg" + lex_cast(i+1);
490 target_symbol *tsym = new target_symbol;
491 tsym->tok = e->tok;
492 tsym->name = "$arg" + lex_cast(i+1);
493 tsym->saved_conversion_error = 0;
494 pf->raw_components += "=%#x"; //FIXME: missing type info
495
496 functioncall* n = new functioncall; //same as the following
497 n->tok = e->tok;
498 n->function = "_utrace_syscall_arg";
499 n->referent = 0;
500 literal_number *num = new literal_number(i);
501 num->tok = e->tok;
502 n->args.push_back(num);
503
504 pf->args.push_back(n);
505 }
506 pf->components = print_format::string_to_components(pf->raw_components);
507
508 provide (pf);
509 }
510 else // $argN
511 {
512 string argnum_s = e->name.substr(4,e->name.length()-4);
513 int argnum = 0;
514 try
515 {
516 argnum = lex_cast<int>(argnum_s);
517 }
518 catch (const runtime_error& f) // non-integral $arg suffix: e.g. $argKKKSDF
519 {
520 throw semantic_error (_("invalid syscall argument number (1-6)"), e->tok);
521 }
522
523 e->assert_no_components("utrace");
524
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);
528
529 bool lvalue = is_active_lvalue(e);
530 if (lvalue)
531 throw semantic_error(_("utrace '$argN' variable is read-only"), e->tok);
532
533 // Remember that we've seen a target variable.
534 target_symbol_seen = true;
535
536 // We're going to substitute a synthesized '_utrace_syscall_arg'
537 // function call for the '$argN' reference.
538 functioncall* n = new functioncall;
539 n->tok = e->tok;
540 n->function = "_utrace_syscall_arg";
541 n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session
542
543 literal_number *num = new literal_number(argnum - 1);
544 num->tok = e->tok;
545 n->args.push_back(num);
546
547 provide (n);
548 }
549 }
550
551 void
552 utrace_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
553 {
554 const string& sname = e->name;
555
556 e->assert_no_components("utrace");
557
558 bool lvalue = is_active_lvalue(e);
559 if (lvalue)
560 throw semantic_error(_F("utrace '%s' variable is read-only", sname.c_str()), e->tok);
561
562 string fname;
563 if (sname == "$return")
564 {
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";
568 }
569 else if (sname == "$syscall")
570 {
571 // If we've got a syscall entry probe, we can just call the
572 // right function.
573 if (flags == UDPF_SYSCALL) {
574 fname = "_utrace_syscall_nr";
575 }
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.
581 else {
582 visit_target_symbol_cached (e);
583
584 // Remember that we've seen a target variable.
585 target_symbol_seen = true;
586 return;
587 }
588 }
589 else
590 {
591 throw semantic_error (_("unknown target variable"), e->tok);
592 }
593
594 // Remember that we've seen a target variable.
595 target_symbol_seen = true;
596
597 // We're going to substitute a synthesized '_utrace_syscall_nr'
598 // function call for the '$syscall' reference.
599 functioncall* n = new functioncall;
600 n->tok = e->tok;
601 n->function = fname;
602 n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session
603
604 provide (n);
605 }
606
607 void
608 utrace_var_expanding_visitor::visit_target_symbol (target_symbol* e)
609 {
610 assert(e->name.size() > 0 && e->name[0] == '$');
611
612 try
613 {
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"),
617 e->tok);
618
619 if (e->addressof)
620 throw semantic_error(_("cannot take address of utrace variable"), e->tok);
621
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);
626 else
627 throw semantic_error (_("invalid target symbol for utrace probe,"
628 " $syscall, $return, $argN or $$parms expected"),
629 e->tok);
630 }
631 catch (const semantic_error &er)
632 {
633 e->chain (er);
634 provide(e);
635 return;
636 }
637 }
638
639
640 struct utrace_builder: public derived_probe_builder
641 {
642 utrace_builder() {}
643 virtual void build(systemtap_session & sess,
644 probe * base,
645 probe_point * location,
646 literal_map_t const & parameters,
647 vector<derived_probe *> & finished_results)
648 {
649 string path;
650 int64_t pid;
651
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;
655
656 if (has_null_param (parameters, TOK_THREAD))
657 {
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;
662 }
663 else if (has_null_param (parameters, TOK_SYSCALL))
664 {
665 if (has_null_param (parameters, TOK_RETURN))
666 flags = UDPF_SYSCALL_RETURN;
667 else
668 flags = UDPF_SYSCALL;
669 }
670 else if (has_null_param (parameters, TOK_BEGIN))
671 flags = UDPF_BEGIN;
672 else if (has_null_param (parameters, TOK_END))
673 flags = UDPF_END;
674
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)
678 {
679 has_path = false;
680 path.clear();
681 has_pid = true;
682 pid = 0;
683 }
684 else if (has_path)
685 {
686 path = find_executable (path);
687 sess.unwindsym_modules.insert (path);
688 }
689 else if (has_pid)
690 {
691 // We can't probe 'init' (pid 1). XXX: where does this limitation come from?
692 if (pid < 2)
693 throw semantic_error (_("process pid must be greater than 1"),
694 location->components.front()->tok);
695
696 // XXX: could we use /proc/$pid/exe in unwindsym_modules and elsewhere?
697 }
698
699 finished_results.push_back(new utrace_derived_probe(sess, base, location,
700 has_path, path, pid,
701 flags));
702 }
703 };
704
705
706 void
707 utrace_derived_probe_group::enroll (utrace_derived_probe* p)
708 {
709 if (p->has_path)
710 probes_by_path[p->path].push_back(p);
711 else
712 probes_by_pid[p->pid].push_back(p);
713 num_probes++;
714 flags_seen[p->flags] = true;
715
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.
719 }
720
721
722 void
723 utrace_derived_probe_group::emit_probe_decl (systemtap_session& s,
724 utrace_derived_probe *p)
725 {
726 s.op->newline() << "{";
727 s.op->line() << " .tgt={";
728
729 if (p->has_path)
730 {
731 s.op->line() << " .procname=\"" << p->path << "\",";
732 s.op->line() << " .pid=0,";
733 }
734 else
735 {
736 s.op->line() << " .procname=NULL,";
737 s.op->line() << " .pid=" << p->pid << ",";
738 }
739
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) << ",";
746
747 // Handle flags
748 switch (p->flags)
749 {
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),";
754 break;
755 case UDPF_THREAD_BEGIN: // thread begin
756 s.op->line() << " .flags=(UDPF_THREAD_BEGIN),";
757 break;
758
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),";
764 break;
765 case UDPF_THREAD_END: // thread end
766 s.op->line() << " .flags=(UDPF_THREAD_END),";
767 break;
768
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.
773 case UDPF_SYSCALL:
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)),";
777 break;
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)),";
782 break;
783
784 case UDPF_NONE:
785 s.op->line() << " .flags=(UDPF_NONE),";
786 s.op->line() << " .ops={ },";
787 s.op->line() << " .events=0,";
788 break;
789 default:
790 throw semantic_error ("bad utrace probe flag");
791 break;
792 }
793 s.op->line() << " .engine_attached=0,";
794 s.op->line() << " },";
795 }
796
797
798 void
799 utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
800 {
801 if (probes_by_path.empty() && probes_by_pid.empty())
802 return;
803
804 s.op->newline();
805 s.op->newline() << "/* ---- utrace probes ---- */";
806
807 s.op->newline() << "enum utrace_derived_probe_flags {";
808 s.op->indent(1);
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) << "};";
818
819 s.op->newline() << "struct stap_utrace_probe {";
820 s.op->indent(1);
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) << "};";
828
829
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])
834 {
835 s.op->newline() << "static void stap_utrace_probe_handler(struct task_struct *tsk, struct stap_utrace_probe *p) {";
836 s.op->indent(1);
837
838 common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "p->probe",
839 "_STP_PROBE_HANDLER_UTRACE");
840
841 // call probe function
842 s.op->newline() << "(*p->probe->ph) (c);";
843 common_probe_entryfn_epilogue (s.op);
844
845 s.op->newline() << "return;";
846 s.op->newline(-1) << "}";
847 }
848
849 // Output handler function for SYSCALL_ENTRY and SYSCALL_EXIT events
850 if (flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN])
851 {
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";
861
862 s.op->indent(1);
863 s.op->newline() << "struct stap_utrace_probe *p = (struct stap_utrace_probe *)engine->data;";
864
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;";
869
870 // call probe function
871 s.op->newline() << "(*p->probe->ph) (c);";
872 common_probe_entryfn_epilogue (s.op);
873
874 s.op->newline() << "if ((atomic_read (&session_state) != STAP_SESSION_STARTING) && (atomic_read (&session_state) != STAP_SESSION_RUNNING)) {";
875 s.op->indent(1);
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) << "}";
881 }
882
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) {";
886 s.op->indent(1);
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;";
890
891 s.op->newline() << "if (register_p) {";
892 s.op->indent(1);
893
894 s.op->newline() << "switch (p->flags) {";
895 s.op->indent(1);
896
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])
902 {
903 s.op->newline() << "case UDPF_BEGIN:";
904 s.op->indent(1);
905 s.op->newline() << "if (process_p) {";
906 s.op->indent(1);
907 s.op->newline() << "stap_utrace_probe_handler(tsk, p);";
908 s.op->newline(-1) << "}";
909 s.op->newline() << "break;";
910 s.op->indent(-1);
911 }
912 if (flags_seen[UDPF_THREAD_BEGIN])
913 {
914 s.op->newline() << "case UDPF_THREAD_BEGIN:";
915 s.op->indent(1);
916 s.op->newline() << "if (! process_p) {";
917 s.op->indent(1);
918 s.op->newline() << "stap_utrace_probe_handler(tsk, p);";
919 s.op->newline(-1) << "}";
920 s.op->newline() << "break;";
921 s.op->indent(-1);
922 }
923
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])
927 {
928 s.op->newline() << "case UDPF_END:";
929 s.op->newline() << "case UDPF_THREAD_END:";
930 s.op->indent(1);
931 s.op->newline() << "break;";
932 s.op->indent(-1);
933 }
934
935 // Attach an engine for SYSCALL_ENTRY and SYSCALL_EXIT events.
936 if (flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN])
937 {
938 s.op->newline() << "case UDPF_SYSCALL:";
939 s.op->newline() << "case UDPF_SYSCALL_RETURN:";
940 s.op->indent(1);
941 s.op->newline() << "rc = stap_utrace_attach(tsk, &p->ops, p, p->events);";
942 s.op->newline() << "if (rc == 0) {";
943 s.op->indent(1);
944 s.op->newline() << "p->engine_attached = 1;";
945 s.op->newline(-1) << "}";
946 s.op->newline() << "break;";
947 s.op->indent(-1);
948 }
949
950 s.op->newline() << "default:";
951 s.op->indent(1);
952 s.op->newline() << "_stp_error(\"unhandled flag value %d at %s:%d\", p->flags, __FUNCTION__, __LINE__);";
953 s.op->newline() << "break;";
954 s.op->indent(-1);
955 s.op->newline(-1) << "}";
956 s.op->newline(-1) << "}";
957
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 {";
962 s.op->indent(1);
963 s.op->newline() << "switch (p->flags) {";
964 s.op->indent(1);
965 // For end probes, go ahead and call the probe directly.
966 if (flags_seen[UDPF_END])
967 {
968 s.op->newline() << "case UDPF_END:";
969 s.op->indent(1);
970 s.op->newline() << "if (process_p) {";
971 s.op->indent(1);
972 s.op->newline() << "stap_utrace_probe_handler(tsk, p);";
973 s.op->newline(-1) << "}";
974 s.op->newline() << "break;";
975 s.op->indent(-1);
976 }
977 if (flags_seen[UDPF_THREAD_END])
978 {
979 s.op->newline() << "case UDPF_THREAD_END:";
980 s.op->indent(1);
981 s.op->newline() << "if (! process_p) {";
982 s.op->indent(1);
983 s.op->newline() << "stap_utrace_probe_handler(tsk, p);";
984 s.op->newline(-1) << "}";
985 s.op->newline() << "break;";
986 s.op->indent(-1);
987 }
988
989 // For begin/thread_begin probes, we don't need to do anything.
990 if (flags_seen[UDPF_BEGIN] || flags_seen[UDPF_THREAD_BEGIN])
991 {
992 s.op->newline() << "case UDPF_BEGIN:";
993 s.op->newline() << "case UDPF_THREAD_BEGIN:";
994 s.op->indent(1);
995 s.op->newline() << "break;";
996 s.op->indent(-1);
997 }
998
999 if (flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN])
1000 {
1001 s.op->newline() << "case UDPF_SYSCALL:";
1002 s.op->newline() << "case UDPF_SYSCALL_RETURN:";
1003 s.op->indent(1);
1004 s.op->newline() << "stap_utrace_detach(tsk, &p->ops);";
1005 s.op->newline() << "break;";
1006 s.op->indent(-1);
1007 }
1008
1009 s.op->newline() << "default:";
1010 s.op->indent(1);
1011 s.op->newline() << "_stp_error(\"unhandled flag value %d at %s:%d\", p->flags, __FUNCTION__, __LINE__);";
1012 s.op->newline() << "break;";
1013 s.op->indent(-1);
1014 s.op->newline(-1) << "}";
1015 s.op->newline(-1) << "}";
1016 s.op->newline() << "return rc;";
1017 s.op->newline(-1) << "}";
1018
1019 s.op->newline() << "static struct stap_utrace_probe stap_utrace_probes[] = {";
1020 s.op->indent(1);
1021
1022 // Set up 'process(PATH)' probes
1023 if (! probes_by_path.empty())
1024 {
1025 for (p_b_path_iterator it = probes_by_path.begin();
1026 it != probes_by_path.end(); it++)
1027 {
1028 for (unsigned i = 0; i < it->second.size(); i++)
1029 {
1030 utrace_derived_probe *p = it->second[i];
1031 emit_probe_decl(s, p);
1032 }
1033 }
1034 }
1035
1036 // Set up 'process(PID)' probes
1037 if (! probes_by_pid.empty())
1038 {
1039 for (p_b_pid_iterator it = probes_by_pid.begin();
1040 it != probes_by_pid.end(); it++)
1041 {
1042 for (unsigned i = 0; i < it->second.size(); i++)
1043 {
1044 utrace_derived_probe *p = it->second[i];
1045 emit_probe_decl(s, p);
1046 }
1047 }
1048 }
1049 s.op->newline(-1) << "};";
1050 }
1051
1052
1053 void
1054 utrace_derived_probe_group::emit_module_init (systemtap_session& s)
1055 {
1056 if (probes_by_path.empty() && probes_by_pid.empty())
1057 return;
1058
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);";
1064
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;";
1071
1072 s.op->newline(-1) << "}";
1073 }
1074
1075
1076 void
1077 utrace_derived_probe_group::emit_module_exit (systemtap_session& s)
1078 {
1079 if (probes_by_path.empty() && probes_by_pid.empty()) return;
1080
1081 s.op->newline();
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];";
1085
1086 s.op->newline() << "if (p->engine_attached) {";
1087 s.op->newline(1) << "stap_utrace_detach_ops(&p->ops);";
1088
1089 s.op->newline(-1) << "}";
1090 s.op->newline(-1) << "}";
1091 }
1092
1093
1094 void
1095 register_tapset_utrace(systemtap_session& s)
1096 {
1097 match_node* root = s.pattern_root;
1098 derived_probe_builder *builder = new utrace_builder();
1099
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));
1104
1105 for (unsigned i = 0; i < roots.size(); ++i)
1106 {
1107 roots[i]->bind(TOK_BEGIN)
1108 ->bind_privilege(pr_all)
1109 ->bind(builder);
1110 roots[i]->bind(TOK_END)
1111 ->bind_privilege(pr_all)
1112 ->bind(builder);
1113 roots[i]->bind(TOK_THREAD)->bind(TOK_BEGIN)
1114 ->bind_privilege(pr_all)
1115 ->bind(builder);
1116 roots[i]->bind(TOK_THREAD)->bind(TOK_END)
1117 ->bind_privilege(pr_all)
1118 ->bind(builder);
1119 roots[i]->bind(TOK_SYSCALL)
1120 ->bind_privilege(pr_all)
1121 ->bind(builder);
1122 roots[i]->bind(TOK_SYSCALL)->bind(TOK_RETURN)
1123 ->bind_privilege(pr_all)
1124 ->bind(builder);
1125 }
1126 }
1127
1128 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.095176 seconds and 6 git commands to generate.