Branch data Line data Source code
1 : : // -*- C++ -*-
2 : : // Copyright (C) 2005-2011 Red Hat Inc.
3 : : //
4 : : // This file is part of systemtap, and is free software. You can
5 : : // redistribute it and/or modify it under the terms of the GNU General
6 : : // Public License (GPL); either version 2, or (at your option) any
7 : : // later version.
8 : :
9 : : #ifndef ELABORATE_H
10 : : #define ELABORATE_H
11 : :
12 : : #include "staptree.h"
13 : : #include "parse.h"
14 : : #include <string>
15 : : #include <vector>
16 : : //#include <iostream>
17 : : #include <iosfwd>
18 : : #include <sstream>
19 : : #include <map>
20 : : #include <list>
21 : :
22 : : extern "C" {
23 : : #include <elfutils/libdw.h>
24 : : }
25 : :
26 : : #include "privilege.h"
27 : :
28 : : struct recursive_expansion_error : public semantic_error
29 : : {
30 [ - + ]: 5 : ~recursive_expansion_error () throw () {}
31 : 5 : recursive_expansion_error (const std::string& msg, const token* t1=0):
32 : 5 : semantic_error (msg, t1) {}
33 : :
34 : : recursive_expansion_error (const std::string& msg, const token* t1,
35 : : const token* t2):
36 : : semantic_error (msg, t1, t2) {}
37 : : };
38 : :
39 : : // ------------------------------------------------------------------------
40 : :
41 : : struct derived_probe;
42 : : class match_node;
43 : :
44 [ - + ]: 1352 : struct symresolution_info: public traversing_visitor
45 : : {
46 : : protected:
47 : : systemtap_session& session;
48 : :
49 : : public:
50 : : functiondecl* current_function;
51 : : derived_probe* current_probe;
52 : : symresolution_info (systemtap_session& s);
53 : :
54 : : vardecl* find_var (const std::string& name, int arity, const token *tok);
55 : : functiondecl* find_function (const std::string& name, unsigned arity);
56 : :
57 : : void visit_block (block *s);
58 : : void visit_symbol (symbol* e);
59 : : void visit_foreach_loop (foreach_loop* e);
60 : : void visit_arrayindex (arrayindex* e);
61 : : void visit_functioncall (functioncall* e);
62 : : void visit_delete_statement (delete_statement* s);
63 : : };
64 : :
65 : :
66 [ + - ][ + - ]: 1240 : struct typeresolution_info: public visitor
[ - + ]
67 : : {
68 : : typeresolution_info (systemtap_session& s);
69 : : systemtap_session& session;
70 : : unsigned num_newly_resolved;
71 : : unsigned num_still_unresolved;
72 : : bool assert_resolvability;
73 : : functiondecl* current_function;
74 : : derived_probe* current_probe;
75 : : std::vector <const token*> resolved_toks; // account for type mis-
76 : : std::vector <const token*> printed_toks; // matches (BZ 9719)
77 : :
78 : : void check_arg_type (exp_type wanted, expression* arg);
79 : : void check_local (vardecl* v);
80 : : void mismatch (const token* tok, exp_type t1, exp_type t2);
81 : : void unresolved (const token* tok);
82 : : void resolved (const token* tok, exp_type t);
83 : : void invalid (const token* tok, exp_type t);
84 : :
85 : : exp_type t; // implicit parameter for nested visit call; may clobber
86 : : // Upon entry to one of the visit_* calls, the incoming
87 : : // `t' value is the type inferred for that node from
88 : : // context. It may match or conflict with the node's
89 : : // preexisting type, or it may be unknown.
90 : :
91 : : void visit_block (block* s);
92 : : void visit_try_block (try_block* s);
93 : : void visit_embeddedcode (embeddedcode* s);
94 : : void visit_null_statement (null_statement* s);
95 : : void visit_expr_statement (expr_statement* s);
96 : : void visit_if_statement (if_statement* s);
97 : : void visit_for_loop (for_loop* s);
98 : : void visit_foreach_loop (foreach_loop* s);
99 : : void visit_return_statement (return_statement* s);
100 : : void visit_delete_statement (delete_statement* s);
101 : : void visit_next_statement (next_statement* s);
102 : : void visit_break_statement (break_statement* s);
103 : : void visit_continue_statement (continue_statement* s);
104 : : void visit_literal_string (literal_string* e);
105 : : void visit_literal_number (literal_number* e);
106 : : void visit_embedded_expr (embedded_expr* e);
107 : : void visit_binary_expression (binary_expression* e);
108 : : void visit_unary_expression (unary_expression* e);
109 : : void visit_pre_crement (pre_crement* e);
110 : : void visit_post_crement (post_crement* e);
111 : : void visit_logical_or_expr (logical_or_expr* e);
112 : : void visit_logical_and_expr (logical_and_expr* e);
113 : : void visit_array_in (array_in* e);
114 : : void visit_regex_query (regex_query* e);
115 : : void visit_comparison (comparison* e);
116 : : void visit_concatenation (concatenation* e);
117 : : void visit_ternary_expression (ternary_expression* e);
118 : : void visit_assignment (assignment* e);
119 : : void visit_symbol (symbol* e);
120 : : void visit_target_symbol (target_symbol* e);
121 : : void visit_arrayindex (arrayindex* e);
122 : : void visit_functioncall (functioncall* e);
123 : : void visit_print_format (print_format* e);
124 : : void visit_stat_op (stat_op* e);
125 : : void visit_hist_op (hist_op* e);
126 : : void visit_cast_op (cast_op* e);
127 : : void visit_defined_op (defined_op* e);
128 : : void visit_entry_op (entry_op* e);
129 : : void visit_perf_op (perf_op* e);
130 : : };
131 : :
132 : :
133 : : // ------------------------------------------------------------------------
134 : :
135 : :
136 : : // A derived_probe is a probe that has been elaborated by
137 : : // binding to a matching provider. The locations std::vector
138 : : // may be smaller or larger than the base probe, since a
139 : : // provider may transform it.
140 : :
141 : : class translator_output;
142 : : struct derived_probe_group;
143 : :
144 : : struct derived_probe: public probe
145 : : {
146 : : derived_probe (probe* b, probe_point* l, bool rewrite_loc=false);
147 : : probe* base; // the original parsed probe
148 : : probe_point* base_pp; // the probe_point that led to this derivation
149 : 0 : virtual const probe* basest () const { return base->basest(); }
150 [ + + ]: 54400 : virtual const probe* almost_basest () const { return base->almost_basest() ?: this; }
151 [ + - ][ - + ]: 9 : virtual ~derived_probe () {}
152 : : virtual void join_group (systemtap_session& s) = 0;
153 : : virtual probe_point* sole_location () const;
154 : : virtual probe_point* script_location () const;
155 : : virtual void printsig (std::ostream &o) const;
156 : : // return arguments of probe if there
157 : 0 : virtual void getargs (std::list<std::string> &) const {}
158 : : void printsig_nested (std::ostream &o) const;
159 : : virtual void collect_derivation_chain (std::vector<probe*> &probes_list);
160 : : virtual void collect_derivation_pp_chain (std::vector<probe_point*> &pp_list);
161 : : std::string derived_locations ();
162 : :
163 : 28622 : virtual void print_dupe_stamp(std::ostream&) {}
164 : : // To aid duplication elimination, print a stamp which uniquely identifies
165 : : // the code that will be added to the probe body. (Doesn't need to be the
166 : : // actual code...)
167 : :
168 : 8570 : virtual void initialize_probe_context_vars (translator_output*) {}
169 : : // From within unparser::emit_probe, initialized any extra variables
170 : : // in this probe's context locals.
171 : :
172 : 2395 : virtual void emit_probe_local_init (systemtap_session& s, translator_output*) {}
173 : : // From within unparser::emit_probe, emit any extra processing block
174 : : // for this probe.
175 : :
176 : : virtual void emit_privilege_assertion (translator_output*);
177 : : // From within unparser::emit_probe, emit any unprivileged mode
178 : : // checking for this probe.
179 : :
180 : : public:
181 : : static void emit_common_header (translator_output* o);
182 : : // from c_unparser::emit_common_header
183 : : // XXX: probably can move this stuff to a probe_group::emit_module_decls
184 : :
185 : : static void emit_process_owner_assertion (translator_output*);
186 : : // From within unparser::emit_probe, emit a check that the current
187 : : // process belongs to the user.
188 : :
189 : : static void print_dupe_stamp_unprivileged(std::ostream& o);
190 : : static void print_dupe_stamp_unprivileged_process_owner(std::ostream& o);
191 : :
192 : 69207 : virtual bool needs_global_locks () { return true; }
193 : : // by default, probes need locks around global variables
194 : :
195 : : // Location of semaphores to activate sdt probes
196 : : Dwarf_Addr sdt_semaphore_addr;
197 : :
198 : : // perf.counter probes that this probe references
199 : : std::set<derived_probe*> perf_counter_refs;
200 : :
201 : : // index into session.probes[], set and used during translation
202 : : unsigned session_index;
203 : : };
204 : :
205 : : // ------------------------------------------------------------------------
206 : :
207 : : struct unparser;
208 : :
209 : : // Various derived classes derived_probe_group manage the
210 : : // registration/invocation/unregistration of sibling probes.
211 : 1602 : struct derived_probe_group
212 : : {
213 [ # # ]: 0 : virtual ~derived_probe_group () {}
214 : :
215 : : virtual void emit_module_decls (systemtap_session& s) = 0;
216 : : // The _decls-generated code may assume that declarations such as
217 : : // the context, embedded-C code, function and probe handler bodies
218 : : // are all already generated. That is, _decls is called near the
219 : : // end of the code generation process. It should minimize the
220 : : // number of separate variables (and to a lesser extent, their
221 : : // size).
222 : :
223 : : virtual void emit_module_init (systemtap_session& s) = 0;
224 : : // The _init-generated code may assume that it is called only once.
225 : : // If that code fails at run time, it must set rc=1 and roll back
226 : : // any partial initializations, for its _exit friend will NOT be
227 : : // invoked. The generated code may use pre-declared "int i, j;"
228 : : // and set "const char* probe_point;".
229 : :
230 : 881 : virtual void emit_module_post_init (systemtap_session& s) {}
231 : : // The emit_module_post_init() code is called once session_state is
232 : : // set to running.
233 : :
234 : 705 : virtual void emit_module_refresh (systemtap_session& s) {}
235 : : // The _refresh-generated code may be called multiple times during
236 : : // a session run, bracketed by _init and _exit calls.
237 : : // Upon failure, it must set enough state so that
238 : : // a subsequent _exit call will clean up everything.
239 : : // The generated code may use pre-declared "int i, j;".
240 : :
241 : : virtual void emit_module_exit (systemtap_session& s) = 0;
242 : : // The _exit-generated code may assume that it is executed exactly
243 : : // zero times (if the _init-generated code failed) or once. (_exit
244 : : // itself may be called a few times, to generate the code in a few
245 : : // different places in the probe module.)
246 : : // The generated code may use pre-declared "int i, j;".
247 : : };
248 : :
249 : :
250 : : // ------------------------------------------------------------------------
251 : :
252 : : typedef std::map<std::string, literal*> literal_map_t;
253 : :
254 : 2493500 : struct derived_probe_builder
255 : : {
256 : : virtual void build(systemtap_session & sess,
257 : : probe* base,
258 : : probe_point* location,
259 : : literal_map_t const & parameters,
260 : : std::vector<derived_probe*> & finished_results) = 0;
261 : : virtual void build_with_suffix(systemtap_session & sess,
262 : : probe * use,
263 : : probe_point * location,
264 : : std::map<std::string, literal *>
265 : : const & parameters,
266 : : std::vector<derived_probe *>
267 : : & finished_results,
268 : : std::vector<probe_point::component *>
269 : : const & suffix);
270 [ # # ]: 0 : virtual ~derived_probe_builder() {}
271 : 2549528 : virtual void build_no_more (systemtap_session &) {}
272 : 0 : virtual bool is_alias () const { return false; }
273 : :
274 : : static bool has_null_param (literal_map_t const & parameters,
275 : : const std::string& key);
276 : : static bool get_param (literal_map_t const & parameters,
277 : : const std::string& key, std::string& value);
278 : : static bool get_param (literal_map_t const & parameters,
279 : : const std::string& key, int64_t& value);
280 : : };
281 : :
282 : :
283 : : struct
284 : 27296270 : match_key
285 : : {
286 : : std::string name;
287 : : bool have_parameter;
288 : : exp_type parameter_type;
289 : :
290 : : match_key(std::string const & n);
291 : : match_key(probe_point::component const & c);
292 : :
293 : : match_key & with_number();
294 : : match_key & with_string();
295 : : std::string str() const;
296 : : bool operator<(match_key const & other) const;
297 : : bool globmatch(match_key const & other) const;
298 : : };
299 : :
300 : :
301 : : class
302 [ + - ]: 2413 : match_node
303 : : {
304 : : typedef std::map<match_key, match_node*> sub_map_t;
305 : : typedef std::map<match_key, match_node*>::iterator sub_map_iterator_t;
306 : : sub_map_t sub;
307 : : std::vector<derived_probe_builder*> ends;
308 : :
309 : : public:
310 : : match_node();
311 : :
312 : : void find_and_build (systemtap_session& s,
313 : : probe* p, probe_point *loc, unsigned pos,
314 : : std::vector<derived_probe *>& results);
315 : : void try_suffix_expansion (systemtap_session& s,
316 : : probe *p, probe_point *loc, unsigned pos,
317 : : std::vector<derived_probe *>& results);
318 : : void build_no_more (systemtap_session &s);
319 : : void dump (systemtap_session &s, const std::string &name = "");
320 : :
321 : : match_node* bind(match_key const & k);
322 : : match_node* bind(std::string const & k);
323 : : match_node* bind_str(std::string const & k);
324 : : match_node* bind_num(std::string const & k);
325 : : match_node* bind_privilege(privilege_t p = privilege_t (pr_stapdev | pr_stapsys));
326 : : void bind(derived_probe_builder* e);
327 : :
328 : : private:
329 : : privilege_t privilege;
330 : : };
331 : :
332 : : // ------------------------------------------------------------------------
333 : :
334 : : struct
335 [ # # ]: 0 : alias_expansion_builder
336 : : : public derived_probe_builder
337 : : {
338 : : probe_alias * alias;
339 : :
340 : 2453306 : alias_expansion_builder(probe_alias * a)
341 : 2453306 : : alias(a)
342 : 2453306 : {}
343 : :
344 : : virtual void build(systemtap_session & sess,
345 : : probe * use,
346 : : probe_point * location,
347 : : std::map<std::string, literal *> const &,
348 : : std::vector<derived_probe *> & finished_results);
349 : : virtual void build_with_suffix(systemtap_session & sess,
350 : : probe * use,
351 : : probe_point * location,
352 : : std::map<std::string, literal *>
353 : : const &,
354 : : std::vector<derived_probe *>
355 : : & finished_results,
356 : : std::vector<probe_point::component *>
357 : : const & suffix);
358 : 0 : virtual bool is_alias () const { return true; }
359 : :
360 : : bool checkForRecursiveExpansion (probe *use);
361 : : };
362 : :
363 : : // ------------------------------------------------------------------------
364 : :
365 : : /* struct systemtap_session moved to session.h */
366 : :
367 : : int semantic_pass (systemtap_session& s);
368 : : void derive_probes (systemtap_session& s,
369 : : probe *p, std::vector<derived_probe*>& dps,
370 : : bool optional = false, bool rethrow_errors = false);
371 : :
372 : : // A helper we use here and in translate, for pulling symbols out of lvalue
373 : : // expressions.
374 : : symbol * get_symbol_within_expression (expression *e);
375 : :
376 : :
377 : : struct unparser;
378 : :
379 : :
380 : : #endif // ELABORATE_H
381 : :
382 : : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
|