2 // Copyright (C) 2005-2010 Red Hat Inc.
3 // Copyright (C) 2005-2007 Intel Corporation.
4 // Copyright (C) 2008 James.Bottomley@HansenPartnership.com
6 // This file is part of systemtap, and is free software. You can
7 // redistribute it and/or modify it under the terms of the GNU General
8 // Public License (GPL); either version 2, or (at your option) any
14 #include "translate.h"
22 using namespace __gnu_cxx
;
25 static const string
TOK_PROCFS("procfs");
26 static const string
TOK_READ("read");
27 static const string
TOK_WRITE("write");
28 static const string
TOK_MAXSIZE("maxsize");
29 static const string
TOK_UMASK("umask");
32 // ------------------------------------------------------------------------
33 // procfs file derived probes
34 // ------------------------------------------------------------------------
37 struct procfs_derived_probe
: public derived_probe
41 bool target_symbol_seen
;
46 procfs_derived_probe (systemtap_session
&, probe
* p
, probe_point
* l
, string ps
, bool w
, int64_t m
, int64_t umask
);
47 void join_group (systemtap_session
& s
);
51 struct procfs_probe_set
53 procfs_derived_probe
* read_probe
;
54 procfs_derived_probe
* write_probe
;
56 procfs_probe_set () : read_probe (NULL
), write_probe (NULL
) {}
60 struct procfs_derived_probe_group
: public generic_dpg
<procfs_derived_probe
>
63 map
<string
, procfs_probe_set
*> probes_by_path
;
64 typedef map
<string
, procfs_probe_set
*>::iterator p_b_p_iterator
;
66 bool has_write_probes
;
69 procfs_derived_probe_group () :
70 has_read_probes(false), has_write_probes(false) {}
72 void enroll (procfs_derived_probe
* probe
);
73 void emit_module_decls (systemtap_session
& s
);
74 void emit_module_init (systemtap_session
& s
);
75 void emit_module_exit (systemtap_session
& s
);
79 struct procfs_var_expanding_visitor
: public var_expanding_visitor
81 procfs_var_expanding_visitor(systemtap_session
& s
, const string
& pn
,
82 string path
, bool write_probe
);
84 systemtap_session
& sess
;
88 bool target_symbol_seen
;
90 void visit_target_symbol (target_symbol
* e
);
94 procfs_derived_probe::procfs_derived_probe (systemtap_session
&s
, probe
* p
,
95 probe_point
* l
, string ps
, bool w
,
96 int64_t m
, int64_t umask
):
97 derived_probe(p
, l
), path(ps
), write(w
), target_symbol_seen(false),
98 maxsize_val(m
), umask(umask
)
100 // Expand local variables in the probe body
101 procfs_var_expanding_visitor
v (s
, name
, path
, write
);
102 v
.replace (this->body
);
103 target_symbol_seen
= v
.target_symbol_seen
;
108 procfs_derived_probe::join_group (systemtap_session
& s
)
110 if (! s
.procfs_derived_probes
)
112 s
.procfs_derived_probes
= new procfs_derived_probe_group ();
114 // Make sure 'struct _stp_procfs_data' is defined early.
115 embeddedcode
*ec
= new embeddedcode
;
117 ec
->code
= string("struct _stp_procfs_data {\n")
118 + string(" char *buffer;\n")
119 + string(" size_t bufsize;\n")
120 + string(" size_t count;\n")
122 + string("#ifndef STP_PROCFS_BUFSIZE\n")
123 + string("#define STP_PROCFS_BUFSIZE MAXSTRINGLEN\n")
124 + string("#endif\n");
125 s
.embeds
.push_back(ec
);
127 s
.procfs_derived_probes
->enroll (this);
132 procfs_derived_probe_group::enroll (procfs_derived_probe
* p
)
134 procfs_probe_set
*pset
;
136 if (probes_by_path
.count(p
->path
) == 0)
138 pset
= new procfs_probe_set
;
139 probes_by_path
[p
->path
] = pset
;
143 pset
= probes_by_path
[p
->path
];
145 // You can only specify 1 read and 1 write probe.
146 if (p
->write
&& pset
->write_probe
!= NULL
)
147 throw semantic_error(_("only one write procfs probe can exist for procfs path \"") + p
->path
+ "\"");
148 else if (! p
->write
&& pset
->read_probe
!= NULL
)
149 throw semantic_error(_("only one read procfs probe can exist for procfs path \"") + p
->path
+ "\"");
151 // XXX: multiple writes should be acceptable
156 pset
->write_probe
= p
;
157 has_write_probes
= true;
161 pset
->read_probe
= p
;
162 has_read_probes
= true;
168 procfs_derived_probe_group::emit_module_decls (systemtap_session
& s
)
170 if (probes_by_path
.empty())
173 s
.op
->newline() << "/* ---- procfs probes ---- */";
174 s
.op
->newline() << "#include \"procfs.c\"";
175 s
.op
->newline() << "#include \"procfs-probes.c\"";
177 // Emit the procfs probe buffer structure
178 s
.op
->newline() << "static struct stap_procfs_probe_buffer {";
180 unsigned buf_index
= 0; // used for buffer naming
181 for (p_b_p_iterator it
= probes_by_path
.begin(); it
!= probes_by_path
.end();
184 procfs_probe_set
*pset
= it
->second
;
185 s
.op
->newline() << "char buf_" << buf_index
++;
187 if (pset
->read_probe
!= NULL
)
189 if (pset
->read_probe
->maxsize_val
== 0)
190 s
.op
->line() << "[STP_PROCFS_BUFSIZE];";
192 s
.op
->line() << "[" << pset
->read_probe
->maxsize_val
<< "];";
195 s
.op
->line() << "[MAXSTRINGLEN];";
197 s
.op
->newline(-1) << "} stap_procfs_probe_buffers;";
199 // Emit the procfs probe data list
200 s
.op
->newline() << "static struct stap_procfs_probe stap_procfs_probes[] = {";
204 for (p_b_p_iterator it
= probes_by_path
.begin(); it
!= probes_by_path
.end();
207 procfs_probe_set
*pset
= it
->second
;
209 s
.op
->newline() << "{";
210 s
.op
->line() << " .path=" << lex_cast_qstring (it
->first
) << ",";
212 if (pset
->read_probe
!= NULL
)
213 s
.op
->line() << " .read_probe=" << common_probe_init (pset
->read_probe
) << ",";
215 if (pset
->write_probe
!= NULL
)
216 s
.op
->line() << " .write_probe=" << common_probe_init (pset
->write_probe
) << ",";
218 s
.op
->line() << " .buffer=stap_procfs_probe_buffers.buf_" << buf_index
++ << ",";
219 if (pset
->read_probe
!= NULL
)
221 if (pset
->read_probe
->maxsize_val
== 0)
222 s
.op
->line() << " .bufsize=STP_PROCFS_BUFSIZE,";
224 s
.op
->line() << " .bufsize="
225 << pset
->read_probe
->maxsize_val
<< ",";
228 s
.op
->line() << " .bufsize=MAXSTRINGLEN,";
230 s
.op
->line() << " .permissions=" << (((pset
->read_probe
? 0444 : 0)
231 | (pset
->write_probe
? 0222 : 0)) &~
232 ((pset
->read_probe
? pset
->read_probe
->umask
: 0)
233 | (pset
->write_probe
? pset
->write_probe
->umask
: 0)))
236 s
.op
->line() << " },";
238 s
.op
->newline(-1) << "};";
240 // Output routine to fill in the buffer with our data. Note that we
241 // need to do this even in the case where we have no read probes,
242 // but we can skip most of it then.
245 s
.op
->newline() << "static int _stp_proc_fill_read_buffer(struct stap_procfs_probe *spp) {";
249 s
.op
->newline() << "struct _stp_procfs_data pdata;";
251 common_probe_entryfn_prologue (s
.op
, "STAP_SESSION_RUNNING",
253 "_STP_PROBE_HANDLER_PROCFS");
255 s
.op
->newline() << "pdata.buffer = spp->buffer;";
256 s
.op
->newline() << "pdata.bufsize = spp->bufsize;";
257 s
.op
->newline() << "if (c->ips.procfs_data == NULL)";
258 s
.op
->newline(1) << "c->ips.procfs_data = &pdata;";
259 s
.op
->newline(-1) << "else {";
261 s
.op
->newline(1) << "if (unlikely (atomic_inc_return (& skipped_count) > MAXSKIPPED)) {";
262 s
.op
->newline(1) << "atomic_set (& session_state, STAP_SESSION_ERROR);";
263 s
.op
->newline() << "_stp_exit ();";
264 s
.op
->newline(-1) << "}";
265 s
.op
->newline() << "atomic_dec (& c->busy);";
266 s
.op
->newline() << "goto probe_epilogue;";
267 s
.op
->newline(-1) << "}";
269 // call probe function
270 s
.op
->newline() << "(*spp->read_probe->ph) (c);";
272 // Note that _procfs_value_set copied string data into spp->buffer
273 s
.op
->newline() << "c->ips.procfs_data = NULL;";
274 s
.op
->newline() << "spp->needs_fill = 0;";
275 s
.op
->newline() << "spp->count = strlen(spp->buffer);";
277 common_probe_entryfn_epilogue (s
.op
, true, s
.suppress_handler_errors
);
279 s
.op
->newline() << "if (spp->needs_fill) {";
280 s
.op
->newline(1) << "spp->needs_fill = 0;";
281 s
.op
->newline() << "return -EIO;";
282 s
.op
->newline(-1) << "}";
284 s
.op
->newline() << "return 0;";
285 s
.op
->newline(-1) << "}";
287 // Output routine to read data. Note that we need to do this even
288 // in the case where we have no write probes, but we can skip most
290 s
.op
->newline() << "static int _stp_process_write_buffer(struct stap_procfs_probe *spp, const char __user *buf, size_t count) {";
292 s
.op
->newline() << "int retval = 0;";
293 if (has_write_probes
)
295 s
.op
->newline() << "struct _stp_procfs_data pdata;";
297 common_probe_entryfn_prologue (s
.op
, "STAP_SESSION_RUNNING",
299 "_STP_PROBE_HANDLER_PROCFS");
301 // We've got 2 problems here. The data count could be greater
302 // than MAXSTRINGLEN or greater than the bufsize (if the same
303 // procfs file had a size less than MAXSTRINGLEN).
304 s
.op
->newline() << "if (count >= MAXSTRINGLEN)";
305 s
.op
->newline(1) << "count = MAXSTRINGLEN - 1;";
307 s
.op
->newline() << "pdata.bufsize = spp->bufsize;";
308 s
.op
->newline() << "if (count >= pdata.bufsize)";
309 s
.op
->newline(1) << "count = pdata.bufsize - 1;";
312 s
.op
->newline() << "pdata.buffer = (char *)buf;";
313 s
.op
->newline() << "pdata.count = count;";
315 s
.op
->newline() << "if (c->ips.procfs_data == NULL)";
316 s
.op
->newline(1) << "c->ips.procfs_data = &pdata;";
317 s
.op
->newline(-1) << "else {";
319 s
.op
->newline(1) << "if (unlikely (atomic_inc_return (& skipped_count) > MAXSKIPPED)) {";
320 s
.op
->newline(1) << "atomic_set (& session_state, STAP_SESSION_ERROR);";
321 s
.op
->newline() << "_stp_exit ();";
322 s
.op
->newline(-1) << "}";
323 s
.op
->newline() << "atomic_dec (& c->busy);";
324 s
.op
->newline() << "goto probe_epilogue;";
325 s
.op
->newline(-1) << "}";
327 // call probe function
328 s
.op
->newline() << "(*spp->write_probe->ph) (c);";
330 s
.op
->newline() << "c->ips.procfs_data = NULL;";
331 s
.op
->newline() << "if (c->last_error == 0) {";
332 s
.op
->newline(1) << "retval = count;";
333 s
.op
->newline(-1) << "}";
335 common_probe_entryfn_epilogue (s
.op
, true, s
.suppress_handler_errors
);
338 s
.op
->newline() << "return retval;";
339 s
.op
->newline(-1) << "}";
344 procfs_derived_probe_group::emit_module_init (systemtap_session
& s
)
346 if (probes_by_path
.empty())
349 s
.op
->newline() << "for (i = 0; i < " << probes_by_path
.size() << "; i++) {";
350 s
.op
->newline(1) << "struct stap_procfs_probe *spp = &stap_procfs_probes[i];";
352 s
.op
->newline() << "if (spp->read_probe)";
353 s
.op
->newline(1) << "probe_point = spp->read_probe->pp;";
354 s
.op
->newline(-1) << "else";
355 s
.op
->newline(1) << "probe_point = spp->write_probe->pp;";
358 s
.op
->newline() << "_spp_init(spp);";
359 s
.op
->newline() << "rc = _stp_create_procfs(spp->path, i, &_stp_proc_fops, spp->permissions);";
361 s
.op
->newline() << "if (rc) {";
362 s
.op
->newline(1) << "_stp_close_procfs();";
364 s
.op
->newline() << "for (i = 0; i < " << probes_by_path
.size() << "; i++) {";
365 s
.op
->newline(1) << "spp = &stap_procfs_probes[i];";
366 s
.op
->newline() << "_spp_shutdown(spp);";
367 s
.op
->newline(-1) << "}";
368 s
.op
->newline() << "break;";
369 s
.op
->newline(-1) << "}";
371 s
.op
->newline() << "_stp_procfs_files[i]->data = spp;";
372 s
.op
->newline(-1) << "}"; // for loop
377 procfs_derived_probe_group::emit_module_exit (systemtap_session
& s
)
379 if (probes_by_path
.empty())
382 s
.op
->newline() << "_stp_close_procfs();";
383 s
.op
->newline() << "for (i = 0; i < " << probes_by_path
.size() << "; i++) {";
384 s
.op
->newline(1) << "struct stap_procfs_probe *spp = &stap_procfs_probes[i];";
385 s
.op
->newline() << "_spp_shutdown(spp);";
386 s
.op
->newline(-1) << "}";
390 procfs_var_expanding_visitor::procfs_var_expanding_visitor (systemtap_session
& s
,
394 sess (s
), probe_name (pn
), path (path
), write_probe (write_probe
),
395 target_symbol_seen (false)
397 // procfs probes can also handle '.='.
398 valid_ops
.insert (".=");
403 procfs_var_expanding_visitor::visit_target_symbol (target_symbol
* e
)
407 assert(e
->name
.size() > 0 && e
->name
[0] == '$');
409 if (e
->name
!= "$value")
410 throw semantic_error (_("invalid target symbol for procfs probe, $value expected"),
413 e
->assert_no_components("procfs");
415 bool lvalue
= is_active_lvalue(e
);
416 if (write_probe
&& lvalue
)
417 throw semantic_error(_("procfs $value variable is read-only in a procfs write probe"), e
->tok
);
418 else if (! write_probe
&& ! lvalue
)
419 throw semantic_error(_("procfs $value variable cannot be read in a procfs read probe"), e
->tok
);
422 throw semantic_error(_("cannot take address of procfs variable"), e
->tok
);
424 // Remember that we've seen a target variable.
425 target_symbol_seen
= true;
427 // Synthesize a function.
428 functiondecl
*fdecl
= new functiondecl
;
429 fdecl
->synthetic
= true;
431 embeddedcode
*ec
= new embeddedcode
;
435 string locvalue
= "CONTEXT->ips.procfs_data";
439 fname
= "_procfs_value_get";
440 ec
->code
= string(" struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue
+ string("); /* pure */\n")
442 + string(" _stp_copy_from_user(THIS->__retvalue, data->buffer, data->count);\n")
443 + string(" THIS->__retvalue[data->count] = '\\0';\n");
449 fname
= "_procfs_value_set";
450 ec
->code
= string("struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue
+ string(");\n")
451 + string(" strlcpy(data->buffer, THIS->value, data->bufsize);\n")
452 + string(" data->count = strlen(data->buffer);\n");
454 else if (*op
== ".=")
456 fname
= "_procfs_value_append";
457 ec
->code
= string("struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue
+ string(");\n")
458 + string(" strlcat(data->buffer, THIS->value, data->bufsize);\n")
459 + string(" data->count = strlen(data->buffer);\n");
463 throw semantic_error (_("Only the following assign operators are"
464 " implemented on procfs read target variables:"
465 " '=', '.='"), e
->tok
);
468 fname
+= lex_cast(++tick
);
472 fdecl
->type
= pe_string
;
476 // Modify the fdecl so it carries a single pe_string formal
477 // argument called "value".
479 vardecl
*v
= new vardecl
;
483 fdecl
->formal_args
.push_back(v
);
487 // Synthesize a functioncall.
488 functioncall
* n
= new functioncall
;
494 // Provide the functioncall to our parent, so that it can be
495 // used to substitute for the assignment node immediately above
497 assert(!target_symbol_setter_functioncalls
.empty());
498 *(target_symbol_setter_functioncalls
.top()) = n
;
503 catch (const semantic_error
&er
)
511 struct procfs_builder
: public derived_probe_builder
514 virtual void build(systemtap_session
& sess
,
516 probe_point
* location
,
517 literal_map_t
const & parameters
,
518 vector
<derived_probe
*> & finished_results
);
523 procfs_builder::build(systemtap_session
& sess
,
525 probe_point
* location
,
526 literal_map_t
const & parameters
,
527 vector
<derived_probe
*> & finished_results
)
530 bool has_procfs
= get_param(parameters
, TOK_PROCFS
, path
);
531 bool has_read
= (parameters
.find(TOK_READ
) != parameters
.end());
532 bool has_write
= (parameters
.find(TOK_WRITE
) != parameters
.end());
533 bool has_umask
= (parameters
.find(TOK_UMASK
) != parameters
.end());
534 int64_t maxsize_val
= 0;
537 get_param(parameters
, TOK_UMASK
, umask_val
);
547 // Validate '.maxsize(NNN)', if it exists.
548 if (get_param(parameters
, TOK_MAXSIZE
, maxsize_val
))
550 if (maxsize_val
<= 0)
551 throw semantic_error (_("maxsize must be greater than 0"));
554 // If no procfs path, default to "command". The runtime will do
555 // this for us, but if we don't do it here, we'll think the
556 // following 2 probes are attached to different paths:
558 // probe procfs("command").read {}"
559 // probe procfs.write {}
563 // If we have a path, we need to validate it.
566 string::size_type start_pos
, end_pos
;
569 while ((end_pos
= path
.find('/', start_pos
)) != string::npos
)
571 // Make sure it doesn't start with '/'.
573 throw semantic_error (_("procfs path cannot start with a '/'"),
574 location
->components
.front()->tok
);
576 component
= path
.substr(start_pos
, end_pos
- start_pos
);
577 // Make sure it isn't empty.
578 if (component
.size() == 0)
579 throw semantic_error (_("procfs path component cannot be empty"),
580 location
->components
.front()->tok
);
581 // Make sure it isn't relative.
582 else if (component
== "." || component
== "..")
583 throw semantic_error (_("procfs path cannot be relative (and contain '.' or '..')"), location
->components
.front()->tok
);
585 start_pos
= end_pos
+ 1;
587 component
= path
.substr(start_pos
);
588 // Make sure it doesn't end with '/'.
589 if (component
.size() == 0)
590 throw semantic_error (_("procfs path cannot end with a '/'"), location
->components
.front()->tok
);
591 // Make sure it isn't relative.
592 else if (component
== "." || component
== "..")
593 throw semantic_error (_("procfs path cannot be relative (and contain '.' or '..')"), location
->components
.front()->tok
);
596 if (!(has_read
^ has_write
))
597 throw semantic_error (_("need read/write component"), location
->components
.front()->tok
);
599 finished_results
.push_back(new procfs_derived_probe(sess
, base
, location
,
601 maxsize_val
, umask_val
));
606 register_tapset_procfs(systemtap_session
& s
)
608 match_node
* root
= s
.pattern_root
;
609 derived_probe_builder
*builder
= new procfs_builder();
611 root
->bind(TOK_PROCFS
)->bind(TOK_READ
)->bind(builder
);
612 root
->bind(TOK_PROCFS
)->bind_num(TOK_UMASK
)->bind(TOK_READ
)->bind(builder
);
613 root
->bind(TOK_PROCFS
)->bind(TOK_READ
)->bind_num(TOK_MAXSIZE
)->bind(builder
);
614 root
->bind(TOK_PROCFS
)->bind_num(TOK_UMASK
)->bind(TOK_READ
)->bind_num(TOK_MAXSIZE
)->bind(builder
);
615 root
->bind_str(TOK_PROCFS
)->bind(TOK_READ
)->bind(builder
);
616 root
->bind_str(TOK_PROCFS
)->bind_num(TOK_UMASK
)->bind(TOK_READ
)->bind(builder
);
617 root
->bind_str(TOK_PROCFS
)->bind(TOK_READ
)->bind_num(TOK_MAXSIZE
)->bind(builder
);
618 root
->bind_str(TOK_PROCFS
)->bind_num(TOK_UMASK
)->bind(TOK_READ
)->bind_num(TOK_MAXSIZE
)->bind(builder
);
620 root
->bind(TOK_PROCFS
)->bind(TOK_WRITE
)->bind(builder
);
621 root
->bind(TOK_PROCFS
)->bind_num(TOK_UMASK
)->bind(TOK_WRITE
)->bind(builder
);
622 root
->bind_str(TOK_PROCFS
)->bind(TOK_WRITE
)->bind(builder
);
623 root
->bind_str(TOK_PROCFS
)->bind_num(TOK_UMASK
)->bind(TOK_WRITE
)->bind(builder
);
628 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */