]> sourceware.org Git - systemtap.git/blob - tapset-mark.cxx
PR13306: introduce stap --suppress-handler-errors option
[systemtap.git] / tapset-mark.cxx
1 // tapset for kernel static markers
2 // Copyright (C) 2005-2010 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 #include "session.h"
12 #include "tapsets.h"
13 #include "translate.h"
14 #include "util.h"
15
16 #include <cerrno>
17 #include <cstdlib>
18 #include <cstring>
19 #include <string>
20
21 extern "C" {
22 #include <fnmatch.h>
23 }
24
25
26 using namespace std;
27 using namespace __gnu_cxx;
28
29
30 static const string TOK_KERNEL("kernel");
31 static const string TOK_MARK("mark");
32 static const string TOK_FORMAT("format");
33
34
35 // ------------------------------------------------------------------------
36 // statically inserted macro-based derived probes
37 // ------------------------------------------------------------------------
38
39 struct mark_arg
40 {
41 bool str;
42 bool isptr;
43 string c_type;
44 exp_type stp_type;
45 };
46
47 struct mark_derived_probe: public derived_probe
48 {
49 mark_derived_probe (systemtap_session &s,
50 const string& probe_name, const string& probe_format,
51 probe* base_probe, probe_point* location);
52
53 systemtap_session& sess;
54 string probe_name, probe_format;
55 vector <struct mark_arg *> mark_args;
56 bool target_symbol_seen;
57
58 void join_group (systemtap_session& s);
59 void print_dupe_stamp (ostream& o);
60 void initialize_probe_context_vars (translator_output* o);
61 void getargs (std::list<std::string> &arg_set) const;
62
63 void parse_probe_format ();
64 };
65
66
67 struct mark_derived_probe_group: public generic_dpg<mark_derived_probe>
68 {
69 public:
70 void emit_module_decls (systemtap_session& s);
71 void emit_module_init (systemtap_session& s);
72 void emit_module_exit (systemtap_session& s);
73 };
74
75
76 struct mark_var_expanding_visitor: public var_expanding_visitor
77 {
78 mark_var_expanding_visitor(systemtap_session& s, const string& pn,
79 vector <struct mark_arg *> &mark_args):
80 sess (s), probe_name (pn), mark_args (mark_args),
81 target_symbol_seen (false) {}
82 systemtap_session& sess;
83 string probe_name;
84 vector <struct mark_arg *> &mark_args;
85 bool target_symbol_seen;
86
87 void visit_target_symbol (target_symbol* e);
88 void visit_target_symbol_arg (target_symbol* e);
89 void visit_target_symbol_context (target_symbol* e);
90 };
91
92
93 void
94 mark_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
95 {
96 string argnum_s = e->name.substr(4,e->name.length()-4);
97 int argnum = atoi (argnum_s.c_str());
98
99 if (argnum < 1 || argnum > (int)mark_args.size())
100 throw semantic_error (_("invalid marker argument number"), e->tok);
101
102 if (is_active_lvalue (e))
103 throw semantic_error(_("write to marker parameter not permitted"), e->tok);
104
105 e->assert_no_components("marker");
106
107 // Remember that we've seen a target variable.
108 target_symbol_seen = true;
109
110 symbol* sym = new symbol;
111 sym->tok = e->tok;
112 sym->name = "__mark_arg" + lex_cast(argnum);
113 provide (sym);
114 }
115
116
117 void
118 mark_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
119 {
120 string sname = e->name;
121
122 if (is_active_lvalue (e))
123 throw semantic_error(_F("write to marker '%s' not permitted", sname.c_str()), e->tok);
124
125 e->assert_no_components("marker");
126
127 if (e->name == "$format" || e->name == "$name") {
128 // Synthesize an embedded expression.
129 embedded_expr *expr = new embedded_expr;
130 expr->tok = e->tok;
131
132 if (e->name == "$format")
133 expr->code = string("/* string */ /* pure */ ")
134 + string("c->ips.kmark.marker_format ? c->ips.kmark.marker_format : \"\"");
135 else
136 expr->code = string("/* string */ /* pure */ ")
137 + string("c->ips.kmark.marker_name ? c->ips.kmark.marker_name : \"\"");
138
139 provide (expr);
140 }
141 else if (e->name == "$$vars" || e->name == "$$parms")
142 {
143 //copy from tracepoint
144 token* pf_tok = new token(*e->tok);
145 pf_tok->content = "sprintf";
146 print_format* pf = print_format::create(pf_tok);
147
148 for (unsigned i = 0; i < mark_args.size(); ++i)
149 {
150 if (i > 0)
151 pf->raw_components += " ";
152 pf->raw_components += "$arg" + lex_cast(i+1);
153 target_symbol *tsym = new target_symbol;
154 tsym->tok = e->tok;
155 tsym->name = "$arg" + lex_cast(i+1);
156
157 tsym->saved_conversion_error = 0;
158 expression *texp = require (tsym); //same treatment as tracepoint
159 assert (!tsym->saved_conversion_error);
160 switch (mark_args[i]->stp_type)
161 {
162 case pe_long:
163 pf->raw_components += mark_args[i]->isptr ? "=%p" : "=%#x";
164 break;
165 case pe_string:
166 pf->raw_components += "=%s";
167 break;
168 default:
169 pf->raw_components += "=%#x";
170 break;
171 }
172 pf->args.push_back(texp);
173 }
174 pf->components = print_format::string_to_components(pf->raw_components);
175 provide (pf);
176 }
177 }
178
179 void
180 mark_var_expanding_visitor::visit_target_symbol (target_symbol* e)
181 {
182 assert(e->name.size() > 0 && e->name[0] == '$');
183
184 try
185 {
186 if (e->addressof)
187 throw semantic_error(_("cannot take address of marker variable"), e->tok);
188
189 if (startswith(e->name, "$arg"))
190 visit_target_symbol_arg (e);
191 else if (e->name == "$format" || e->name == "$name"
192 || e->name == "$$parms" || e->name == "$$vars")
193 visit_target_symbol_context (e);
194 else
195 throw semantic_error (_("invalid target symbol for marker, $argN, $name, $format, $$parms or $$vars expected"),
196 e->tok);
197 }
198 catch (const semantic_error &er)
199 {
200 e->chain (er);
201 provide (e);
202 }
203 }
204
205
206 mark_derived_probe::mark_derived_probe (systemtap_session &s,
207 const string& p_n,
208 const string& p_f,
209 probe* base, probe_point* loc):
210 derived_probe (base, loc, true /* .components soon rewritten */),
211 sess (s), probe_name (p_n), probe_format (p_f),
212 target_symbol_seen (false)
213 {
214 // create synthetic probe point name; preserve condition
215 vector<probe_point::component*> comps;
216 comps.push_back (new probe_point::component (TOK_KERNEL));
217 comps.push_back (new probe_point::component (TOK_MARK, new literal_string (probe_name)));
218 comps.push_back (new probe_point::component (TOK_FORMAT, new literal_string (probe_format)));
219 this->sole_location()->components = comps;
220
221 // expand the marker format
222 parse_probe_format();
223
224 // Now expand the local variables in the probe body
225 mark_var_expanding_visitor v (sess, name, mark_args);
226 v.replace (this->body);
227 target_symbol_seen = v.target_symbol_seen;
228 if (target_symbol_seen)
229 for (unsigned i = 0; i < mark_args.size(); ++i)
230 {
231 vardecl* v = new vardecl;
232 v->name = "__mark_arg" + lex_cast(i+1);
233 v->tok = this->tok;
234 v->set_arity(0, this->tok);
235 v->type = mark_args[i]->stp_type;
236 v->skip_init = true;
237 this->locals.push_back (v);
238 }
239
240 if (sess.verbose > 2)
241 clog << "marker-based " << name << " mark=" << probe_name << " fmt='" << probe_format
242 << "'" << endl;
243 }
244
245
246 static int
247 skip_atoi(const char **s)
248 {
249 int i = 0;
250 while (isdigit(**s))
251 i = i * 10 + *((*s)++) - '0';
252 return i;
253 }
254
255
256 void
257 mark_derived_probe::parse_probe_format()
258 {
259 const char *fmt = probe_format.c_str();
260 int qualifier; // 'h', 'l', or 'L' for integer fields
261 mark_arg *arg;
262
263 for (; *fmt ; ++fmt)
264 {
265 if (*fmt != '%')
266 {
267 /* Skip text */
268 continue;
269 }
270
271 repeat:
272 ++fmt;
273
274 // skip conversion flags (if present)
275 switch (*fmt)
276 {
277 case '-':
278 case '+':
279 case ' ':
280 case '#':
281 case '0':
282 goto repeat;
283 }
284
285 // skip minimum field witdh (if present)
286 if (isdigit(*fmt))
287 skip_atoi(&fmt);
288
289 // skip precision (if present)
290 if (*fmt == '.')
291 {
292 ++fmt;
293 if (isdigit(*fmt))
294 skip_atoi(&fmt);
295 }
296
297 // get the conversion qualifier (if present)
298 qualifier = -1;
299 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L')
300 {
301 qualifier = *fmt;
302 ++fmt;
303 if (qualifier == 'l' && *fmt == 'l')
304 {
305 qualifier = 'L';
306 ++fmt;
307 }
308 }
309
310 // get the conversion type
311 switch (*fmt)
312 {
313 case 'c':
314 arg = new mark_arg;
315 arg->str = false;
316 arg->isptr = false;
317 arg->c_type = "int";
318 arg->stp_type = pe_long;
319 mark_args.push_back(arg);
320 continue;
321
322 case 's':
323 arg = new mark_arg;
324 arg->str = true;
325 arg->isptr = false;
326 arg->c_type = "char *";
327 arg->stp_type = pe_string;
328 mark_args.push_back(arg);
329 continue;
330
331 case 'p':
332 arg = new mark_arg;
333 arg->str = false;
334 arg->isptr = true;
335 // This should really be 'void *'. But, then we'll get a
336 // compile error when we assign the void pointer to an
337 // integer without a cast. So, we use 'long' instead, since
338 // it should have the same size as 'void *'.
339 arg->c_type = "long";
340 arg->stp_type = pe_long;
341 mark_args.push_back(arg);
342 continue;
343
344 case '%':
345 continue;
346
347 case 'o':
348 case 'X':
349 case 'x':
350 case 'd':
351 case 'i':
352 case 'u':
353 // fall through...
354 break;
355
356 default:
357 if (!*fmt)
358 --fmt;
359 continue;
360 }
361
362 arg = new mark_arg;
363 arg->str = false;
364 arg->isptr = false;
365 arg->stp_type = pe_long;
366 switch (qualifier)
367 {
368 case 'L':
369 arg->c_type = "long long";
370 break;
371
372 case 'l':
373 arg->c_type = "long";
374 break;
375
376 case 'h':
377 arg->c_type = "short";
378 break;
379
380 default:
381 arg->c_type = "int";
382 break;
383 }
384 mark_args.push_back(arg);
385 }
386 }
387
388
389 void
390 mark_derived_probe::join_group (systemtap_session& s)
391 {
392 if (! s.mark_derived_probes)
393 {
394 s.mark_derived_probes = new mark_derived_probe_group ();
395
396 // Make sure <linux/marker.h> is included early.
397 embeddedcode *ec = new embeddedcode;
398 ec->tok = NULL;
399 ec->code = string("#if ! defined(CONFIG_MARKERS)\n")
400 + string("#error \"Need CONFIG_MARKERS!\"\n")
401 + string("#endif\n")
402 + string("#include <linux/marker.h>\n");
403
404 s.embeds.push_back(ec);
405 }
406 s.mark_derived_probes->enroll (this);
407 }
408
409
410 void
411 mark_derived_probe::print_dupe_stamp (ostream& o)
412 {
413 if (target_symbol_seen)
414 for (unsigned i = 0; i < mark_args.size(); i++)
415 o << mark_args[i]->c_type << " __mark_arg" << (i+1) << endl;
416 }
417
418
419 void
420 mark_derived_probe::initialize_probe_context_vars (translator_output* o)
421 {
422 // If we haven't seen a target symbol for this probe, quit.
423 if (! target_symbol_seen)
424 return;
425
426 bool deref_fault_needed = false;
427 for (unsigned i = 0; i < mark_args.size(); i++)
428 {
429 string localname = "l->__mark_arg" + lex_cast(i+1);
430 switch (mark_args[i]->stp_type)
431 {
432 case pe_long:
433 o->newline() << localname << " = va_arg(*c->ips.kmark.mark_va_list, "
434 << mark_args[i]->c_type << ");";
435 break;
436
437 case pe_string:
438 // We're assuming that this is a kernel string (this code is
439 // basically the guts of kernel_string), not a user string.
440 o->newline() << "{ " << mark_args[i]->c_type
441 << " tmp_str = va_arg(*c->ips.kmark.mark_va_list, "
442 << mark_args[i]->c_type << ");";
443 o->newline() << "kderef_string (" << localname
444 << ", tmp_str, MAXSTRINGLEN); }";
445 deref_fault_needed = true;
446 break;
447
448 default:
449 throw semantic_error (_("cannot expand unknown type"));
450 break;
451 }
452 }
453 if (deref_fault_needed)
454 // Need to report errors?
455 o->newline() << "deref_fault: ;";
456 }
457
458 void
459 mark_derived_probe::getargs(std::list<std::string> &arg_set) const
460 {
461 //PR11761: hard-coded the basic variables
462 arg_set.push_back("$name:string");
463 arg_set.push_back("$format:string");
464 for (unsigned i = 0; i < mark_args.size(); i++)
465 {
466 string localname = "$arg" + lex_cast(i+1);
467 switch (mark_args[i]->stp_type)
468 {
469 case pe_long:
470 arg_set.push_back(localname+":long");
471 break;
472 case pe_string:
473 arg_set.push_back(localname+":string");
474 break;
475 default:
476 arg_set.push_back(localname+":unknown");
477 break;
478 }
479 }
480 }
481
482
483 void
484 mark_derived_probe_group::emit_module_decls (systemtap_session& s)
485 {
486 if (probes.empty())
487 return;
488
489 s.op->newline() << "/* ---- marker probes ---- */";
490
491 s.op->newline() << "static struct stap_marker_probe {";
492 s.op->newline(1) << "const char * const name;";
493 s.op->newline() << "const char * const format;";
494 s.op->newline() << "struct stap_probe * const probe;";
495 s.op->newline(-1) << "} stap_marker_probes [" << probes.size() << "] = {";
496 s.op->indent(1);
497 for (unsigned i=0; i < probes.size(); i++)
498 {
499 s.op->newline () << "{";
500 s.op->line() << " .name=" << lex_cast_qstring(probes[i]->probe_name) << ",";
501 s.op->line() << " .format=" << lex_cast_qstring(probes[i]->probe_format) << ",";
502 s.op->line() << " .probe=" << common_probe_init (probes[i]) << ",";
503 s.op->line() << " },";
504 }
505 s.op->newline(-1) << "};";
506 s.op->newline();
507
508
509 // Emit the marker callback function
510 s.op->newline();
511 s.op->newline() << "static void enter_marker_probe (void *probe_data, void *call_data, const char *fmt, va_list *args) {";
512 s.op->newline(1) << "struct stap_marker_probe *smp = (struct stap_marker_probe *)probe_data;";
513 common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "smp->probe",
514 "_STP_PROBE_HANDLER_MARKER");
515 s.op->newline() << "c->ips.kmark.marker_name = smp->name;";
516 s.op->newline() << "c->ips.kmark.marker_format = smp->format;";
517 s.op->newline() << "c->ips.kmark.mark_va_list = args;";
518 s.op->newline() << "(*smp->probe->ph) (c);";
519 s.op->newline() << "c->ips.kmark.mark_va_list = NULL;";
520
521 common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
522 s.op->newline(-1) << "}";
523
524 return;
525 }
526
527
528 void
529 mark_derived_probe_group::emit_module_init (systemtap_session &s)
530 {
531 if (probes.size () == 0)
532 return;
533
534 s.op->newline() << "/* init marker probes */";
535 s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {";
536 s.op->newline(1) << "struct stap_marker_probe *smp = &stap_marker_probes[i];";
537 s.op->newline() << "probe_point = smp->probe->pp;";
538 s.op->newline() << "rc = marker_probe_register(smp->name, smp->format, enter_marker_probe, smp);";
539 s.op->newline() << "if (rc) {";
540 s.op->newline(1) << "for (j=i-1; j>=0; j--) {"; // partial rollback
541 s.op->newline(1) << "struct stap_marker_probe *smp2 = &stap_marker_probes[j];";
542 s.op->newline() << "marker_probe_unregister(smp2->name, enter_marker_probe, smp2);";
543 s.op->newline(-1) << "}";
544 s.op->newline() << "break;"; // don't attempt to register any more probes
545 s.op->newline(-1) << "}";
546 s.op->newline(-1) << "}"; // for loop
547 }
548
549
550 void
551 mark_derived_probe_group::emit_module_exit (systemtap_session& s)
552 {
553 if (probes.empty())
554 return;
555
556 s.op->newline() << "/* deregister marker probes */";
557 s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {";
558 s.op->newline(1) << "struct stap_marker_probe *smp = &stap_marker_probes[i];";
559 s.op->newline() << "marker_probe_unregister(smp->name, enter_marker_probe, smp);";
560 s.op->newline(-1) << "}"; // for loop
561 }
562
563
564 struct mark_builder: public derived_probe_builder
565 {
566 private:
567 bool cache_initialized;
568 typedef multimap<string, string> mark_cache_t;
569 typedef multimap<string, string>::const_iterator mark_cache_const_iterator_t;
570 typedef pair<mark_cache_const_iterator_t, mark_cache_const_iterator_t>
571 mark_cache_const_iterator_pair_t;
572 mark_cache_t mark_cache;
573
574 public:
575 mark_builder(): cache_initialized(false) {}
576
577 void build_no_more (systemtap_session &s)
578 {
579 if (! mark_cache.empty())
580 {
581 if (s.verbose > 3)
582 clog << _("mark_builder releasing cache") << endl;
583 mark_cache.clear();
584 }
585 }
586
587 void build(systemtap_session & sess,
588 probe * base,
589 probe_point * location,
590 literal_map_t const & parameters,
591 vector<derived_probe *> & finished_results);
592 };
593
594
595 void
596 mark_builder::build(systemtap_session & sess,
597 probe * base,
598 probe_point *loc,
599 literal_map_t const & parameters,
600 vector<derived_probe *> & finished_results)
601 {
602 string mark_str_val;
603 bool has_mark_str = get_param (parameters, TOK_MARK, mark_str_val);
604 string mark_format_val;
605 bool has_mark_format = get_param (parameters, TOK_FORMAT, mark_format_val);
606 assert (has_mark_str);
607 (void) has_mark_str;
608
609 if (! cache_initialized)
610 {
611 cache_initialized = true;
612 string module_markers_path = sess.kernel_build_tree + "/Module.markers";
613
614 ifstream module_markers;
615 module_markers.open(module_markers_path.c_str(), ifstream::in);
616 if (! module_markers)
617 {
618 if (sess.verbose>3)
619 //TRANSLATORS: specific path cannot be opened
620 clog << module_markers_path << _(" cannot be opened: ")
621 << strerror(errno) << endl;
622 return;
623 }
624
625 string name, module, format;
626 do
627 {
628 module_markers >> name >> module;
629 getline(module_markers, format);
630
631 // trim leading whitespace
632 string::size_type notwhite = format.find_first_not_of(" \t");
633 format.erase(0, notwhite);
634
635 // If the format is empty, make sure we add back a space
636 // character, which is what MARK_NOARGS expands to.
637 if (format.length() == 0)
638 format = " ";
639
640 if (sess.verbose>3)
641 clog << "'" << name << "' '" << module << "' '" << format
642 << "'" << endl;
643
644 if (mark_cache.count(name) > 0)
645 {
646 // If we have 2 markers with the same we've got 2 cases:
647 // different format strings or duplicate format strings.
648 // If an existing marker in the cache doesn't have the
649 // same format string, add this marker.
650 mark_cache_const_iterator_pair_t ret;
651 mark_cache_const_iterator_t it;
652 bool matching_format_string = false;
653
654 ret = mark_cache.equal_range(name);
655 for (it = ret.first; it != ret.second; ++it)
656 {
657 if (format == it->second)
658 {
659 matching_format_string = true;
660 break;
661 }
662 }
663
664 if (! matching_format_string)
665 mark_cache.insert(pair<string,string>(name, format));
666 }
667 else
668 mark_cache.insert(pair<string,string>(name, format));
669 }
670 while (! module_markers.eof());
671 module_markers.close();
672 }
673
674 // Search marker list for matching markers
675 for (mark_cache_const_iterator_t it = mark_cache.begin();
676 it != mark_cache.end(); it++)
677 {
678 // Below, "rc" has negative polarity: zero iff matching.
679 int rc = fnmatch(mark_str_val.c_str(), it->first.c_str(), 0);
680 if (! rc)
681 {
682 bool add_result = true;
683
684 // Match format strings (if the user specified one)
685 if (has_mark_format && fnmatch(mark_format_val.c_str(),
686 it->second.c_str(), 0))
687 add_result = false;
688
689 if (add_result)
690 {
691 derived_probe *dp
692 = new mark_derived_probe (sess,
693 it->first, it->second,
694 base, loc);
695 finished_results.push_back (dp);
696 }
697 }
698 }
699 }
700
701
702
703 void
704 register_tapset_mark(systemtap_session& s)
705 {
706 match_node* root = s.pattern_root;
707 derived_probe_builder *builder = new mark_builder();
708
709 root = root->bind(TOK_KERNEL);
710 root = root->bind_str(TOK_MARK);
711
712 root->bind(builder);
713 root->bind_str(TOK_FORMAT)->bind(builder);
714 }
715
716 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.076839 seconds and 6 git commands to generate.