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