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");
31 // ------------------------------------------------------------------------
32 // procfs file derived probes
33 // ------------------------------------------------------------------------
36 struct procfs_derived_probe
: public derived_probe
40 bool target_symbol_seen
;
43 procfs_derived_probe (systemtap_session
&, probe
* p
, probe_point
* l
, string ps
, bool w
, int64_t m
);
44 void join_group (systemtap_session
& s
);
48 struct procfs_probe_set
50 procfs_derived_probe
* read_probe
;
51 procfs_derived_probe
* write_probe
;
53 procfs_probe_set () : read_probe (NULL
), write_probe (NULL
) {}
57 struct procfs_derived_probe_group
: public generic_dpg
<procfs_derived_probe
>
60 map
<string
, procfs_probe_set
*> probes_by_path
;
61 typedef map
<string
, procfs_probe_set
*>::iterator p_b_p_iterator
;
63 bool has_write_probes
;
66 procfs_derived_probe_group () :
67 has_read_probes(false), has_write_probes(false) {}
69 void enroll (procfs_derived_probe
* probe
);
70 void emit_module_decls (systemtap_session
& s
);
71 void emit_module_init (systemtap_session
& s
);
72 void emit_module_exit (systemtap_session
& s
);
76 struct procfs_var_expanding_visitor
: public var_expanding_visitor
78 procfs_var_expanding_visitor(systemtap_session
& s
, const string
& pn
,
79 string path
, bool write_probe
);
81 systemtap_session
& sess
;
85 bool target_symbol_seen
;
87 void visit_target_symbol (target_symbol
* e
);
91 procfs_derived_probe::procfs_derived_probe (systemtap_session
&s
, probe
* p
,
92 probe_point
* l
, string ps
, bool w
,
94 derived_probe(p
, l
), path(ps
), write(w
), target_symbol_seen(false),
97 // Expand local variables in the probe body
98 procfs_var_expanding_visitor
v (s
, name
, path
, write
);
99 v
.replace (this->body
);
100 target_symbol_seen
= v
.target_symbol_seen
;
105 procfs_derived_probe::join_group (systemtap_session
& s
)
107 if (! s
.procfs_derived_probes
)
109 s
.procfs_derived_probes
= new procfs_derived_probe_group ();
111 // Make sure 'struct _stp_procfs_data' is defined early.
112 embeddedcode
*ec
= new embeddedcode
;
114 ec
->code
= string("struct _stp_procfs_data {\n")
115 + string(" char *buffer;\n")
116 + string(" size_t bufsize;\n")
117 + string(" size_t count;\n")
119 + string("#ifndef STP_PROCFS_BUFSIZE\n")
120 + string("#define STP_PROCFS_BUFSIZE MAXSTRINGLEN\n")
121 + string("#endif\n");
122 s
.embeds
.push_back(ec
);
124 s
.procfs_derived_probes
->enroll (this);
129 procfs_derived_probe_group::enroll (procfs_derived_probe
* p
)
131 procfs_probe_set
*pset
;
133 if (probes_by_path
.count(p
->path
) == 0)
135 pset
= new procfs_probe_set
;
136 probes_by_path
[p
->path
] = pset
;
140 pset
= probes_by_path
[p
->path
];
142 // You can only specify 1 read and 1 write probe.
143 if (p
->write
&& pset
->write_probe
!= NULL
)
144 throw semantic_error("only one write procfs probe can exist for procfs path \"" + p
->path
+ "\"");
145 else if (! p
->write
&& pset
->read_probe
!= NULL
)
146 throw semantic_error("only one read procfs probe can exist for procfs path \"" + p
->path
+ "\"");
148 // XXX: multiple writes should be acceptable
153 pset
->write_probe
= p
;
154 has_write_probes
= true;
158 pset
->read_probe
= p
;
159 has_read_probes
= true;
165 procfs_derived_probe_group::emit_module_decls (systemtap_session
& s
)
167 if (probes_by_path
.empty())
170 s
.op
->newline() << "/* ---- procfs probes ---- */";
171 s
.op
->newline() << "#include \"procfs.c\"";
172 s
.op
->newline() << "#include \"procfs-probes.c\"";
174 // Emit the procfs probe buffer structure
175 s
.op
->newline() << "static struct stap_procfs_probe_buffer {";
177 for (p_b_p_iterator it
= probes_by_path
.begin(); it
!= probes_by_path
.end();
180 procfs_probe_set
*pset
= it
->second
;
182 if (pset
->read_probe
!= NULL
)
184 if (pset
->read_probe
->maxsize_val
== 0)
186 s
.op
->newline() << "char " << pset
->read_probe
->name
187 << "[STP_PROCFS_BUFSIZE];";
191 s
.op
->newline() << "char " << pset
->read_probe
->name
192 << "[" << pset
->read_probe
->maxsize_val
198 s
.op
->newline() << "char " << pset
->write_probe
->name
199 << "[MAXSTRINGLEN];";
202 s
.op
->newline(-1) << "} stap_procfs_probe_buffers;";
204 // Emit the procfs probe data list
205 s
.op
->newline() << "static struct stap_procfs_probe stap_procfs_probes[] = {";
208 for (p_b_p_iterator it
= probes_by_path
.begin(); it
!= probes_by_path
.end();
211 procfs_probe_set
*pset
= it
->second
;
213 s
.op
->newline() << "{";
214 s
.op
->line() << " .path=" << lex_cast_qstring (it
->first
) << ",";
216 if (pset
->read_probe
!= NULL
)
218 s
.op
->line() << " .read_pp="
219 << lex_cast_qstring (*pset
->read_probe
->sole_location())
221 s
.op
->line() << " .read_ph=&" << pset
->read_probe
->name
<< ",";
225 s
.op
->line() << " .read_pp=NULL,";
226 s
.op
->line() << " .read_ph=NULL,";
229 if (pset
->write_probe
!= NULL
)
231 s
.op
->line() << " .write_pp="
232 << lex_cast_qstring (*pset
->write_probe
->sole_location())
234 s
.op
->line() << " .write_ph=&" << pset
->write_probe
->name
<< ",";
238 s
.op
->line() << " .write_pp=NULL,";
239 s
.op
->line() << " .write_ph=NULL,";
242 if (pset
->read_probe
!= NULL
)
244 s
.op
->line() << " .buffer=stap_procfs_probe_buffers."
245 << pset
->read_probe
->name
<< ",";
246 if (pset
->read_probe
->maxsize_val
== 0)
247 s
.op
->line() << " .bufsize=STP_PROCFS_BUFSIZE,";
249 s
.op
->line() << " .bufsize="
250 << pset
->read_probe
->maxsize_val
<< ",";
254 s
.op
->line() << " .buffer=stap_procfs_probe_buffers."
255 << pset
->write_probe
->name
<< ",";
256 s
.op
->line() << " .bufsize=MAXSTRINGLEN,";
259 s
.op
->line() << " },";
261 s
.op
->newline(-1) << "};";
263 // Output routine to fill in the buffer with our data. Note that we
264 // need to do this even in the case where we have no read probes,
265 // but we can skip most of it then.
268 s
.op
->newline() << "static int _stp_proc_fill_read_buffer(struct stap_procfs_probe *spp) {";
272 s
.op
->newline() << "struct _stp_procfs_data pdata;";
274 common_probe_entryfn_prologue (s
.op
, "STAP_SESSION_RUNNING", "spp->read_pp");
276 s
.op
->newline() << "pdata.buffer = spp->buffer;";
277 s
.op
->newline() << "pdata.bufsize = spp->bufsize;";
278 s
.op
->newline() << "if (c->data == NULL)";
279 s
.op
->newline(1) << "c->data = &pdata;";
280 s
.op
->newline(-1) << "else {";
282 s
.op
->newline(1) << "if (unlikely (atomic_inc_return (& skipped_count) > MAXSKIPPED)) {";
283 s
.op
->newline(1) << "atomic_set (& session_state, STAP_SESSION_ERROR);";
284 s
.op
->newline() << "_stp_exit ();";
285 s
.op
->newline(-1) << "}";
286 s
.op
->newline() << "atomic_dec (& c->busy);";
287 s
.op
->newline() << "goto probe_epilogue;";
288 s
.op
->newline(-1) << "}";
290 // call probe function
291 s
.op
->newline() << "(*spp->read_ph) (c);";
293 // Note that _procfs_value_set copied string data into spp->buffer
294 s
.op
->newline() << "c->data = NULL;";
295 s
.op
->newline() << "spp->needs_fill = 0;";
296 s
.op
->newline() << "spp->count = strlen(spp->buffer);";
298 common_probe_entryfn_epilogue (s
.op
);
300 s
.op
->newline() << "if (spp->needs_fill) {";
301 s
.op
->newline(1) << "spp->needs_fill = 0;";
302 s
.op
->newline() << "return -EIO;";
303 s
.op
->newline(-1) << "}";
305 s
.op
->newline() << "return 0;";
306 s
.op
->newline(-1) << "}";
308 // Output routine to read data. Note that we need to do this even
309 // in the case where we have no write probes, but we can skip most
311 s
.op
->newline() << "static int _stp_process_write_buffer(struct stap_procfs_probe *spp, const char __user *buf, size_t count) {";
313 s
.op
->newline() << "int retval = 0;";
314 if (has_write_probes
)
316 s
.op
->newline() << "struct _stp_procfs_data pdata;";
318 common_probe_entryfn_prologue (s
.op
, "STAP_SESSION_RUNNING", "spp->write_pp");
320 // We've got 2 problems here. The data count could be greater
321 // than MAXSTRINGLEN or greater than the bufsize (if the same
322 // procfs file had a size less than MAXSTRINGLEN).
323 s
.op
->newline() << "if (count >= MAXSTRINGLEN)";
324 s
.op
->newline(1) << "count = MAXSTRINGLEN - 1;";
326 s
.op
->newline() << "pdata.bufsize = spp->bufsize;";
327 s
.op
->newline() << "if (count >= pdata.bufsize)";
328 s
.op
->newline(1) << "count = pdata.bufsize - 1;";
331 s
.op
->newline() << "pdata.buffer = (char *)buf;";
332 s
.op
->newline() << "pdata.count = count;";
334 s
.op
->newline() << "if (c->data == NULL)";
335 s
.op
->newline(1) << "c->data = &pdata;";
336 s
.op
->newline(-1) << "else {";
338 s
.op
->newline(1) << "if (unlikely (atomic_inc_return (& skipped_count) > MAXSKIPPED)) {";
339 s
.op
->newline(1) << "atomic_set (& session_state, STAP_SESSION_ERROR);";
340 s
.op
->newline() << "_stp_exit ();";
341 s
.op
->newline(-1) << "}";
342 s
.op
->newline() << "atomic_dec (& c->busy);";
343 s
.op
->newline() << "goto probe_epilogue;";
344 s
.op
->newline(-1) << "}";
346 // call probe function
347 s
.op
->newline() << "(*spp->write_ph) (c);";
349 s
.op
->newline() << "c->data = NULL;";
350 s
.op
->newline() << "if (c->last_error == 0) {";
351 s
.op
->newline(1) << "retval = count;";
352 s
.op
->newline(-1) << "}";
354 common_probe_entryfn_epilogue (s
.op
);
356 s
.op
->newline() << "return retval;";
357 s
.op
->newline(-1) << "}";
362 procfs_derived_probe_group::emit_module_init (systemtap_session
& s
)
364 if (probes_by_path
.empty())
367 s
.op
->newline() << "for (i = 0; i < " << probes_by_path
.size() << "; i++) {";
368 s
.op
->newline(1) << "struct stap_procfs_probe *spp = &stap_procfs_probes[i];";
370 s
.op
->newline() << "if (spp->read_pp)";
371 s
.op
->newline(1) << "probe_point = spp->read_pp;";
372 s
.op
->newline(-1) << "else";
373 s
.op
->newline(1) << "probe_point = spp->write_pp;";
376 s
.op
->newline() << "_spp_init(spp);";
377 s
.op
->newline() << "rc = _stp_create_procfs(spp->path, i, &_stp_proc_fops);";
379 s
.op
->newline() << "if (rc) {";
380 s
.op
->newline(1) << "_stp_close_procfs();";
382 s
.op
->newline() << "for (i = 0; i < " << probes_by_path
.size() << "; i++) {";
383 s
.op
->newline(1) << "spp = &stap_procfs_probes[i];";
384 s
.op
->newline() << "_spp_shutdown(spp);";
385 s
.op
->newline(-1) << "}";
386 s
.op
->newline() << "break;";
387 s
.op
->newline(-1) << "}";
389 s
.op
->newline() << "_stp_procfs_files[i]->data = spp;";
390 s
.op
->newline(-1) << "}"; // for loop
395 procfs_derived_probe_group::emit_module_exit (systemtap_session
& s
)
397 if (probes_by_path
.empty())
400 s
.op
->newline() << "_stp_close_procfs();";
401 s
.op
->newline() << "for (i = 0; i < " << probes_by_path
.size() << "; i++) {";
402 s
.op
->newline(1) << "struct stap_procfs_probe *spp = &stap_procfs_probes[i];";
403 s
.op
->newline() << "_spp_shutdown(spp);";
404 s
.op
->newline(-1) << "}";
408 procfs_var_expanding_visitor::procfs_var_expanding_visitor (systemtap_session
& s
,
412 sess (s
), probe_name (pn
), path (path
), write_probe (write_probe
),
413 target_symbol_seen (false)
415 // procfs probes can also handle '.='.
416 valid_ops
.insert (".=");
421 procfs_var_expanding_visitor::visit_target_symbol (target_symbol
* e
)
425 assert(e
->base_name
.size() > 0 && e
->base_name
[0] == '$');
427 if (e
->base_name
!= "$value")
428 throw semantic_error ("invalid target symbol for procfs probe, $value expected",
431 e
->assert_no_components("procfs");
433 bool lvalue
= is_active_lvalue(e
);
434 if (write_probe
&& lvalue
)
435 throw semantic_error("procfs $value variable is read-only in a procfs write probe", e
->tok
);
436 else if (! write_probe
&& ! lvalue
)
437 throw semantic_error("procfs $value variable cannot be read in a procfs read probe", e
->tok
);
440 throw semantic_error("cannot take address of procfs variable", e
->tok
);
442 // Remember that we've seen a target variable.
443 target_symbol_seen
= true;
445 // Synthesize a function.
446 functiondecl
*fdecl
= new functiondecl
;
447 fdecl
->synthetic
= true;
449 embeddedcode
*ec
= new embeddedcode
;
453 string locvalue
= "CONTEXT->data";
457 fname
= "_procfs_value_get";
458 ec
->code
= string(" struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue
+ string("); /* pure */\n")
460 + string(" _stp_copy_from_user(THIS->__retvalue, data->buffer, data->count);\n")
461 + string(" THIS->__retvalue[data->count] = '\\0';\n");
467 fname
= "_procfs_value_set";
468 ec
->code
= string("struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue
+ string(");\n")
469 + string(" strlcpy(data->buffer, THIS->value, data->bufsize);\n")
470 + string(" data->count = strlen(data->buffer);\n");
472 else if (*op
== ".=")
474 fname
= "_procfs_value_append";
475 ec
->code
= string("struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue
+ string(");\n")
476 + string(" strlcat(data->buffer, THIS->value, data->bufsize);\n")
477 + string(" data->count = strlen(data->buffer);\n");
481 throw semantic_error ("Only the following assign operators are"
482 " implemented on procfs read target variables:"
483 " '=', '.='", e
->tok
);
489 fdecl
->type
= pe_string
;
493 // Modify the fdecl so it carries a single pe_string formal
494 // argument called "value".
496 vardecl
*v
= new vardecl
;
500 fdecl
->formal_args
.push_back(v
);
502 sess
.functions
[fdecl
->name
]=fdecl
;
504 // Synthesize a functioncall.
505 functioncall
* n
= new functioncall
;
508 n
->referent
= 0; // NB: must not resolve yet, to ensure inclusion in session
512 // Provide the functioncall to our parent, so that it can be
513 // used to substitute for the assignment node immediately above
515 assert(!target_symbol_setter_functioncalls
.empty());
516 *(target_symbol_setter_functioncalls
.top()) = n
;
521 catch (const semantic_error
&er
)
529 struct procfs_builder
: public derived_probe_builder
532 virtual void build(systemtap_session
& sess
,
534 probe_point
* location
,
535 literal_map_t
const & parameters
,
536 vector
<derived_probe
*> & finished_results
);
541 procfs_builder::build(systemtap_session
& sess
,
543 probe_point
* location
,
544 literal_map_t
const & parameters
,
545 vector
<derived_probe
*> & finished_results
)
548 bool has_procfs
= get_param(parameters
, TOK_PROCFS
, path
);
549 bool has_read
= (parameters
.find(TOK_READ
) != parameters
.end());
550 bool has_write
= (parameters
.find(TOK_WRITE
) != parameters
.end());
551 int64_t maxsize_val
= 0;
553 // Validate '.maxsize(NNN)', if it exists.
554 if (get_param(parameters
, TOK_MAXSIZE
, maxsize_val
))
556 if (maxsize_val
<= 0)
557 throw semantic_error ("maxsize must be greater than 0");
560 // If no procfs path, default to "command". The runtime will do
561 // this for us, but if we don't do it here, we'll think the
562 // following 2 probes are attached to different paths:
564 // probe procfs("command").read {}"
565 // probe procfs.write {}
569 // If we have a path, we need to validate it.
572 string::size_type start_pos
, end_pos
;
575 while ((end_pos
= path
.find('/', start_pos
)) != string::npos
)
577 // Make sure it doesn't start with '/'.
579 throw semantic_error ("procfs path cannot start with a '/'",
580 location
->components
.front()->tok
);
582 component
= path
.substr(start_pos
, end_pos
- start_pos
);
583 // Make sure it isn't empty.
584 if (component
.size() == 0)
585 throw semantic_error ("procfs path component cannot be empty",
586 location
->components
.front()->tok
);
587 // Make sure it isn't relative.
588 else if (component
== "." || component
== "..")
589 throw semantic_error ("procfs path cannot be relative (and contain '.' or '..')", location
->components
.front()->tok
);
591 start_pos
= end_pos
+ 1;
593 component
= path
.substr(start_pos
);
594 // Make sure it doesn't end with '/'.
595 if (component
.size() == 0)
596 throw semantic_error ("procfs path cannot end with a '/'", location
->components
.front()->tok
);
597 // Make sure it isn't relative.
598 else if (component
== "." || component
== "..")
599 throw semantic_error ("procfs path cannot be relative (and contain '.' or '..')", location
->components
.front()->tok
);
602 if (!(has_read
^ has_write
))
603 throw semantic_error ("need read/write component", location
->components
.front()->tok
);
605 finished_results
.push_back(new procfs_derived_probe(sess
, base
, location
,
612 register_tapset_procfs(systemtap_session
& s
)
614 match_node
* root
= s
.pattern_root
;
615 derived_probe_builder
*builder
= new procfs_builder();
617 root
->bind(TOK_PROCFS
)->bind(TOK_READ
)->bind(builder
);
618 root
->bind(TOK_PROCFS
)->bind(TOK_READ
)->bind_num(TOK_MAXSIZE
)->bind(builder
);
619 root
->bind_str(TOK_PROCFS
)->bind(TOK_READ
)->bind(builder
);
620 root
->bind_str(TOK_PROCFS
)->bind(TOK_READ
)->bind_num(TOK_MAXSIZE
)->bind(builder
);
622 root
->bind(TOK_PROCFS
)->bind(TOK_WRITE
)->bind(builder
);
623 root
->bind_str(TOK_PROCFS
)->bind(TOK_WRITE
)->bind(builder
);
628 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */