2 // Copyright (C) 2005-2010 Red Hat Inc.
3 // Copyright (C) 2005-2007 Intel Corporation.
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
13 #include "translate.h"
21 using namespace __gnu_cxx
;
24 static const string
TOK_PROCFS("procfs");
25 static const string
TOK_READ("read");
26 static const string
TOK_WRITE("write");
27 static const string
TOK_MAXSIZE("maxsize");
28 static const string
TOK_UMASK("umask");
31 // ------------------------------------------------------------------------
32 // procfs file derived probes
33 // ------------------------------------------------------------------------
36 struct procfs_derived_probe
: public derived_probe
40 bool target_symbol_seen
;
45 procfs_derived_probe (systemtap_session
&, probe
* p
, probe_point
* l
, string ps
, bool w
, int64_t m
, int64_t umask
);
46 void join_group (systemtap_session
& s
);
50 struct procfs_probe_set
52 procfs_derived_probe
* read_probe
;
53 procfs_derived_probe
* write_probe
;
55 procfs_probe_set () : read_probe (NULL
), write_probe (NULL
) {}
59 struct procfs_derived_probe_group
: public generic_dpg
<procfs_derived_probe
>
62 map
<string
, procfs_probe_set
*> probes_by_path
;
63 typedef map
<string
, procfs_probe_set
*>::iterator p_b_p_iterator
;
65 bool has_write_probes
;
68 procfs_derived_probe_group () :
69 has_read_probes(false), has_write_probes(false) {}
71 void enroll (procfs_derived_probe
* probe
);
72 void emit_kernel_module_init (systemtap_session
& s
);
73 void emit_kernel_module_exit (systemtap_session
& s
);
74 void emit_module_decls (systemtap_session
& s
);
75 void emit_module_init (systemtap_session
& s
);
76 void emit_module_exit (systemtap_session
& s
);
80 struct procfs_var_expanding_visitor
: public var_expanding_visitor
82 procfs_var_expanding_visitor(systemtap_session
& s
, const string
& pn
,
83 string path
, bool write_probe
);
85 systemtap_session
& sess
;
89 bool target_symbol_seen
;
91 void visit_target_symbol (target_symbol
* e
);
95 procfs_derived_probe::procfs_derived_probe (systemtap_session
&s
, probe
* p
,
96 probe_point
* l
, string ps
, bool w
,
97 int64_t m
, int64_t umask
):
98 derived_probe(p
, l
), path(ps
), write(w
), target_symbol_seen(false),
99 maxsize_val(m
), umask(umask
)
101 // Expand local variables in the probe body
102 procfs_var_expanding_visitor
v (s
, name
, path
, write
);
103 v
.replace (this->body
);
104 target_symbol_seen
= v
.target_symbol_seen
;
109 procfs_derived_probe::join_group (systemtap_session
& s
)
111 if (! s
.procfs_derived_probes
)
113 s
.procfs_derived_probes
= new procfs_derived_probe_group ();
115 // Make sure 'struct _stp_procfs_data' is defined early.
116 embeddedcode
*ec
= new embeddedcode
;
118 ec
->code
= string("struct _stp_procfs_data {\n")
119 + string(" char *buffer;\n")
120 + string(" size_t bufsize;\n")
121 + string(" size_t count;\n")
123 + string("#ifndef STP_PROCFS_BUFSIZE\n")
124 + string("#define STP_PROCFS_BUFSIZE MAXSTRINGLEN\n")
125 + string("#endif\n");
126 s
.embeds
.push_back(ec
);
128 s
.procfs_derived_probes
->enroll (this);
133 procfs_derived_probe_group::enroll (procfs_derived_probe
* p
)
135 procfs_probe_set
*pset
;
137 if (probes_by_path
.count(p
->path
) == 0)
139 pset
= new procfs_probe_set
;
140 probes_by_path
[p
->path
] = pset
;
144 pset
= probes_by_path
[p
->path
];
146 // You can only specify 1 read and 1 write probe.
147 if (p
->write
&& pset
->write_probe
!= NULL
)
148 throw SEMANTIC_ERROR(_("only one write procfs probe can exist for procfs path \"") + p
->path
+ "\"");
149 else if (! p
->write
&& pset
->read_probe
!= NULL
)
150 throw SEMANTIC_ERROR(_("only one read procfs probe can exist for procfs path \"") + p
->path
+ "\"");
152 // XXX: multiple writes should be acceptable
157 pset
->write_probe
= p
;
158 has_write_probes
= true;
162 pset
->read_probe
= p
;
163 has_read_probes
= true;
169 procfs_derived_probe_group::emit_kernel_module_init (systemtap_session
& s
)
171 if (probes_by_path
.empty())
173 s
.op
->newline() << "rc = _stp_mkdir_proc_module();";
178 procfs_derived_probe_group::emit_kernel_module_exit (systemtap_session
& s
)
180 if (probes_by_path
.empty())
182 // If we're using the original transport, it uses the
183 // '/proc/systemtap/{module_name}' directory to store control
184 // files. Let the transport layer clean up that directory.
185 s
.op
->newline() << "#if (STP_TRANSPORT_VERSION != 1)";
186 s
.op
->newline() << "_stp_rmdir_proc_module();";
187 s
.op
->newline() << "#endif";
192 procfs_derived_probe_group::emit_module_decls (systemtap_session
& s
)
194 if (probes_by_path
.empty())
197 s
.op
->newline() << "/* ---- procfs probes ---- */";
198 s
.op
->newline() << "#include \"procfs.c\"";
199 s
.op
->newline() << "#include \"procfs-probes.c\"";
201 // Emit the procfs probe buffer structure
202 s
.op
->newline() << "static struct stap_procfs_probe_buffer {";
204 unsigned buf_index
= 0; // used for buffer naming
205 for (p_b_p_iterator it
= probes_by_path
.begin(); it
!= probes_by_path
.end();
208 procfs_probe_set
*pset
= it
->second
;
209 s
.op
->newline() << "char buf_" << buf_index
++;
211 if (pset
->read_probe
!= NULL
)
213 if (pset
->read_probe
->maxsize_val
== 0)
214 s
.op
->line() << "[STP_PROCFS_BUFSIZE];";
216 s
.op
->line() << "[" << pset
->read_probe
->maxsize_val
<< "];";
219 s
.op
->line() << "[MAXSTRINGLEN];";
221 s
.op
->newline(-1) << "} stap_procfs_probe_buffers;";
223 // Emit the procfs probe data list
224 s
.op
->newline() << "static struct stap_procfs_probe stap_procfs_probes[] = {";
228 for (p_b_p_iterator it
= probes_by_path
.begin(); it
!= probes_by_path
.end();
231 procfs_probe_set
*pset
= it
->second
;
233 s
.op
->newline() << "{";
234 s
.op
->line() << " .path=" << lex_cast_qstring (it
->first
) << ",";
236 if (pset
->read_probe
!= NULL
)
237 s
.op
->line() << " .read_probe=" << common_probe_init (pset
->read_probe
) << ",";
239 if (pset
->write_probe
!= NULL
)
240 s
.op
->line() << " .write_probe=" << common_probe_init (pset
->write_probe
) << ",";
242 s
.op
->line() << " .buffer=stap_procfs_probe_buffers.buf_" << buf_index
++ << ",";
243 if (pset
->read_probe
!= NULL
)
245 if (pset
->read_probe
->maxsize_val
== 0)
246 s
.op
->line() << " .bufsize=STP_PROCFS_BUFSIZE,";
248 s
.op
->line() << " .bufsize="
249 << pset
->read_probe
->maxsize_val
<< ",";
252 s
.op
->line() << " .bufsize=MAXSTRINGLEN,";
254 s
.op
->line() << " .permissions=" << (((pset
->read_probe
? 0444 : 0)
255 | (pset
->write_probe
? 0222 : 0)) &~
256 ((pset
->read_probe
? pset
->read_probe
->umask
: 0)
257 | (pset
->write_probe
? pset
->write_probe
->umask
: 0)))
260 s
.op
->line() << " },";
262 s
.op
->newline(-1) << "};";
264 // Output routine to fill in the buffer with our data. Note that we
265 // need to do this even in the case where we have no read probes,
266 // but we can skip most of it then.
269 s
.op
->newline() << "static int _stp_proc_fill_read_buffer(struct stap_procfs_probe *spp) {";
273 s
.op
->newline() << "struct _stp_procfs_data pdata;";
275 common_probe_entryfn_prologue (s
, "STAP_SESSION_RUNNING",
277 "stp_probe_type_procfs");
279 s
.op
->newline() << "pdata.buffer = spp->buffer;";
280 s
.op
->newline() << "pdata.bufsize = spp->bufsize;";
281 s
.op
->newline() << "if (c->ips.procfs_data == NULL)";
282 s
.op
->newline(1) << "c->ips.procfs_data = &pdata;";
283 s
.op
->newline(-1) << "else {";
285 s
.op
->newline(1) << "if (unlikely (atomic_inc_return (skipped_count()) > MAXSKIPPED)) {";
286 s
.op
->newline(1) << "atomic_set (session_state(), STAP_SESSION_ERROR);";
287 s
.op
->newline() << "_stp_exit ();";
288 s
.op
->newline(-1) << "}";
289 s
.op
->newline() << "atomic_dec (& c->busy);";
290 s
.op
->newline() << "goto probe_epilogue;";
291 s
.op
->newline(-1) << "}";
293 // call probe function
294 s
.op
->newline() << "(*spp->read_probe->ph) (c);";
296 // Note that _procfs_value_set copied string data into spp->buffer
297 s
.op
->newline() << "c->ips.procfs_data = NULL;";
298 s
.op
->newline() << "spp->needs_fill = 0;";
299 s
.op
->newline() << "spp->count = strlen(spp->buffer);";
301 common_probe_entryfn_epilogue (s
, true);
303 s
.op
->newline() << "if (spp->needs_fill) {";
304 s
.op
->newline(1) << "spp->needs_fill = 0;";
305 s
.op
->newline() << "return -EIO;";
306 s
.op
->newline(-1) << "}";
308 s
.op
->newline() << "return 0;";
309 s
.op
->newline(-1) << "}";
311 // Output routine to read data. Note that we need to do this even
312 // in the case where we have no write probes, but we can skip most
314 s
.op
->newline() << "static int _stp_process_write_buffer(struct stap_procfs_probe *spp, const char __user *buf, size_t count) {";
316 s
.op
->newline() << "int retval = 0;";
317 if (has_write_probes
)
319 s
.op
->newline() << "struct _stp_procfs_data pdata;";
321 common_probe_entryfn_prologue (s
, "STAP_SESSION_RUNNING",
323 "stp_probe_type_procfs");
325 // We've got 2 problems here. The data count could be greater
326 // than MAXSTRINGLEN or greater than the bufsize (if the same
327 // procfs file had a size less than MAXSTRINGLEN).
328 s
.op
->newline() << "if (count >= MAXSTRINGLEN)";
329 s
.op
->newline(1) << "count = MAXSTRINGLEN - 1;";
331 s
.op
->newline() << "pdata.bufsize = spp->bufsize;";
332 s
.op
->newline() << "if (count >= pdata.bufsize)";
333 s
.op
->newline(1) << "count = pdata.bufsize - 1;";
336 s
.op
->newline() << "pdata.buffer = (char *)buf;";
337 s
.op
->newline() << "pdata.count = count;";
339 s
.op
->newline() << "if (c->ips.procfs_data == NULL)";
340 s
.op
->newline(1) << "c->ips.procfs_data = &pdata;";
341 s
.op
->newline(-1) << "else {";
343 s
.op
->newline(1) << "if (unlikely (atomic_inc_return (skipped_count()) > MAXSKIPPED)) {";
344 s
.op
->newline(1) << "atomic_set (session_state(), STAP_SESSION_ERROR);";
345 s
.op
->newline() << "_stp_exit ();";
346 s
.op
->newline(-1) << "}";
347 s
.op
->newline() << "atomic_dec (& c->busy);";
348 s
.op
->newline() << "goto probe_epilogue;";
349 s
.op
->newline(-1) << "}";
351 // call probe function
352 s
.op
->newline() << "(*spp->write_probe->ph) (c);";
354 s
.op
->newline() << "c->ips.procfs_data = NULL;";
355 s
.op
->newline() << "if (c->last_error == 0) {";
356 s
.op
->newline(1) << "retval = count;";
357 s
.op
->newline(-1) << "}";
359 common_probe_entryfn_epilogue (s
, true);
362 s
.op
->newline() << "return retval;";
363 s
.op
->newline(-1) << "}";
368 procfs_derived_probe_group::emit_module_init (systemtap_session
& s
)
370 if (probes_by_path
.empty())
373 s
.op
->newline() << "for (i = 0; i < " << probes_by_path
.size() << "; i++) {";
374 s
.op
->newline(1) << "struct stap_procfs_probe *spp = &stap_procfs_probes[i];";
376 s
.op
->newline() << "if (spp->read_probe)";
377 s
.op
->newline(1) << "probe_point = spp->read_probe->pp;";
378 s
.op
->newline(-1) << "else";
379 s
.op
->newline(1) << "probe_point = spp->write_probe->pp;";
382 s
.op
->newline() << "_spp_init(spp);";
383 s
.op
->newline() << "rc = _stp_create_procfs(spp->path, i, &_stp_proc_fops, spp->permissions, spp);";
385 s
.op
->newline() << "if (rc) {";
386 s
.op
->newline(1) << "_stp_close_procfs();";
388 s
.op
->newline() << "for (i = 0; i < " << probes_by_path
.size() << "; i++) {";
389 s
.op
->newline(1) << "spp = &stap_procfs_probes[i];";
390 s
.op
->newline() << "_spp_shutdown(spp);";
391 s
.op
->newline(-1) << "}";
392 s
.op
->newline() << "break;";
393 s
.op
->newline(-1) << "}";
394 s
.op
->newline(-1) << "}"; // for loop
399 procfs_derived_probe_group::emit_module_exit (systemtap_session
& s
)
401 if (probes_by_path
.empty())
404 s
.op
->newline() << "_stp_close_procfs();";
405 s
.op
->newline() << "for (i = 0; i < " << probes_by_path
.size() << "; i++) {";
406 s
.op
->newline(1) << "struct stap_procfs_probe *spp = &stap_procfs_probes[i];";
407 s
.op
->newline() << "_spp_shutdown(spp);";
408 s
.op
->newline(-1) << "}";
412 procfs_var_expanding_visitor::procfs_var_expanding_visitor (systemtap_session
& s
,
416 sess (s
), probe_name (pn
), path (path
), write_probe (write_probe
),
417 target_symbol_seen (false)
419 // procfs probes can also handle '.='.
420 valid_ops
.insert (".=");
425 procfs_var_expanding_visitor::visit_target_symbol (target_symbol
* e
)
429 assert(e
->name
.size() > 0 && e
->name
[0] == '$');
431 if (e
->name
!= "$value")
432 throw SEMANTIC_ERROR (_("invalid target symbol for procfs probe, $value expected"),
435 e
->assert_no_components("procfs");
437 bool lvalue
= is_active_lvalue(e
);
438 if (write_probe
&& lvalue
)
439 throw SEMANTIC_ERROR(_("procfs $value variable is read-only in a procfs write probe"), e
->tok
);
440 else if (! write_probe
&& ! lvalue
)
441 throw SEMANTIC_ERROR(_("procfs $value variable cannot be read in a procfs read probe"), e
->tok
);
444 throw SEMANTIC_ERROR(_("cannot take address of procfs variable"), e
->tok
);
446 // Remember that we've seen a target variable.
447 target_symbol_seen
= true;
449 // Synthesize a function.
450 functiondecl
*fdecl
= new functiondecl
;
451 fdecl
->synthetic
= true;
453 embeddedcode
*ec
= new embeddedcode
;
457 string locvalue
= "CONTEXT->ips.procfs_data";
461 fname
= "_procfs_value_get";
462 ec
->code
= string(" struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue
+ string("); /* pure */\n")
464 + string(" _stp_copy_from_user(STAP_RETVALUE, data->buffer, data->count);\n")
465 + string(" STAP_RETVALUE[data->count] = '\\0';\n");
471 fname
= "_procfs_value_set";
472 ec
->code
= string("struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue
+ string(");\n")
473 + string(" strlcpy(data->buffer, STAP_ARG_value, data->bufsize);\n")
474 + string(" data->count = strlen(data->buffer);\n");
476 else if (*op
== ".=")
478 fname
= "_procfs_value_append";
479 ec
->code
= string("struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue
+ string(");\n")
480 + string(" strlcat(data->buffer, STAP_ARG_value, data->bufsize);\n")
481 + string(" data->count = strlen(data->buffer);\n");
485 throw SEMANTIC_ERROR (_("Only the following assign operators are"
486 " implemented on procfs read target variables:"
487 " '=', '.='"), e
->tok
);
490 fname
+= lex_cast(++tick
);
494 fdecl
->type
= pe_string
;
498 // Modify the fdecl so it carries a single pe_string formal
499 // argument called "value".
501 vardecl
*v
= new vardecl
;
505 fdecl
->formal_args
.push_back(v
);
509 // Synthesize a functioncall.
510 functioncall
* n
= new functioncall
;
516 // Provide the functioncall to our parent, so that it can be
517 // used to substitute for the assignment node immediately above
519 assert(!target_symbol_setter_functioncalls
.empty());
520 *(target_symbol_setter_functioncalls
.top()) = n
;
525 catch (const semantic_error
&er
)
533 struct procfs_builder
: public derived_probe_builder
536 virtual void build(systemtap_session
& sess
,
538 probe_point
* location
,
539 literal_map_t
const & parameters
,
540 vector
<derived_probe
*> & finished_results
);
545 procfs_builder::build(systemtap_session
& sess
,
547 probe_point
* location
,
548 literal_map_t
const & parameters
,
549 vector
<derived_probe
*> & finished_results
)
552 bool has_procfs
= get_param(parameters
, TOK_PROCFS
, path
);
553 bool has_read
= (parameters
.find(TOK_READ
) != parameters
.end());
554 bool has_write
= (parameters
.find(TOK_WRITE
) != parameters
.end());
555 bool has_umask
= (parameters
.find(TOK_UMASK
) != parameters
.end());
556 int64_t maxsize_val
= 0;
559 get_param(parameters
, TOK_UMASK
, umask_val
);
569 // Validate '.maxsize(NNN)', if it exists.
570 if (get_param(parameters
, TOK_MAXSIZE
, maxsize_val
))
572 if (maxsize_val
<= 0)
573 throw SEMANTIC_ERROR (_("maxsize must be greater than 0"));
576 // If no procfs path, default to "command". The runtime will do
577 // this for us, but if we don't do it here, we'll think the
578 // following 2 probes are attached to different paths:
580 // probe procfs("command").read {}"
581 // probe procfs.write {}
585 // If we have a path, we need to validate it.
588 string::size_type start_pos
, end_pos
;
591 while ((end_pos
= path
.find('/', start_pos
)) != string::npos
)
593 // Make sure it doesn't start with '/'.
595 throw SEMANTIC_ERROR (_("procfs path cannot start with a '/'"),
596 location
->components
.front()->tok
);
598 component
= path
.substr(start_pos
, end_pos
- start_pos
);
599 // Make sure it isn't empty.
600 if (component
.size() == 0)
601 throw SEMANTIC_ERROR (_("procfs path component cannot be empty"),
602 location
->components
.front()->tok
);
603 // Make sure it isn't relative.
604 else if (component
== "." || component
== "..")
605 throw SEMANTIC_ERROR (_("procfs path cannot be relative (and contain '.' or '..')"), location
->components
.front()->tok
);
607 start_pos
= end_pos
+ 1;
609 component
= path
.substr(start_pos
);
610 // Make sure it doesn't end with '/'.
611 if (component
.size() == 0)
612 throw SEMANTIC_ERROR (_("procfs path cannot end with a '/'"), location
->components
.front()->tok
);
613 // Make sure it isn't relative.
614 else if (component
== "." || component
== "..")
615 throw SEMANTIC_ERROR (_("procfs path cannot be relative (and contain '.' or '..')"), location
->components
.front()->tok
);
618 if (!(has_read
^ has_write
))
619 throw SEMANTIC_ERROR (_("need read/write component"), location
->components
.front()->tok
);
621 finished_results
.push_back(new procfs_derived_probe(sess
, base
, location
,
623 maxsize_val
, umask_val
));
628 register_tapset_procfs(systemtap_session
& s
)
630 match_node
* root
= s
.pattern_root
;
631 derived_probe_builder
*builder
= new procfs_builder();
633 root
->bind(TOK_PROCFS
)->bind(TOK_READ
)->bind(builder
);
634 root
->bind(TOK_PROCFS
)->bind_num(TOK_UMASK
)->bind(TOK_READ
)->bind(builder
);
635 root
->bind(TOK_PROCFS
)->bind(TOK_READ
)->bind_num(TOK_MAXSIZE
)->bind(builder
);
636 root
->bind(TOK_PROCFS
)->bind_num(TOK_UMASK
)->bind(TOK_READ
)->bind_num(TOK_MAXSIZE
)->bind(builder
);
637 root
->bind_str(TOK_PROCFS
)->bind(TOK_READ
)->bind(builder
);
638 root
->bind_str(TOK_PROCFS
)->bind_num(TOK_UMASK
)->bind(TOK_READ
)->bind(builder
);
639 root
->bind_str(TOK_PROCFS
)->bind(TOK_READ
)->bind_num(TOK_MAXSIZE
)->bind(builder
);
640 root
->bind_str(TOK_PROCFS
)->bind_num(TOK_UMASK
)->bind(TOK_READ
)->bind_num(TOK_MAXSIZE
)->bind(builder
);
642 root
->bind(TOK_PROCFS
)->bind(TOK_WRITE
)->bind(builder
);
643 root
->bind(TOK_PROCFS
)->bind_num(TOK_UMASK
)->bind(TOK_WRITE
)->bind(builder
);
644 root
->bind_str(TOK_PROCFS
)->bind(TOK_WRITE
)->bind(builder
);
645 root
->bind_str(TOK_PROCFS
)->bind_num(TOK_UMASK
)->bind(TOK_WRITE
)->bind(builder
);
650 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */