]> sourceware.org Git - systemtap.git/blame - tapset-utrace.cxx
PR32209: Define the __COUNT_ARGS macro conditionally
[systemtap.git] / tapset-utrace.cxx
CommitLineData
b84779a5 1// utrace tapset
ef36f781 2// Copyright (C) 2005-2014 Red Hat Inc.
b84779a5 3// Copyright (C) 2005-2007 Intel Corporation.
b84779a5
JS
4//
5// This file is part of systemtap, and is free software. You can
6// redistribute it and/or modify it under the terms of the GNU General
7// Public License (GPL); either version 2, or (at your option) any
8// later version.
9
10
11#include "session.h"
12#include "tapsets.h"
13#include "task_finder.h"
f31a77f5 14#include "tapset-dynprobe.h"
b84779a5
JS
15#include "translate.h"
16#include "util.h"
17
18#include <cstring>
19#include <string>
20
21
22using namespace std;
23using namespace __gnu_cxx;
24
25
4627ed58
JS
26static const string TOK_PROCESS("process");
27static const string TOK_BEGIN("begin");
28static const string TOK_END("end");
29static const string TOK_THREAD("thread");
30static const string TOK_SYSCALL("syscall");
31static const string TOK_RETURN("return");
b84779a5
JS
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).
40enum 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
51struct utrace_derived_probe: public derived_probe
52{
53 bool has_path;
45a63356 54 interned_string path;
63b4fd14 55 bool has_library;
45a63356 56 interned_string library;
b84779a5
JS
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,
45a63356 62 bool hp, interned_string pn, int64_t pd,
bbafcb1e 63 enum utrace_derived_probe_flags f);
b84779a5 64 void join_group (systemtap_session& s);
2865d17a 65
42e38653 66 void emit_privilege_assertion (translator_output*);
8f6d8c2b 67 void print_dupe_stamp(ostream& o);
5a195cd5 68 void getargs (std::list<std::string> &arg_set) const;
b84779a5
JS
69};
70
71
72struct utrace_derived_probe_group: public generic_dpg<utrace_derived_probe>
73{
74private:
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
f31a77f5
DS
82 // Using the linux backend
83 void emit_linux_probe_decl (systemtap_session& s, utrace_derived_probe *p);
84 void emit_module_linux_decls (systemtap_session& s);
85 void emit_module_linux_init (systemtap_session& s);
86 void emit_module_linux_exit (systemtap_session& s);
87
88 // Using the dyninst backend (via stapdyn)
89 void emit_dyninst_probe_decl (systemtap_session& s, const string& path,
90 utrace_derived_probe *p);
91 void emit_module_dyninst_decls (systemtap_session& s);
92 void emit_module_dyninst_init (systemtap_session& s);
93 void emit_module_dyninst_exit (systemtap_session& s);
b84779a5
JS
94
95public:
96 utrace_derived_probe_group(): num_probes(0), flags_seen() { }
97
98 void enroll (utrace_derived_probe* probe);
99 void emit_module_decls (systemtap_session& s);
100 void emit_module_init (systemtap_session& s);
101 void emit_module_exit (systemtap_session& s);
40dbe72a
SM
102
103 friend void warn_for_bpf(systemtap_session& s,
104 utrace_derived_probe_group *upg,
105 const std::string& kind);
b84779a5
JS
106};
107
108
109struct utrace_var_expanding_visitor: public var_expanding_visitor
110{
111 utrace_var_expanding_visitor(systemtap_session& s, probe_point* l,
b84779a5 112 enum utrace_derived_probe_flags f):
16aa72d9
FCE
113 var_expanding_visitor (s),
114 base_loc (l), flags (f),
b84779a5
JS
115 target_symbol_seen (false), add_block(NULL), add_probe(NULL) {}
116
b84779a5 117 probe_point* base_loc;
b84779a5
JS
118 enum utrace_derived_probe_flags flags;
119 bool target_symbol_seen;
120 block *add_block;
121 probe *add_probe;
122 std::map<std::string, symbol *> return_ts_map;
123
124 void visit_target_symbol_arg (target_symbol* e);
125 void visit_target_symbol_context (target_symbol* e);
126 void visit_target_symbol_cached (target_symbol* e);
127 void visit_target_symbol (target_symbol* e);
128};
129
130
131
132utrace_derived_probe::utrace_derived_probe (systemtap_session &s,
133 probe* p, probe_point* l,
45a63356 134 bool hp, interned_string pn, int64_t pd,
bbafcb1e 135 enum utrace_derived_probe_flags f):
4c5d1300 136 derived_probe (p, l, true /* .components soon rewritten */ ),
74fe61bc 137 has_path(hp), path(pn), has_library(false), pid(pd), flags(f),
b84779a5
JS
138 target_symbol_seen(false)
139{
100c0a15
JS
140 if (!s.runtime_usermode_p())
141 check_process_probe_kernel_support(s);
e34d5d13 142
b84779a5 143 // Expand local variables in the probe body
70719cbf 144 utrace_var_expanding_visitor v (s, l, flags);
16aa72d9 145 var_expand_const_fold_loop (s, this->body, v);
b84779a5
JS
146 target_symbol_seen = v.target_symbol_seen;
147
148 // If during target-variable-expanding the probe, we added a new block
149 // of code, add it to the start of the probe.
150 if (v.add_block)
151 this->body = new block(v.add_block, this->body);
152 // If when target-variable-expanding the probe, we added a new
153 // probe, add it in a new file to the list of files to be processed.
154 if (v.add_probe)
155 {
156 stapfile *f = new stapfile;
157 f->probes.push_back(v.add_probe);
158 s.files.push_back(f);
159 }
160
161 // Reset the sole element of the "locations" vector as a
162 // "reverse-engineered" form of the incoming (q.base_loc) probe
163 // point. This allows a user to see what program etc.
164 // number any particular match of the wildcards.
165
166 vector<probe_point::component*> comps;
167 if (hp)
168 comps.push_back (new probe_point::component(TOK_PROCESS, new literal_string(path)));
169 else if (pid != 0)
170 comps.push_back (new probe_point::component(TOK_PROCESS, new literal_number(pid)));
171 else
172 comps.push_back (new probe_point::component(TOK_PROCESS));
173
174 switch (flags)
175 {
176 case UDPF_THREAD_BEGIN:
177 comps.push_back (new probe_point::component(TOK_THREAD));
178 comps.push_back (new probe_point::component(TOK_BEGIN));
179 break;
180 case UDPF_THREAD_END:
181 comps.push_back (new probe_point::component(TOK_THREAD));
182 comps.push_back (new probe_point::component(TOK_END));
183 break;
184 case UDPF_SYSCALL:
185 comps.push_back (new probe_point::component(TOK_SYSCALL));
186 break;
187 case UDPF_SYSCALL_RETURN:
188 comps.push_back (new probe_point::component(TOK_SYSCALL));
189 comps.push_back (new probe_point::component(TOK_RETURN));
190 break;
191 case UDPF_BEGIN:
192 comps.push_back (new probe_point::component(TOK_BEGIN));
193 break;
194 case UDPF_END:
195 comps.push_back (new probe_point::component(TOK_END));
196 break;
197 default:
198 assert (0);
199 }
200
201 // Overwrite it.
202 this->sole_location()->components = comps;
203}
204
205
206void
207utrace_derived_probe::join_group (systemtap_session& s)
208{
209 if (! s.utrace_derived_probes)
210 {
211 s.utrace_derived_probes = new utrace_derived_probe_group ();
212 }
213 s.utrace_derived_probes->enroll (this);
ca6d3b0f 214 this->group = s.utrace_derived_probes;
b84779a5 215
f31a77f5
DS
216 if (s.runtime_usermode_p())
217 enable_dynprobes(s);
218 else
219 enable_task_finder(s);
b84779a5
JS
220}
221
222
2865d17a 223void
42e38653 224utrace_derived_probe::emit_privilege_assertion (translator_output* o)
2865d17a 225{
54b76f09
DB
226 // Process end probes can fire for unprivileged users even if the process
227 // does not belong to the user. On example is that process.end will fire
228 // at the end of a process which executes execve on an executable which
229 // has the setuid bit set. When the setuid executable ends, the process.end
230 // will fire even though the owner of the process is different than the
231 // original owner.
232 // Unprivileged users must use check is_myproc() from within any
233 // process.end variant in their script before doing anything "dangerous".
2865d17a
DB
234 if (flags == UDPF_END)
235 return;
236
54b76f09
DB
237 // Other process probes should only fire for unprivileged users in the
238 // context of processes which they own. Generate an assertion to this effect
239 // as a safety net.
2865d17a
DB
240 emit_process_owner_assertion (o);
241}
242
8f6d8c2b
DB
243void
244utrace_derived_probe::print_dupe_stamp(ostream& o)
245{
54b76f09
DB
246 // Process end probes can fire for unprivileged users even if the process
247 // does not belong to the user. On example is that process.end will fire
248 // at the end of a process which executes execve on an executable which
249 // has the setuid bit set. When the setuid executable ends, the process.end
250 // will fire even though the owner of the process is different than the
251 // original owner.
252 // Unprivileged users must use check is_myproc() from within any
253 // process.end variant in their script before doing anything "dangerous".
254 //
255 // Other process probes should only fire for unprivileged users in the
8f6d8c2b
DB
256 // context of processes which they own.
257 if (flags == UDPF_END)
258 print_dupe_stamp_unprivileged (o);
259 else
260 print_dupe_stamp_unprivileged_process_owner (o);
261}
262
5a195cd5
LB
263void
264utrace_derived_probe::getargs(std::list<std::string> &arg_set) const
265{
266 arg_set.push_back("$syscall:long");
267 arg_set.push_back("$arg1:long");
268 arg_set.push_back("$arg2:long");
269 arg_set.push_back("$arg3:long");
270 arg_set.push_back("$arg4:long");
271 arg_set.push_back("$arg5:long");
272 arg_set.push_back("$arg6:long");
273}
2865d17a 274
b84779a5
JS
275void
276utrace_var_expanding_visitor::visit_target_symbol_cached (target_symbol* e)
277{
278 // Get the full name of the target symbol.
279 stringstream ts_name_stream;
280 e->print(ts_name_stream);
281 string ts_name = ts_name_stream.str();
282
283 // Check and make sure we haven't already seen this target
284 // variable in this return probe. If we have, just return our
285 // last replacement.
286 map<string, symbol *>::iterator i = return_ts_map.find(ts_name);
287 if (i != return_ts_map.end())
288 {
289 provide (i->second);
290 return;
291 }
292
293 // We've got to do several things here to handle target
294 // variables in return probes.
295
296 // (1) Synthesize a global array which is the cache of the
297 // target variable value. We don't need a nesting level counter
298 // like the dwarf_var_expanding_visitor::visit_target_symbol()
299 // does since a particular thread can only be in one system
300 // calls at a time. The array will look like this:
301 //
302 // _utrace_tvar_{name}_{num}
38bf68a8 303 string aname = (string("__global_utrace_tvar_")
cc9001af 304 + e->sym_name()
aca66a36 305 + "_" + lex_cast(tick++));
b84779a5
JS
306 vardecl* vd = new vardecl;
307 vd->name = aname;
308 vd->tok = e->tok;
309 sess.globals.push_back (vd);
310
311 // (2) Create a new code block we're going to insert at the
312 // beginning of this probe to get the cached value into a
313 // temporary variable. We'll replace the target variable
314 // reference with the temporary variable reference. The code
315 // will look like this:
316 //
317 // _utrace_tvar_tid = tid()
318 // _utrace_tvar_{name}_{num}_tmp
319 // = _utrace_tvar_{name}_{num}[_utrace_tvar_tid]
320 // delete _utrace_tvar_{name}_{num}[_utrace_tvar_tid]
321
322 // (2a) Synthesize the tid temporary expression, which will look
323 // like this:
324 //
325 // _utrace_tvar_tid = tid()
326 symbol* tidsym = new symbol;
327 tidsym->name = string("_utrace_tvar_tid");
328 tidsym->tok = e->tok;
329
330 if (add_block == NULL)
331 {
332 add_block = new block;
333 add_block->tok = e->tok;
334
335 // Synthesize a functioncall to grab the thread id.
336 functioncall* fc = new functioncall;
337 fc->tok = e->tok;
338 fc->function = string("tid");
339
340 // Assign the tid to '_utrace_tvar_tid'.
341 assignment* a = new assignment;
342 a->tok = e->tok;
343 a->op = "=";
344 a->left = tidsym;
345 a->right = fc;
346
347 expr_statement* es = new expr_statement;
348 es->tok = e->tok;
349 es->value = a;
350 add_block->statements.push_back (es);
351 }
352
353 // (2b) Synthesize an array reference and assign it to a
354 // temporary variable (that we'll use as replacement for the
355 // target variable reference). It will look like this:
356 //
357 // _utrace_tvar_{name}_{num}_tmp
358 // = _utrace_tvar_{name}_{num}[_utrace_tvar_tid]
359
360 arrayindex* ai_tvar = new arrayindex;
361 ai_tvar->tok = e->tok;
362
363 symbol* sym = new symbol;
364 sym->name = aname;
365 sym->tok = e->tok;
366 ai_tvar->base = sym;
367
368 ai_tvar->indexes.push_back(tidsym);
369
370 symbol* tmpsym = new symbol;
371 tmpsym->name = aname + "_tmp";
372 tmpsym->tok = e->tok;
373
374 assignment* a = new assignment;
375 a->tok = e->tok;
376 a->op = "=";
377 a->left = tmpsym;
378 a->right = ai_tvar;
379
380 expr_statement* es = new expr_statement;
381 es->tok = e->tok;
382 es->value = a;
383
384 add_block->statements.push_back (es);
385
386 // (2c) Delete the array value. It will look like this:
387 //
388 // delete _utrace_tvar_{name}_{num}[_utrace_tvar_tid]
389
390 delete_statement* ds = new delete_statement;
391 ds->tok = e->tok;
392 ds->value = ai_tvar;
393 add_block->statements.push_back (ds);
394
395 // (3) We need an entry probe that saves the value for us in the
396 // global array we created. Create the entry probe, which will
397 // look like this:
398 //
399 // probe process(PATH_OR_PID).syscall {
400 // _utrace_tvar_tid = tid()
401 // _utrace_tvar_{name}_{num}[_utrace_tvar_tid] = ${param}
402 // }
403 //
404 // Why the temporary for tid()? If we end up caching more
405 // than one target variable, we can reuse the temporary instead
406 // of calling tid() multiple times.
407
408 if (add_probe == NULL)
409 {
410 add_probe = new probe;
411 add_probe->tok = e->tok;
412
413 // We need the name of the current probe point, minus the
414 // ".return". Create a new probe point, copying all the
415 // components, stopping when we see the ".return"
416 // component.
417 probe_point* pp = new probe_point;
418 for (unsigned c = 0; c < base_loc->components.size(); c++)
419 {
420 if (base_loc->components[c]->functor == "return")
421 break;
422 else
423 pp->components.push_back(base_loc->components[c]);
424 }
b84779a5
JS
425 pp->optional = base_loc->optional;
426 add_probe->locations.push_back(pp);
427
428 add_probe->body = new block;
429 add_probe->body->tok = e->tok;
430
431 // Synthesize a functioncall to grab the thread id.
432 functioncall* fc = new functioncall;
433 fc->tok = e->tok;
434 fc->function = string("tid");
435
436 // Assign the tid to '_utrace_tvar_tid'.
437 assignment* a = new assignment;
438 a->tok = e->tok;
439 a->op = "=";
440 a->left = tidsym;
441 a->right = fc;
442
443 expr_statement* es = new expr_statement;
444 es->tok = e->tok;
445 es->value = a;
446 add_probe->body = new block(add_probe->body, es);
447
448 vardecl* vd = new vardecl;
449 vd->tok = e->tok;
47d349b1 450 vd->name = tidsym->name;
b84779a5 451 vd->type = pe_long;
58701b78 452 vd->set_arity(0, e->tok);
b84779a5
JS
453 add_probe->locals.push_back(vd);
454 }
455
456 // Save the value, like this:
457 //
458 // _utrace_tvar_{name}_{num}[_utrace_tvar_tid] = ${param}
459 a = new assignment;
460 a->tok = e->tok;
461 a->op = "=";
462 a->left = ai_tvar;
463 a->right = e;
464
465 es = new expr_statement;
466 es->tok = e->tok;
467 es->value = a;
468
469 add_probe->body = new block(add_probe->body, es);
470
471 // (4) Provide the '_utrace_tvar_{name}_{num}_tmp' variable to
472 // our parent so it can be used as a substitute for the target
473 // symbol.
474 provide (tmpsym);
475
476 // (5) Remember this replacement since we might be able to reuse
477 // it later if the same return probe references this target
478 // symbol again.
479 return_ts_map[ts_name] = tmpsym;
480 return;
481}
482
483
484void
485utrace_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
486{
b84779a5 487 if (flags != UDPF_SYSCALL)
dc09353a 488 throw SEMANTIC_ERROR (_("only \"process(PATH_OR_PID).syscall\" support $argN or $$parms."), e->tok);
b84779a5 489
277c21bc 490 if (e->name == "$$parms")
b84779a5 491 {
a0c0ed1c 492 // copy from tracepoint
1c922ad7 493 print_format* pf = print_format::create(e->tok, "sprintf");
a0c0ed1c
WH
494
495 target_symbol_seen = true;
496
497 for (unsigned i = 0; i < 6; ++i)
498 {
499 if (i > 0)
500 pf->raw_components += " ";
aca66a36 501 pf->raw_components += "$arg" + lex_cast(i+1);
a0c0ed1c
WH
502 target_symbol *tsym = new target_symbol;
503 tsym->tok = e->tok;
277c21bc 504 tsym->name = "$arg" + lex_cast(i+1);
a0c0ed1c
WH
505 tsym->saved_conversion_error = 0;
506 pf->raw_components += "=%#x"; //FIXME: missing type info
507
508 functioncall* n = new functioncall; //same as the following
509 n->tok = e->tok;
510 n->function = "_utrace_syscall_arg";
7b5b30a8 511 n->referents.clear();
a0c0ed1c
WH
512 literal_number *num = new literal_number(i);
513 num->tok = e->tok;
514 n->args.push_back(num);
515
516 pf->args.push_back(n);
517 }
518 pf->components = print_format::string_to_components(pf->raw_components);
519
520 provide (pf);
277c21bc 521 }
a0c0ed1c
WH
522 else // $argN
523 {
47d349b1 524 string argnum_s = (string)e->name.substr(4,e->name.length()-4);
30263a73
FCE
525 int argnum = 0;
526 try
527 {
528 argnum = lex_cast<int>(argnum_s);
529 }
530 catch (const runtime_error& f) // non-integral $arg suffix: e.g. $argKKKSDF
531 {
dc09353a 532 throw SEMANTIC_ERROR (_("invalid syscall argument number (1-6)"), e->tok);
30263a73 533 }
a0c0ed1c 534
dc5a09fc 535 e->assert_no_components("utrace");
a0c0ed1c
WH
536
537 // FIXME: max argnument number should not be hardcoded.
538 if (argnum < 1 || argnum > 6)
dc09353a 539 throw SEMANTIC_ERROR (_("invalid syscall argument number (1-6)"), e->tok);
a0c0ed1c
WH
540
541 bool lvalue = is_active_lvalue(e);
542 if (lvalue)
dc09353a 543 throw SEMANTIC_ERROR(_("utrace '$argN' variable is read-only"), e->tok);
a0c0ed1c
WH
544
545 // Remember that we've seen a target variable.
546 target_symbol_seen = true;
547
548 // We're going to substitute a synthesized '_utrace_syscall_arg'
549 // function call for the '$argN' reference.
550 functioncall* n = new functioncall;
551 n->tok = e->tok;
552 n->function = "_utrace_syscall_arg";
7b5b30a8 553 n->referents.clear(); // NB: must not resolve yet, to ensure inclusion in session
a0c0ed1c
WH
554
555 literal_number *num = new literal_number(argnum - 1);
556 num->tok = e->tok;
557 n->args.push_back(num);
558
559 provide (n);
560 }
b84779a5
JS
561}
562
563void
564utrace_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
565{
47d349b1 566 string sname = e->name;
b84779a5 567
dc5a09fc 568 e->assert_no_components("utrace");
b84779a5
JS
569
570 bool lvalue = is_active_lvalue(e);
571 if (lvalue)
dc09353a 572 throw SEMANTIC_ERROR(_F("utrace '%s' variable is read-only", sname.c_str()), e->tok);
b84779a5
JS
573
574 string fname;
575 if (sname == "$return")
576 {
577 if (flags != UDPF_SYSCALL_RETURN)
dc09353a 578 throw SEMANTIC_ERROR (_("only \"process(PATH_OR_PID).syscall.return\" support $return."), e->tok);
b84779a5
JS
579 fname = "_utrace_syscall_return";
580 }
581 else if (sname == "$syscall")
582 {
583 // If we've got a syscall entry probe, we can just call the
584 // right function.
585 if (flags == UDPF_SYSCALL) {
586 fname = "_utrace_syscall_nr";
587 }
588 // If we're in a syscal return probe, we can't really access
589 // $syscall. So, similar to what
590 // dwarf_var_expanding_visitor::visit_target_symbol() does,
591 // we'll create an syscall entry probe to cache $syscall, then
592 // we'll access the cached value in the syscall return probe.
593 else {
594 visit_target_symbol_cached (e);
595
596 // Remember that we've seen a target variable.
597 target_symbol_seen = true;
598 return;
599 }
600 }
601 else
602 {
dc09353a 603 throw SEMANTIC_ERROR (_("unknown target variable"), e->tok);
b84779a5
JS
604 }
605
606 // Remember that we've seen a target variable.
607 target_symbol_seen = true;
608
609 // We're going to substitute a synthesized '_utrace_syscall_nr'
610 // function call for the '$syscall' reference.
611 functioncall* n = new functioncall;
612 n->tok = e->tok;
613 n->function = fname;
7b5b30a8 614 n->referents.clear(); // NB: must not resolve yet, to ensure inclusion in session
b84779a5
JS
615
616 provide (n);
617}
618
619void
620utrace_var_expanding_visitor::visit_target_symbol (target_symbol* e)
621{
277c21bc 622 assert(e->name.size() > 0 && e->name[0] == '$');
b84779a5 623
277c21bc 624 try
c69a87e0
FCE
625 {
626 if (flags != UDPF_SYSCALL && flags != UDPF_SYSCALL_RETURN)
dc09353a 627 throw SEMANTIC_ERROR (_("only \"process(PATH_OR_PID).syscall\""
b530b5b3 628 " and \"process(PATH_OR_PID).syscall.return\" probes support target symbols"),
c69a87e0 629 e->tok);
277c21bc 630
c69a87e0 631 if (e->addressof)
dc09353a 632 throw SEMANTIC_ERROR(_("cannot take address of utrace variable"), e->tok);
277c21bc 633
47d349b1 634 if (startswith(e->name, "$arg") || e->name == "$$parms")
c69a87e0 635 visit_target_symbol_arg(e);
277c21bc 636 else if (e->name == "$syscall" || e->name == "$return")
c69a87e0
FCE
637 visit_target_symbol_context(e);
638 else
dc09353a 639 throw SEMANTIC_ERROR (_("invalid target symbol for utrace probe,"
b530b5b3 640 " $syscall, $return, $argN or $$parms expected"),
c69a87e0
FCE
641 e->tok);
642 }
277c21bc 643 catch (const semantic_error &er)
c69a87e0 644 {
1af1e62d 645 e->chain (er);
c69a87e0
FCE
646 provide(e);
647 return;
648 }
b84779a5
JS
649}
650
651
652struct utrace_builder: public derived_probe_builder
653{
654 utrace_builder() {}
655 virtual void build(systemtap_session & sess,
656 probe * base,
657 probe_point * location,
658 literal_map_t const & parameters,
659 vector<derived_probe *> & finished_results)
660 {
45a63356 661 interned_string path, path_tgt;
b84779a5
JS
662 int64_t pid;
663
664 bool has_path = get_param (parameters, TOK_PROCESS, path);
665 bool has_pid = get_param (parameters, TOK_PROCESS, pid);
666 enum utrace_derived_probe_flags flags = UDPF_NONE;
667
668 if (has_null_param (parameters, TOK_THREAD))
669 {
670 if (has_null_param (parameters, TOK_BEGIN))
671 flags = UDPF_THREAD_BEGIN;
672 else if (has_null_param (parameters, TOK_END))
673 flags = UDPF_THREAD_END;
674 }
675 else if (has_null_param (parameters, TOK_SYSCALL))
676 {
9663016c 677 if (sess.runtime_usermode_p())
dc09353a 678 throw SEMANTIC_ERROR (_("process.syscall probes not available with the dyninst runtime"));
9663016c 679
b84779a5
JS
680 if (has_null_param (parameters, TOK_RETURN))
681 flags = UDPF_SYSCALL_RETURN;
682 else
683 flags = UDPF_SYSCALL;
684 }
685 else if (has_null_param (parameters, TOK_BEGIN))
686 flags = UDPF_BEGIN;
687 else if (has_null_param (parameters, TOK_END))
688 flags = UDPF_END;
689
86b6fb5b 690 // Check that if a pid was given, then it corresponds to a running process.
5c6f9e92
AJ
691 if (has_pid || sess.target_pid)
692 {
a03a3744
JS
693 string pid_err_msg;
694 if (!is_valid_pid(has_pid ? pid : sess.target_pid, pid_err_msg))
695 throw SEMANTIC_ERROR(pid_err_msg);
5c6f9e92
AJ
696 }
697
b84779a5
JS
698 // If we didn't get a path or pid, this means to probe everything.
699 // Convert this to a pid-based probe.
700 if (! has_path && ! has_pid)
701 {
702 has_path = false;
703 path.clear();
704 has_pid = true;
705 pid = 0;
706 }
707 else if (has_path)
708 {
403fa5e6
MC
709 if (path == "")
710 throw SEMANTIC_ERROR (_("empty module"));
05fb3e0c 711 path = find_executable (path, sess.sysroot, sess.sysenv);
b84779a5 712 sess.unwindsym_modules.insert (path);
05fb3e0c 713 path_tgt = path_remove_sysroot(sess, path);
b84779a5 714 }
b84779a5
JS
715
716 finished_results.push_back(new utrace_derived_probe(sess, base, location,
05fb3e0c 717 has_path, path_tgt, pid,
b84779a5
JS
718 flags));
719 }
352c84fe
FL
720
721 virtual string name() { return "utrace builder"; }
b84779a5
JS
722};
723
724
725void
726utrace_derived_probe_group::enroll (utrace_derived_probe* p)
727{
728 if (p->has_path)
729 probes_by_path[p->path].push_back(p);
730 else
731 probes_by_pid[p->pid].push_back(p);
732 num_probes++;
733 flags_seen[p->flags] = true;
734
735 // XXX: multiple exec probes (for instance) for the same path (or
736 // pid) should all share a utrace report function, and have their
737 // handlers executed sequentially.
738}
739
740
741void
f31a77f5
DS
742utrace_derived_probe_group::emit_linux_probe_decl (systemtap_session& s,
743 utrace_derived_probe *p)
b84779a5
JS
744{
745 s.op->newline() << "{";
746 s.op->line() << " .tgt={";
1af100fc 747 s.op->line() << " .purpose=\"lifecycle tracking\",";
b84779a5
JS
748 if (p->has_path)
749 {
b6921d59 750 s.op->line() << " .procname=\"" << p->path << "\",";
b84779a5
JS
751 s.op->line() << " .pid=0,";
752 }
753 else
754 {
b6921d59 755 s.op->line() << " .procname=NULL,";
b84779a5
JS
756 s.op->line() << " .pid=" << p->pid << ",";
757 }
758
759 s.op->line() << " .callback=&_stp_utrace_probe_cb,";
760 s.op->line() << " .mmap_callback=NULL,";
761 s.op->line() << " .munmap_callback=NULL,";
762 s.op->line() << " .mprotect_callback=NULL,";
763 s.op->line() << " },";
faea5e16 764 s.op->line() << " .probe=" << common_probe_init (p) << ",";
b84779a5
JS
765
766 // Handle flags
767 switch (p->flags)
768 {
769 // Notice that we'll just call the probe directly when we get
770 // notified, since the task_finder layer stops the thread for us.
771 case UDPF_BEGIN: // process begin
772 s.op->line() << " .flags=(UDPF_BEGIN),";
773 break;
774 case UDPF_THREAD_BEGIN: // thread begin
775 s.op->line() << " .flags=(UDPF_THREAD_BEGIN),";
776 break;
777
778 // Notice we're not setting up a .ops/.report_death handler for
779 // either UDPF_END or UDPF_THREAD_END. Instead, we'll just call
780 // the probe directly when we get notified.
781 case UDPF_END: // process end
782 s.op->line() << " .flags=(UDPF_END),";
783 break;
784 case UDPF_THREAD_END: // thread end
785 s.op->line() << " .flags=(UDPF_THREAD_END),";
786 break;
787
788 // For UDPF_SYSCALL/UDPF_SYSCALL_RETURN probes, the .report_death
789 // handler isn't strictly necessary. However, it helps to keep
790 // our attaches/detaches symmetrical. Since the task_finder layer
791 // stops the thread, that works around bug 6841.
792 case UDPF_SYSCALL:
793 s.op->line() << " .flags=(UDPF_SYSCALL),";
fed8d99f 794 s.op->newline() << " .ops={ .report_syscall_entry=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death },";
b84779a5 795 s.op->line() << " .events=(UTRACE_EVENT(SYSCALL_ENTRY)|UTRACE_EVENT(DEATH)),";
fed8d99f 796 s.op->newline();
b84779a5
JS
797 break;
798 case UDPF_SYSCALL_RETURN:
799 s.op->line() << " .flags=(UDPF_SYSCALL_RETURN),";
fed8d99f 800 s.op->newline() << " .ops={ .report_syscall_exit=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death },";
b84779a5 801 s.op->line() << " .events=(UTRACE_EVENT(SYSCALL_EXIT)|UTRACE_EVENT(DEATH)),";
fed8d99f 802 s.op->newline();
b84779a5
JS
803 break;
804
805 case UDPF_NONE:
806 s.op->line() << " .flags=(UDPF_NONE),";
807 s.op->line() << " .ops={ },";
808 s.op->line() << " .events=0,";
809 break;
810 default:
dc09353a 811 throw SEMANTIC_ERROR ("bad utrace probe flag");
b84779a5
JS
812 break;
813 }
814 s.op->line() << " .engine_attached=0,";
815 s.op->line() << " },";
816}
817
818
819void
f31a77f5 820utrace_derived_probe_group::emit_module_linux_decls (systemtap_session& s)
b84779a5
JS
821{
822 if (probes_by_path.empty() && probes_by_pid.empty())
823 return;
824
825 s.op->newline();
826 s.op->newline() << "/* ---- utrace probes ---- */";
827
828 s.op->newline() << "enum utrace_derived_probe_flags {";
829 s.op->indent(1);
830 s.op->newline() << "UDPF_NONE,";
831 s.op->newline() << "UDPF_BEGIN,";
832 s.op->newline() << "UDPF_END,";
833 s.op->newline() << "UDPF_THREAD_BEGIN,";
834 s.op->newline() << "UDPF_THREAD_END,";
835 s.op->newline() << "UDPF_SYSCALL,";
836 s.op->newline() << "UDPF_SYSCALL_RETURN,";
837 s.op->newline() << "UDPF_NFLAGS";
838 s.op->newline(-1) << "};";
839
840 s.op->newline() << "struct stap_utrace_probe {";
841 s.op->indent(1);
842 s.op->newline() << "struct stap_task_finder_target tgt;";
7c3e97f4 843 s.op->newline() << "const struct stap_probe * const probe;";
81fb86d8 844 s.op->newline() << "int engine_attached;";
b84779a5
JS
845 s.op->newline() << "enum utrace_derived_probe_flags flags;";
846 s.op->newline() << "struct utrace_engine_ops ops;";
847 s.op->newline() << "unsigned long events;";
b84779a5
JS
848 s.op->newline(-1) << "};";
849
850
851 // Output handler function for UDPF_BEGIN, UDPF_THREAD_BEGIN,
852 // UDPF_END, and UDPF_THREAD_END
853 if (flags_seen[UDPF_BEGIN] || flags_seen[UDPF_THREAD_BEGIN]
854 || flags_seen[UDPF_END] || flags_seen[UDPF_THREAD_END])
855 {
856 s.op->newline() << "static void stap_utrace_probe_handler(struct task_struct *tsk, struct stap_utrace_probe *p) {";
857 s.op->indent(1);
858
04d221c1
YZ
859 // PR25290, utrace process callbacks might get fired in the
860 // STAP_SESSION_STARTING state occasionally.
861 common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING",
862 "STAP_SESSION_STARTING",
863 "p->probe",
cda141c2 864 "stp_probe_type_utrace");
b84779a5 865
26b24dc2
YZ
866 // make sure tapset funcs like register() work in probe process.begin
867 // and etc.
868 s.op->newline() << "c->uregs = _stp_current_pt_regs();";
869 s.op->newline() << "c->user_mode_p = 1;";
870
b84779a5 871 // call probe function
04d221c1 872 s.op->newline() << "dbug_task(2, \"calling UDPF probe function\");";
26e63673 873 s.op->newline() << "(*p->probe->ph) (c);";
ef1337ee 874 common_probe_entryfn_epilogue (s, true, otf_safe_context(s));
b84779a5
JS
875
876 s.op->newline() << "return;";
877 s.op->newline(-1) << "}";
878 }
879
880 // Output handler function for SYSCALL_ENTRY and SYSCALL_EXIT events
881 if (flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN])
882 {
883 s.op->newline() << "#ifdef UTRACE_ORIG_VERSION";
fcb496ce 884 s.op->newline() << "static u32 stap_utrace_probe_syscall(struct utrace_engine *engine, struct task_struct *tsk, struct pt_regs *regs) {";
b84779a5 885 s.op->newline() << "#else";
b8b815b7 886 s.op->newline() << "#if defined(UTRACE_API_VERSION) && (UTRACE_API_VERSION >= 20091216)";
fcb496ce 887 s.op->newline() << "static u32 stap_utrace_probe_syscall(u32 action, struct utrace_engine *engine, struct pt_regs *regs) {";
b8b815b7 888 s.op->newline() << "#else";
fcb496ce 889 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) {";
b84779a5 890 s.op->newline() << "#endif";
b8b815b7 891 s.op->newline() << "#endif";
b84779a5
JS
892
893 s.op->indent(1);
894 s.op->newline() << "struct stap_utrace_probe *p = (struct stap_utrace_probe *)engine->data;";
895
04d221c1 896 common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "", "p->probe",
cda141c2 897 "stp_probe_type_utrace_syscall");
d9aed31e 898 s.op->newline() << "c->uregs = regs;";
e04b5d74 899 s.op->newline() << "c->user_mode_p = 1;";
b84779a5
JS
900
901 // call probe function
26e63673 902 s.op->newline() << "(*p->probe->ph) (c);";
ef1337ee 903 common_probe_entryfn_epilogue (s, true, otf_safe_context(s));
b84779a5 904
065d5567 905 s.op->newline() << "if ((atomic_read (session_state()) != STAP_SESSION_STARTING) && (atomic_read (session_state()) != STAP_SESSION_RUNNING)) {";
b84779a5
JS
906 s.op->indent(1);
907 s.op->newline() << "debug_task_finder_detach();";
908 s.op->newline() << "return UTRACE_DETACH;";
909 s.op->newline(-1) << "}";
910 s.op->newline() << "return UTRACE_RESUME;";
911 s.op->newline(-1) << "}";
912 }
913
914 // Output task_finder callback routine that gets called for all
915 // utrace probe types.
916 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) {";
917 s.op->indent(1);
918 s.op->newline() << "int rc = 0;";
919 s.op->newline() << "struct stap_utrace_probe *p = container_of(tgt, struct stap_utrace_probe, tgt);";
fcb496ce 920 s.op->newline() << "struct utrace_engine *engine;";
04d221c1
YZ
921 s.op->newline() << "dbug_task(2, \"utrace probe cb: register_p=%d "
922 "process_p=%d, p->flags=%x (begin: %d, thr begin: %d)\", "
923 "register_p, process_p, (unsigned) p->flags, UDPF_BEGIN, "
924 "UDPF_THREAD_BEGIN);";
b84779a5
JS
925
926 s.op->newline() << "if (register_p) {";
927 s.op->indent(1);
928
929 s.op->newline() << "switch (p->flags) {";
930 s.op->indent(1);
931
932 // When receiving a UTRACE_EVENT(CLONE) event, we can't call the
933 // begin/thread.begin probe directly. So, we'll just attach an
934 // engine that waits for the thread to quiesce. When the thread
935 // quiesces, then call the probe.
936 if (flags_seen[UDPF_BEGIN])
937 {
938 s.op->newline() << "case UDPF_BEGIN:";
939 s.op->indent(1);
940 s.op->newline() << "if (process_p) {";
941 s.op->indent(1);
942 s.op->newline() << "stap_utrace_probe_handler(tsk, p);";
943 s.op->newline(-1) << "}";
944 s.op->newline() << "break;";
945 s.op->indent(-1);
946 }
947 if (flags_seen[UDPF_THREAD_BEGIN])
948 {
949 s.op->newline() << "case UDPF_THREAD_BEGIN:";
950 s.op->indent(1);
951 s.op->newline() << "if (! process_p) {";
952 s.op->indent(1);
953 s.op->newline() << "stap_utrace_probe_handler(tsk, p);";
954 s.op->newline(-1) << "}";
955 s.op->newline() << "break;";
956 s.op->indent(-1);
957 }
958
959 // For end/thread_end probes, do nothing at registration time.
960 // We'll handle these in the 'register_p == 0' case.
961 if (flags_seen[UDPF_END] || flags_seen[UDPF_THREAD_END])
962 {
963 s.op->newline() << "case UDPF_END:";
964 s.op->newline() << "case UDPF_THREAD_END:";
965 s.op->indent(1);
966 s.op->newline() << "break;";
967 s.op->indent(-1);
968 }
969
970 // Attach an engine for SYSCALL_ENTRY and SYSCALL_EXIT events.
971 if (flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN])
972 {
973 s.op->newline() << "case UDPF_SYSCALL:";
974 s.op->newline() << "case UDPF_SYSCALL_RETURN:";
975 s.op->indent(1);
976 s.op->newline() << "rc = stap_utrace_attach(tsk, &p->ops, p, p->events);";
977 s.op->newline() << "if (rc == 0) {";
978 s.op->indent(1);
979 s.op->newline() << "p->engine_attached = 1;";
980 s.op->newline(-1) << "}";
981 s.op->newline() << "break;";
982 s.op->indent(-1);
983 }
984
985 s.op->newline() << "default:";
986 s.op->indent(1);
987 s.op->newline() << "_stp_error(\"unhandled flag value %d at %s:%d\", p->flags, __FUNCTION__, __LINE__);";
988 s.op->newline() << "break;";
989 s.op->indent(-1);
990 s.op->newline(-1) << "}";
991 s.op->newline(-1) << "}";
992
993 // Since this engine could be attached to multiple threads, don't
994 // call stap_utrace_detach_ops() here, only call
995 // stap_utrace_detach() as necessary.
996 s.op->newline() << "else {";
997 s.op->indent(1);
998 s.op->newline() << "switch (p->flags) {";
999 s.op->indent(1);
1000 // For end probes, go ahead and call the probe directly.
1001 if (flags_seen[UDPF_END])
1002 {
1003 s.op->newline() << "case UDPF_END:";
1004 s.op->indent(1);
1005 s.op->newline() << "if (process_p) {";
1006 s.op->indent(1);
1007 s.op->newline() << "stap_utrace_probe_handler(tsk, p);";
1008 s.op->newline(-1) << "}";
1009 s.op->newline() << "break;";
1010 s.op->indent(-1);
1011 }
1012 if (flags_seen[UDPF_THREAD_END])
1013 {
1014 s.op->newline() << "case UDPF_THREAD_END:";
1015 s.op->indent(1);
1016 s.op->newline() << "if (! process_p) {";
1017 s.op->indent(1);
1018 s.op->newline() << "stap_utrace_probe_handler(tsk, p);";
1019 s.op->newline(-1) << "}";
1020 s.op->newline() << "break;";
1021 s.op->indent(-1);
1022 }
1023
1024 // For begin/thread_begin probes, we don't need to do anything.
1025 if (flags_seen[UDPF_BEGIN] || flags_seen[UDPF_THREAD_BEGIN])
1026 {
1027 s.op->newline() << "case UDPF_BEGIN:";
1028 s.op->newline() << "case UDPF_THREAD_BEGIN:";
1029 s.op->indent(1);
1030 s.op->newline() << "break;";
1031 s.op->indent(-1);
1032 }
1033
1034 if (flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN])
1035 {
1036 s.op->newline() << "case UDPF_SYSCALL:";
1037 s.op->newline() << "case UDPF_SYSCALL_RETURN:";
1038 s.op->indent(1);
1039 s.op->newline() << "stap_utrace_detach(tsk, &p->ops);";
1040 s.op->newline() << "break;";
1041 s.op->indent(-1);
1042 }
1043
1044 s.op->newline() << "default:";
1045 s.op->indent(1);
1046 s.op->newline() << "_stp_error(\"unhandled flag value %d at %s:%d\", p->flags, __FUNCTION__, __LINE__);";
1047 s.op->newline() << "break;";
1048 s.op->indent(-1);
1049 s.op->newline(-1) << "}";
1050 s.op->newline(-1) << "}";
1051 s.op->newline() << "return rc;";
1052 s.op->newline(-1) << "}";
1053
b84779a5
JS
1054 s.op->newline() << "static struct stap_utrace_probe stap_utrace_probes[] = {";
1055 s.op->indent(1);
1056
1057 // Set up 'process(PATH)' probes
1058 if (! probes_by_path.empty())
1059 {
1060 for (p_b_path_iterator it = probes_by_path.begin();
1061 it != probes_by_path.end(); it++)
1062 {
1063 for (unsigned i = 0; i < it->second.size(); i++)
1064 {
1065 utrace_derived_probe *p = it->second[i];
f31a77f5 1066 emit_linux_probe_decl(s, p);
b84779a5
JS
1067 }
1068 }
1069 }
1070
1071 // Set up 'process(PID)' probes
1072 if (! probes_by_pid.empty())
1073 {
1074 for (p_b_pid_iterator it = probes_by_pid.begin();
1075 it != probes_by_pid.end(); it++)
1076 {
1077 for (unsigned i = 0; i < it->second.size(); i++)
1078 {
1079 utrace_derived_probe *p = it->second[i];
f31a77f5 1080 emit_linux_probe_decl(s, p);
b84779a5
JS
1081 }
1082 }
1083 }
1084 s.op->newline(-1) << "};";
1085}
1086
1087
1088void
f31a77f5
DS
1089utrace_derived_probe_group::emit_dyninst_probe_decl (systemtap_session& s,
1090 const string& path,
1091 utrace_derived_probe *p)
1092{
1093 string flags_str;
1094
1095 // Handle flags
1096 switch (p->flags)
1097 {
1098 case UDPF_BEGIN: // process begin
1099 flags_str = "STAPDYN_PROBE_FLAG_PROC_BEGIN";
1100 break;
1101 case UDPF_THREAD_BEGIN: // thread begin
1102 flags_str = "STAPDYN_PROBE_FLAG_THREAD_BEGIN";
1103 break;
1104 case UDPF_END: // process end
1105 flags_str = "STAPDYN_PROBE_FLAG_PROC_END";
1106 break;
1107 case UDPF_THREAD_END: // thread end
1108 flags_str = "STAPDYN_PROBE_FLAG_THREAD_END";
1109 break;
1110
1111 // FIXME: No handling of syscall probes for dyninst yet.
1112#if 0
1113 case UDPF_SYSCALL:
1114 break;
1115 case UDPF_SYSCALL_RETURN:
1116 break;
1117
1118 case UDPF_NONE:
1119 s.op->line() << " .flags=(UDPF_NONE),";
1120 s.op->line() << " .ops={ },";
1121 s.op->line() << " .events=0,";
1122 break;
1123#endif
1124 default:
dc09353a 1125 throw SEMANTIC_ERROR ("bad utrace probe flag");
f31a77f5
DS
1126 break;
1127 }
1128
1129 if (p->has_path)
1130 dynprobe_add_utrace_path(s, path, flags_str, common_probe_init(p));
1131 else
1132 dynprobe_add_utrace_pid(s, p->pid, flags_str, common_probe_init(p));
1133}
1134
1135void
1136utrace_derived_probe_group::emit_module_dyninst_decls (systemtap_session& s)
1137{
1138 if (probes_by_path.empty() && probes_by_pid.empty())
1139 return;
1140
1141 s.op->newline();
1142 s.op->newline() << "/* ---- dyninst utrace probes ---- */";
1143 s.op->newline() << "#include \"dyninst/uprobes.h\"";
1144 s.op->newline() << "#define STAPDYN_UTRACE_PROBES";
1145
1146 // Let the dynprobe_derived_probe_group handle outputting targets
1147 // and probes. This allows us to merge different types of probes.
1148 s.op->newline() << "static struct stapdu_probe stapdu_probes[];";
1149
1150 // Set up 'process(PATH)' probes
1151 if (! probes_by_path.empty())
1152 {
1153 for (p_b_path_iterator it = probes_by_path.begin();
1154 it != probes_by_path.end(); it++)
1155 {
1156 for (unsigned i = 0; i < it->second.size(); i++)
1157 {
1158 utrace_derived_probe *p = it->second[i];
1159 emit_dyninst_probe_decl(s, it->first, p);
1160 }
1161 }
1162 }
1163 // Set up 'process(PID)' probes
1164 if (! probes_by_pid.empty())
1165 {
1166 for (p_b_pid_iterator it = probes_by_pid.begin();
1167 it != probes_by_pid.end(); it++)
1168 {
1169 for (unsigned i = 0; i < it->second.size(); i++)
1170 {
1171 utrace_derived_probe *p = it->second[i];
1172 emit_dyninst_probe_decl(s, "", p);
1173 }
1174 }
1175 }
1176
1177 // loc2c-generated code assumes pt_regs are available, so use this to make
1178 // sure we always have *something* for it to dereference...
1179 s.op->newline() << "static struct pt_regs stapdu_dummy_uregs;";
1180
1181 // Write the probe handler.
1182 // NB: not static, so dyninst can find it
1183 s.op->newline() << "int enter_dyninst_utrace_probe "
1184 << "(uint64_t index, struct pt_regs *regs) {";
1185 s.op->newline(1) << "struct stapdu_probe *sup = &stapdu_probes[index];";
1186
04d221c1 1187 common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "", "sup->probe",
9663016c 1188 "stp_probe_type_utrace");
f31a77f5
DS
1189 s.op->newline() << "c->uregs = regs ?: &stapdu_dummy_uregs;";
1190 s.op->newline() << "c->user_mode_p = 1;";
1191 // XXX: once we have regs, check how dyninst sets the IP
1192 // XXX: the way that dyninst rewrites stuff is probably going to be
1193 // ... very confusing to our backtracer (at least if we stay in process)
1194 s.op->newline() << "(*sup->probe->ph) (c);";
ef1337ee 1195 common_probe_entryfn_epilogue (s, true, otf_safe_context(s));
f31a77f5
DS
1196 s.op->newline() << "return 0;";
1197 s.op->newline(-1) << "}";
1198 s.op->assert_0_indent();
1199}
1200
1201
1202void
1203utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
1204{
1205 if (s.runtime_usermode_p())
1206 emit_module_dyninst_decls (s);
1207 else
1208 emit_module_linux_decls (s);
1209}
1210
1211
1212void
1213utrace_derived_probe_group::emit_module_linux_init (systemtap_session& s)
b84779a5
JS
1214{
1215 if (probes_by_path.empty() && probes_by_pid.empty())
1216 return;
1217
b84779a5
JS
1218 s.op->newline() << "/* ---- utrace probes ---- */";
1219 s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_utrace_probes); i++) {";
a9b59347 1220 s.op->newline(1) << "struct stap_utrace_probe *p = &stap_utrace_probes[i];";
26e63673 1221 s.op->newline() << "probe_point = p->probe->pp;"; // for error messages
b84779a5 1222 s.op->newline() << "rc = stap_register_task_finder_target(&p->tgt);";
b84779a5 1223
a9b59347
JS
1224 // NB: if (rc), there is no need (XXX: nor any way) to clean up any
1225 // finders already registered, since mere registration does not
1226 // cause any utrace or memory allocation actions. That happens only
1227 // later, once the task finder engine starts running. So, for a
1228 // partial initialization requiring unwind, we need do nothing.
1229 s.op->newline() << "if (rc) break;";
b84779a5
JS
1230
1231 s.op->newline(-1) << "}";
1232}
1233
1234
1235void
f31a77f5
DS
1236utrace_derived_probe_group::emit_module_dyninst_init (systemtap_session& s)
1237{
1238 if (probes_by_path.empty() && probes_by_pid.empty())
1239 return;
1240
1241 /* stapdyn handles the dirty work via dyninst */
1242 s.op->newline() << "/* ---- dyninst utrace probes ---- */";
1243 s.op->newline() << "/* this section left intentionally blank */";
1244}
1245
1246
1247void
1248utrace_derived_probe_group::emit_module_init (systemtap_session& s)
1249{
1250 if (s.runtime_usermode_p())
1251 emit_module_dyninst_init (s);
1252 else
1253 emit_module_linux_init(s);
1254}
1255
1256
1257void
1258utrace_derived_probe_group::emit_module_linux_exit (systemtap_session& s)
b84779a5
JS
1259{
1260 if (probes_by_path.empty() && probes_by_pid.empty()) return;
1261
1262 s.op->newline();
1263 s.op->newline() << "/* ---- utrace probes ---- */";
1264 s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_utrace_probes); i++) {";
a9b59347 1265 s.op->newline(1) << "struct stap_utrace_probe *p = &stap_utrace_probes[i];";
81b2ee28 1266 s.op->newline() << "stap_cleanup_task_finder_target(&p->tgt);";
b84779a5
JS
1267 s.op->newline(-1) << "}";
1268}
1269
1270
f31a77f5
DS
1271void
1272utrace_derived_probe_group::emit_module_dyninst_exit (systemtap_session& s)
1273{
1274 if (probes_by_path.empty() && probes_by_pid.empty())
1275 return;
1276
1277 /* stapdyn handles the dirty work via dyninst */
1278 s.op->newline() << "/* ---- dyninst utrace probes ---- */";
1279 s.op->newline() << "/* this section left intentionally blank */";
1280}
1281
1282
1283void
1284utrace_derived_probe_group::emit_module_exit (systemtap_session& s)
1285{
1286 if (s.runtime_usermode_p())
1287 emit_module_dyninst_exit (s);
1288 else
1289 emit_module_linux_exit(s);
1290}
1291
1292
40dbe72a
SM
1293// PR26234: Not supported by stapbpf.
1294void
1295warn_for_bpf(systemtap_session& s, utrace_derived_probe_group *upg,
1296 const std::string& kind)
1297{
1298 if (! upg->probes_by_path.empty())
1299 {
1300 for (utrace_derived_probe_group::p_b_path_iterator it
1301 = upg->probes_by_path.begin();
1302 it != upg->probes_by_path.end(); it++)
1303 {
1304 for (unsigned i = 0; i < it->second.size(); i++)
1305 {
1306 s.print_warning(_F("%s will be ignored by bpf backend",
1307 kind.c_str()),
1308 it->second[i]->tok);
1309 }
1310 }
1311 }
1312 if (! upg->probes_by_pid.empty())
1313 {
1314 for (utrace_derived_probe_group::p_b_pid_iterator it
1315 = upg->probes_by_pid.begin();
1316 it != upg->probes_by_pid.end(); it++)
1317 {
1318 for (unsigned i = 0; i < it->second.size(); i++)
1319 {
1320 s.print_warning(_F("%s will be ignored by bpf backend",
1321 kind.c_str()),
1322 it->second[i]->tok);
1323 }
1324 }
1325 }
1326}
1327
1328
b84779a5
JS
1329void
1330register_tapset_utrace(systemtap_session& s)
1331{
1332 match_node* root = s.pattern_root;
1333 derived_probe_builder *builder = new utrace_builder();
1334
1335 vector<match_node*> roots;
1336 roots.push_back(root->bind(TOK_PROCESS));
1337 roots.push_back(root->bind_str(TOK_PROCESS));
1338 roots.push_back(root->bind_num(TOK_PROCESS));
1339
1340 for (unsigned i = 0; i < roots.size(); ++i)
1341 {
5e8a3b7b 1342 roots[i]->bind(TOK_BEGIN)
f66bb29a 1343 ->bind_privilege(pr_all)
5e8a3b7b
DB
1344 ->bind(builder);
1345 roots[i]->bind(TOK_END)
f66bb29a 1346 ->bind_privilege(pr_all)
5e8a3b7b
DB
1347 ->bind(builder);
1348 roots[i]->bind(TOK_THREAD)->bind(TOK_BEGIN)
f66bb29a 1349 ->bind_privilege(pr_all)
5e8a3b7b
DB
1350 ->bind(builder);
1351 roots[i]->bind(TOK_THREAD)->bind(TOK_END)
f66bb29a 1352 ->bind_privilege(pr_all)
5e8a3b7b
DB
1353 ->bind(builder);
1354 roots[i]->bind(TOK_SYSCALL)
f66bb29a 1355 ->bind_privilege(pr_all)
5e8a3b7b
DB
1356 ->bind(builder);
1357 roots[i]->bind(TOK_SYSCALL)->bind(TOK_RETURN)
f66bb29a 1358 ->bind_privilege(pr_all)
5e8a3b7b 1359 ->bind(builder);
b84779a5
JS
1360 }
1361}
1362
1363/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.75027 seconds and 6 git commands to generate.