Branch data Line data Source code
1 : : // translation pass
2 : : // Copyright (C) 2005-2013 Red Hat Inc.
3 : : // Copyright (C) 2005-2008 Intel Corporation.
4 : : // Copyright (C) 2010 Novell Corporation.
5 : : //
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
9 : : // later version.
10 : :
11 : : #include "config.h"
12 : : #include "staptree.h"
13 : : #include "elaborate.h"
14 : : #include "translate.h"
15 : : #include "session.h"
16 : : #include "tapsets.h"
17 : : #include "util.h"
18 : : #include "dwarf_wrappers.h"
19 : : #include "setupdwfl.h"
20 : : #include "task_finder.h"
21 : : #include "runtime/k_syms.h"
22 : : #include "dwflpp.h"
23 : :
24 : : #include "re2c-migrate/stapregex.h"
25 : :
26 : : #include <cstdlib>
27 : : #include <iostream>
28 : : #include <set>
29 : : #include <sstream>
30 : : #include <string>
31 : : #include <cassert>
32 : : #include <cstring>
33 : : #include <cerrno>
34 : :
35 : : extern "C" {
36 : : #include <dwarf.h>
37 : : #include <elfutils/libdwfl.h>
38 : : #include <elfutils/libdw.h>
39 : : #include <ftw.h>
40 : : #define __STDC_FORMAT_MACROS
41 : : #include <inttypes.h>
42 : : }
43 : :
44 : : // Max unwind table size (debug or eh) per module. Somewhat arbitrary
45 : : // limit (a bit more than twice the .debug_frame size of my local
46 : : // vmlinux for 2.6.31.4-83.fc12.x86_64).
47 : : // A larger value was recently found in a libxul.so build.
48 : : // ... and yet again in libxul.so, PR15162
49 : : #define MAX_UNWIND_TABLE_SIZE (16 * 1024 * 1024)
50 : :
51 : : #define STAP_T_01 _("\"Array overflow, check ")
52 : : #define STAP_T_02 _("\"MAXNESTING exceeded\";")
53 : : #define STAP_T_03 _("\"division by 0\";")
54 : : #define STAP_T_04 _("\"MAXACTION exceeded\";")
55 : : #define STAP_T_05 _("\"aggregation overflow in ")
56 : : #define STAP_T_06 _("\"empty aggregate\";")
57 : : #define STAP_T_07 _("\"histogram index out of range\";")
58 : : using namespace std;
59 : :
60 : : class var;
61 : : struct tmpvar;
62 : : struct aggvar;
63 : : struct mapvar;
64 : : class itervar;
65 : :
66 : : struct c_unparser: public unparser, public visitor
67 : : {
68 : : systemtap_session* session;
69 : : translator_output* o;
70 : :
71 : : derived_probe* current_probe;
72 : : functiondecl* current_function;
73 : : unsigned tmpvar_counter;
74 : : unsigned label_counter;
75 : : unsigned action_counter;
76 : :
77 : : varuse_collecting_visitor vcv_needs_global_locks;
78 : :
79 : : map<string, string> probe_contents;
80 : :
81 : : map<pair<bool, string>, string> compiled_printfs;
82 : :
83 : 645 : c_unparser (systemtap_session* ss):
84 : : session (ss), o (ss->op), current_probe(0), current_function (0),
85 : : tmpvar_counter (0), label_counter (0), action_counter(0),
86 [ + - ][ + - ]: 645 : vcv_needs_global_locks (*ss) {}
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
87 [ + - ][ + - ]: 645 : ~c_unparser () {}
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ]
88 : :
89 : : void emit_map_type_instantiations ();
90 : : void emit_common_header ();
91 : : void emit_global (vardecl* v);
92 : : void emit_global_init (vardecl* v);
93 : : void emit_global_param (vardecl* v);
94 : : void emit_functionsig (functiondecl* v);
95 : : void emit_module_init ();
96 : : void emit_module_refresh ();
97 : : void emit_module_exit ();
98 : : void emit_function (functiondecl* v);
99 : : void emit_lock_decls (const varuse_collecting_visitor& v);
100 : : void emit_locks (const varuse_collecting_visitor& v);
101 : : void emit_probe (derived_probe* v);
102 : : void emit_unlocks (const varuse_collecting_visitor& v);
103 : :
104 : : void emit_compiled_printfs ();
105 : : void emit_compiled_printf_locals ();
106 : : void declare_compiled_printf (bool print_to_stream, const string& format);
107 : : const string& get_compiled_printf (bool print_to_stream, const string& format);
108 : :
109 : : // for use by stats (pmap) foreach
110 : : set<string> aggregations_active;
111 : :
112 : : // values immediately available in foreach_loop iterations
113 : : map<string, string> foreach_loop_values;
114 : : void visit_foreach_loop_value (visitor* vis, foreach_loop* s,
115 : : const string& value="");
116 : : bool get_foreach_loop_value (arrayindex* ai, string& value);
117 : :
118 : : // for use by looping constructs
119 : : vector<string> loop_break_labels;
120 : : vector<string> loop_continue_labels;
121 : :
122 : : string c_typename (exp_type e);
123 : : virtual string c_localname (const string& e, bool mangle_oldstyle = false);
124 : : virtual string c_globalname (const string &e);
125 : : virtual string c_funcname (const string &e);
126 : : string c_expression (expression* e);
127 : :
128 : : string c_arg_define (const string& e);
129 : : string c_arg_undef (const string& e);
130 : :
131 : : void c_assign (var& lvalue, const string& rvalue, const token* tok);
132 : : void c_assign (const string& lvalue, expression* rvalue, const string& msg);
133 : : void c_assign (const string& lvalue, const string& rvalue, exp_type type,
134 : : const string& msg, const token* tok);
135 : :
136 : : void c_declare(exp_type ty, const string &ident);
137 : : void c_declare_static(exp_type ty, const string &ident);
138 : :
139 : : void c_strcat (const string& lvalue, const string& rvalue);
140 : : void c_strcat (const string& lvalue, expression* rvalue);
141 : :
142 : : void c_strcpy (const string& lvalue, const string& rvalue);
143 : : void c_strcpy (const string& lvalue, expression* rvalue);
144 : :
145 : : bool is_local (vardecl const* r, token const* tok);
146 : :
147 : : tmpvar gensym(exp_type ty);
148 : : aggvar gensym_aggregate();
149 : :
150 : : var getvar(vardecl* v, token const* tok = NULL);
151 : : itervar getiter(symbol* s);
152 : : mapvar getmap(vardecl* v, token const* tok = NULL);
153 : :
154 : : void load_map_indices(arrayindex* e,
155 : : vector<tmpvar> & idx);
156 : :
157 : : var* load_aggregate (expression *e, aggvar & agg);
158 : : string histogram_index_check(var & vase, tmpvar & idx) const;
159 : :
160 : : void collect_map_index_types(vector<vardecl* > const & vars,
161 : : set< pair<vector<exp_type>, exp_type> > & types);
162 : :
163 : : void record_actions (unsigned actions, const token* tok, bool update=false);
164 : :
165 : : void visit_block (block* s);
166 : : void visit_try_block (try_block* s);
167 : : void visit_embeddedcode (embeddedcode* s);
168 : : void visit_null_statement (null_statement* s);
169 : : void visit_expr_statement (expr_statement* s);
170 : : void visit_if_statement (if_statement* s);
171 : : void visit_for_loop (for_loop* s);
172 : : void visit_foreach_loop (foreach_loop* s);
173 : : void visit_return_statement (return_statement* s);
174 : : void visit_delete_statement (delete_statement* s);
175 : : void visit_next_statement (next_statement* s);
176 : : void visit_break_statement (break_statement* s);
177 : : void visit_continue_statement (continue_statement* s);
178 : : void visit_literal_string (literal_string* e);
179 : : void visit_literal_number (literal_number* e);
180 : : void visit_embedded_expr (embedded_expr* e);
181 : : void visit_binary_expression (binary_expression* e);
182 : : void visit_unary_expression (unary_expression* e);
183 : : void visit_pre_crement (pre_crement* e);
184 : : void visit_post_crement (post_crement* e);
185 : : void visit_logical_or_expr (logical_or_expr* e);
186 : : void visit_logical_and_expr (logical_and_expr* e);
187 : : void visit_array_in (array_in* e);
188 : : void visit_regex_query (regex_query* e);
189 : : void visit_comparison (comparison* e);
190 : : void visit_concatenation (concatenation* e);
191 : : void visit_ternary_expression (ternary_expression* e);
192 : : void visit_assignment (assignment* e);
193 : : void visit_symbol (symbol* e);
194 : : void visit_target_symbol (target_symbol* e);
195 : : void visit_arrayindex (arrayindex* e);
196 : : void visit_functioncall (functioncall* e);
197 : : void visit_print_format (print_format* e);
198 : : void visit_stat_op (stat_op* e);
199 : : void visit_hist_op (hist_op* e);
200 : : void visit_cast_op (cast_op* e);
201 : : void visit_defined_op (defined_op* e);
202 : : void visit_entry_op (entry_op* e);
203 : : void visit_perf_op (perf_op* e);
204 : : };
205 : :
206 : : // A shadow visitor, meant to generate temporary variable declarations
207 : : // for function or probe bodies. Member functions should exactly match
208 : : // the corresponding c_unparser logic and traversal sequence,
209 : : // to ensure interlocking naming and declaration of temp variables.
210 [ - + ]: 14947 : struct c_tmpcounter:
211 : : public traversing_visitor
212 : : {
213 : : c_unparser* parent;
214 : 14947 : c_tmpcounter (c_unparser* p):
215 : 14947 : parent (p)
216 : : {
217 : 14947 : parent->tmpvar_counter = 0;
218 : 14947 : }
219 : :
220 : : void load_map_indices(arrayindex* e);
221 : : void load_aggregate (expression *e);
222 : :
223 : : void visit_block (block *s);
224 : : void visit_for_loop (for_loop* s);
225 : : void visit_foreach_loop (foreach_loop* s);
226 : : // void visit_return_statement (return_statement* s);
227 : : void visit_delete_statement (delete_statement* s);
228 : : // void visit_embedded_expr (embedded_expr* e);
229 : : void visit_binary_expression (binary_expression* e);
230 : : // void visit_unary_expression (unary_expression* e);
231 : : void visit_pre_crement (pre_crement* e);
232 : : void visit_post_crement (post_crement* e);
233 : : // void visit_logical_or_expr (logical_or_expr* e);
234 : : // void visit_logical_and_expr (logical_and_expr* e);
235 : : void visit_array_in (array_in* e);
236 : : void visit_regex_query (regex_query* e);
237 : : void visit_comparison (comparison* e);
238 : : void visit_concatenation (concatenation* e);
239 : : // void visit_ternary_expression (ternary_expression* e);
240 : : void visit_assignment (assignment* e);
241 : : void visit_arrayindex (arrayindex* e);
242 : : void visit_functioncall (functioncall* e);
243 : : void visit_print_format (print_format* e);
244 : : void visit_stat_op (stat_op* e);
245 : : };
246 : :
247 [ + - ][ - + ]: 36258 : struct c_unparser_assignment:
248 : : public throwing_visitor
249 : : {
250 : : c_unparser* parent;
251 : : string op;
252 : : expression* rvalue;
253 : : bool post; // true == value saved before modify operator
254 : 33839 : c_unparser_assignment (c_unparser* p, const string& o, expression* e):
255 : : throwing_visitor ("invalid lvalue type"),
256 [ + - ][ + - ]: 33839 : parent (p), op (o), rvalue (e), post (false) {}
[ + - ][ + - ]
257 : 2419 : c_unparser_assignment (c_unparser* p, const string& o, bool pp):
258 : : throwing_visitor ("invalid lvalue type"),
259 [ + - ][ + - ]: 2419 : parent (p), op (o), rvalue (0), post (pp) {}
[ + - ][ + - ]
260 : :
261 : : void prepare_rvalue (string const & op,
262 : : tmpvar & rval,
263 : : token const* tok);
264 : :
265 : : void c_assignop(tmpvar & res,
266 : : var const & lvar,
267 : : tmpvar const & tmp,
268 : : token const* tok);
269 : :
270 : : // only symbols and arrayindex nodes are possible lvalues
271 : : void visit_symbol (symbol* e);
272 : : void visit_arrayindex (arrayindex* e);
273 : : };
274 : :
275 : :
276 [ - + ]: 36258 : struct c_tmpcounter_assignment:
277 : : public traversing_visitor
278 : : // leave throwing for illegal lvalues to the c_unparser_assignment instance
279 : : {
280 : : c_tmpcounter* parent;
281 : : const string& op;
282 : : expression* rvalue;
283 : : bool post; // true == value saved before modify operator
284 : 36258 : c_tmpcounter_assignment (c_tmpcounter* p, const string& o, expression* e, bool pp = false):
285 : 36258 : parent (p), op (o), rvalue (e), post (pp) {}
286 : :
287 : : void prepare_rvalue (tmpvar & rval);
288 : :
289 : : void c_assignop(tmpvar & res);
290 : :
291 : : // only symbols and arrayindex nodes are possible lvalues
292 : : void visit_symbol (symbol* e);
293 : : void visit_arrayindex (arrayindex* e);
294 : : };
295 : :
296 : :
297 : : ostream & operator<<(ostream & o, var const & v);
298 : :
299 : :
300 : : /*
301 : : Some clarification on the runtime structures involved in statistics:
302 : :
303 : : The basic type for collecting statistics in the runtime is struct
304 : : stat_data. This contains the count, min, max, sum, and possibly
305 : : histogram fields.
306 : :
307 : : There are two places struct stat_data shows up.
308 : :
309 : : 1. If you declare a statistic variable of any sort, you want to make
310 : : a struct _Stat. A struct _Stat* is also called a Stat. Struct _Stat
311 : : contains a per-CPU array of struct stat_data values, as well as a
312 : : struct stat_data which it aggregates into. Writes into a Struct
313 : : _Stat go into the per-CPU struct stat. Reads involve write-locking
314 : : the struct _Stat, aggregating into its aggregate struct stat_data,
315 : : unlocking, read-locking the struct _Stat, then reading values out of
316 : : the aggregate and unlocking.
317 : :
318 : : 2. If you declare a statistic-valued map, you want to make a
319 : : pmap. This is a per-CPU array of maps, each of which holds struct
320 : : stat_data values, as well as an aggregate *map*. Writes into a pmap
321 : : go into the per-CPU map. Reads involve write-locking the pmap,
322 : : aggregating into its aggregate map, unlocking, read-locking the
323 : : pmap, then reading values out of its aggregate (which is a normal
324 : : map) and unlocking.
325 : :
326 : : Because, at the moment, the runtime does not support the concept of
327 : : a statistic which collects multiple histogram types, we may need to
328 : : instantiate one pmap or struct _Stat for each histogram variation
329 : : the user wants to track.
330 : : */
331 : :
332 : 186429 : class var
333 : : {
334 : :
335 : : protected:
336 : : // Required for accurate mangling:
337 : : c_unparser *u;
338 : :
339 : : bool local;
340 : : exp_type ty;
341 : : statistic_decl sd;
342 : : string name;
343 : : bool do_mangle;
344 : :
345 : : public:
346 : :
347 : 35044 : var(c_unparser *u, bool local, exp_type ty,
348 : : statistic_decl const & sd, string const & name)
349 : 35044 : : u(u), local(local), ty(ty), sd(sd), name(name), do_mangle(true)
350 : 35044 : {}
351 : :
352 : 50689 : var(c_unparser *u, bool local, exp_type ty, string const & name)
353 : 50689 : : u(u), local(local), ty(ty), name(name), do_mangle(true)
354 : 50689 : {}
355 : :
356 : 375120 : var(c_unparser *u, bool local, exp_type ty,
357 : : string const & name, bool do_mangle)
358 : 375120 : : u(u), local(local), ty(ty), name(name), do_mangle(do_mangle)
359 : 375120 : {}
360 : :
361 [ - + ]: 613020 : virtual ~var() {}
362 : :
363 : : bool is_local() const
364 : : {
365 : : return local;
366 : : }
367 : :
368 : 98 : statistic_decl const & sdecl() const
369 : : {
370 : 98 : return sd;
371 : : }
372 : :
373 : 118 : void assert_hist_compatible(hist_op const & hop)
374 : : {
375 : : // Semantic checks in elaborate should have caught this if it was
376 : : // false. This is just a double-check.
377 [ + + - - ]: 118 : switch (sd.type)
378 : : {
379 : : case statistic_decl::linear:
380 [ - + ]: 56 : assert(hop.htype == hist_linear);
381 [ - + ]: 56 : assert(hop.params.size() == 3);
382 [ - + ]: 56 : assert(hop.params[0] == sd.linear_low);
383 [ - + ]: 56 : assert(hop.params[1] == sd.linear_high);
384 [ - + ]: 56 : assert(hop.params[2] == sd.linear_step);
385 : 56 : break;
386 : : case statistic_decl::logarithmic:
387 [ - + ]: 62 : assert(hop.htype == hist_log);
388 [ - + ]: 62 : assert(hop.params.size() == 0);
389 : 62 : break;
390 : : case statistic_decl::none:
391 : 0 : assert(false);
392 : : }
393 : 118 : }
394 : :
395 : 243881 : exp_type type() const
396 : : {
397 : 243881 : return ty;
398 : : }
399 : :
400 : 420960 : string c_name() const
401 : : {
402 [ + + ]: 420960 : if (!do_mangle)
403 : 331188 : return name;
404 [ + + ]: 89772 : else if (local)
405 : 51277 : return u->c_localname(name);
406 : : else
407 : 420960 : return u->c_globalname(name);
408 : : }
409 : :
410 : 318903 : string value() const
411 : : {
412 [ + + ]: 318903 : if (local)
413 [ + - ]: 281790 : return "l->" + c_name();
414 : : else
415 [ + - ][ + - ]: 318903 : return "global(" + c_name() + ")";
[ + - ]
416 : : }
417 : :
418 : 86 : virtual string hist() const
419 : : {
420 [ - + ]: 86 : assert (ty == pe_stats);
421 [ - + ]: 86 : assert (sd.type != statistic_decl::none);
422 [ + - ][ + - ]: 86 : return "(&(" + value() + "->hist))";
[ + - ]
423 : : }
424 : :
425 : 14 : virtual string buckets() const
426 : : {
427 [ - + ]: 14 : assert (ty == pe_stats);
428 [ - + ]: 14 : assert (sd.type != statistic_decl::none);
429 [ + - ][ + - ]: 14 : return "(" + value() + "->hist.buckets)";
[ + - ]
430 : : }
431 : :
432 : 6962 : string init() const
433 : : {
434 [ + + + - ]: 6962 : switch (type())
435 : : {
436 : : case pe_string:
437 [ + + ]: 1944 : if (! local)
438 [ + - ]: 54 : return ""; // module_param
439 : : else
440 [ + - ]: 1890 : return value() + "[0] = '\\0';";
441 : : case pe_long:
442 [ + + ]: 4947 : if (! local)
443 [ + - ]: 298 : return ""; // module_param
444 : : else
445 [ + - ]: 4649 : return value() + " = 0;";
446 : : case pe_stats:
447 : : {
448 : : // See also mapvar::init().
449 : :
450 [ - + ]: 71 : if (local)
451 [ # # ][ # # ]: 0 : throw semantic_error(_F("unsupported local stats init for %s", value().c_str()));
[ # # ][ # # ]
452 : :
453 [ + - ][ + - ]: 71 : string prefix = "global_set(" + c_name() + ", _stp_stat_init (";
[ + - ][ + - ]
[ + - ]
454 : : // Check for errors during allocation.
455 [ + - ][ + - ]: 71 : string suffix = "if (" + value () + " == NULL) rc = -ENOMEM;";
[ + - ][ + - ]
[ + - ]
456 : :
457 [ + + + - ]: 71 : switch (sd.type)
458 : : {
459 : : case statistic_decl::none:
460 [ + - ]: 30 : prefix += "HIST_NONE";
461 : 30 : break;
462 : :
463 : : case statistic_decl::linear:
464 : : prefix += string("HIST_LINEAR")
465 : : + ", " + lex_cast(sd.linear_low)
466 : : + ", " + lex_cast(sd.linear_high)
467 [ + - ][ + - ]: 23 : + ", " + lex_cast(sd.linear_step);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
468 : 23 : break;
469 : :
470 : : case statistic_decl::logarithmic:
471 [ + - ][ + - ]: 18 : prefix += string("HIST_LOG");
[ + - ]
472 : 18 : break;
473 : :
474 : : default:
475 [ # # ][ # # ]: 0 : throw semantic_error(_F("unsupported stats type for %s", value().c_str()));
[ # # ][ # # ]
476 : : }
477 : :
478 [ + - ][ + - ]: 71 : prefix = prefix + ")); ";
[ + - ]
479 [ + - ][ + - ]: 71 : return string (prefix + suffix);
[ + - ]
480 : : }
481 : :
482 : : default:
483 [ # # ][ # # ]: 6962 : throw semantic_error(_F("unsupported initializer for %s", value().c_str()));
[ # # ][ # # ]
484 : : }
485 : : }
486 : :
487 : 846 : string fini () const
488 : : {
489 [ + + - ]: 846 : switch (type())
490 : : {
491 : : case pe_string:
492 : : case pe_long:
493 [ + - ]: 704 : return ""; // no action required
494 : : case pe_stats:
495 [ + - ][ + - ]: 142 : return "_stp_stat_del (" + value () + ");";
[ + - ]
496 : : default:
497 [ # # ][ # # ]: 846 : throw semantic_error(_F("unsupported deallocator for %s", value().c_str()));
[ # # ][ # # ]
498 : : }
499 : : }
500 : :
501 : 100675 : void declare(c_unparser &c) const
502 : : {
503 [ + - ]: 100675 : c.c_declare(ty, c_name());
504 : 100675 : }
505 : : };
506 : :
507 : 63063 : ostream & operator<<(ostream & o, var const & v)
508 : : {
509 [ + - ]: 63063 : return o << v.value();
510 : : }
511 : :
512 : : struct stmt_expr
513 : : {
514 : : c_unparser & c;
515 : 84759 : stmt_expr(c_unparser & c) : c(c)
516 : : {
517 : 84759 : c.o->newline() << "({";
518 : 84759 : c.o->indent(1);
519 : 84759 : }
520 : 84759 : ~stmt_expr()
521 : : {
522 : 84759 : c.o->newline(-1) << "})";
523 : 84759 : }
524 : : };
525 : :
526 : :
527 [ + - ][ - + ]: 704899 : struct tmpvar
[ + - ]
528 : : : public var
529 : : {
530 : : protected:
531 : : bool overridden;
532 : : string override_value;
533 : :
534 : : public:
535 : 367968 : tmpvar(c_unparser *u, exp_type ty, unsigned & counter)
536 : : : var(u, true, ty, ("__tmp" + lex_cast(counter++)), false),
537 [ + - ][ + - ]: 367968 : overridden(false)
[ + - ][ + - ]
[ + - ][ + - ]
538 : 367968 : {}
539 : :
540 : 1492 : tmpvar(const var& source)
541 [ + - ]: 1492 : : var(source), overridden(false)
542 : 1492 : {}
543 : :
544 : 55220 : void override(const string &value)
545 : : {
546 : 55220 : overridden = true;
547 : 55220 : override_value = value;
548 : 55220 : }
549 : :
550 : 281966 : string value() const
551 : : {
552 [ + + ]: 281966 : if (overridden)
553 : 76416 : return override_value;
554 : : else
555 : 281966 : return var::value();
556 : : }
557 : : };
558 : :
559 : 65184 : ostream & operator<<(ostream & o, tmpvar const & v)
560 : : {
561 [ + - ]: 65184 : return o << v.value();
562 : : }
563 : :
564 [ - + ]: 1388 : struct aggvar
565 : : : public var
566 : : {
567 : 1388 : aggvar(c_unparser *u, unsigned & counter)
568 [ + - ][ + - ]: 1388 : : var(u, true, pe_stats, ("__tmp" + lex_cast(counter++)), false)
[ + - ][ + - ]
[ + - ]
569 : 1388 : {}
570 : :
571 : : string init() const
572 : : {
573 : : assert (type() == pe_stats);
574 : : return value() + " = NULL;";
575 : : }
576 : :
577 : 694 : void declare(c_unparser &c) const
578 : : {
579 [ - + ]: 694 : assert (type() == pe_stats);
580 : 694 : c.o->newline() << "struct stat_data *" << name << ";";
581 : 694 : }
582 : :
583 : 11 : string get_hist (var& index) const
584 : : {
585 [ + - ][ + - ]: 11 : return "(" + value() + "->histogram[" + index.value() + "])";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
586 : : }
587 : : };
588 : :
589 [ + - ][ - + ]: 28931 : struct mapvar
590 : : : public var
591 : : {
592 : : vector<exp_type> index_types;
593 : : int maxsize;
594 : : bool wrap;
595 : 28486 : mapvar (c_unparser *u,
596 : : bool local, exp_type ty,
597 : : statistic_decl const & sd,
598 : : string const & name,
599 : : vector<exp_type> const & index_types,
600 : : int maxsize, bool wrap)
601 : : : var (u, local, ty, sd, name),
602 : : index_types (index_types),
603 [ + - ]: 28486 : maxsize (maxsize), wrap(wrap)
604 : 28486 : {}
605 : :
606 : : static string shortname(exp_type e);
607 : : static string key_typename(exp_type e);
608 : : static string value_typename(exp_type e);
609 : :
610 : 27605 : string keysym () const
611 : : {
612 [ + - ]: 27605 : string result;
613 [ + - ]: 27605 : vector<exp_type> tmp = index_types;
614 [ + - ]: 27605 : tmp.push_back (type ());
615 [ + + ]: 95990 : for (unsigned i = 0; i < tmp.size(); ++i)
616 : : {
617 [ + + + - ]: 68385 : switch (tmp[i])
618 : : {
619 : : case pe_long:
620 [ + - ]: 36768 : result += 'i';
621 : 36768 : break;
622 : : case pe_string:
623 [ + - ]: 23517 : result += 's';
624 : 23517 : break;
625 : : case pe_stats:
626 [ + - ]: 8100 : result += 'x';
627 : 8100 : break;
628 : : default:
629 [ # # ][ # # ]: 0 : throw semantic_error(_("unknown type of map"));
630 : : break;
631 : : }
632 : : }
633 [ + - ]: 27605 : return result;
634 : : }
635 : :
636 : 27605 : string function_keysym(string const & fname, bool pre_agg=false) const
637 : : {
638 [ + + ][ + + ]: 27605 : string mtype = (is_parallel() && !pre_agg) ? "pmap" : "map";
[ + - ]
639 [ + - ][ + - ]: 27605 : string result = "_stp_" + mtype + "_" + fname + "_" + keysym();
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
640 [ + - ]: 27605 : return result;
641 : : }
642 : :
643 : 25122 : string call_prefix (string const & fname, vector<tmpvar> const & indices, bool pre_agg=false) const
644 : : {
645 [ + - ][ + - ]: 25122 : string result = function_keysym(fname, pre_agg) + " (";
646 [ - + ][ # # ]: 25122 : result += pre_agg? fetch_existing_aggregate() : value();
[ + - ][ + - ]
[ + - ]
647 [ + + ]: 59785 : for (unsigned i = 0; i < indices.size(); ++i)
648 : : {
649 [ - + ]: 34663 : if (indices[i].type() != index_types[i])
650 [ # # ][ # # ]: 0 : throw semantic_error(_("index type mismatch"));
651 [ + - ]: 34663 : result += ", ";
652 [ + - ][ + - ]: 34663 : result += indices[i].value();
[ + - ]
653 : : }
654 : :
655 : 25122 : return result;
656 : : }
657 : :
658 : 32052 : bool is_parallel() const
659 : : {
660 : 32052 : return type() == pe_stats;
661 : : }
662 : :
663 : 100 : string calculate_aggregate() const
664 : : {
665 [ - + ]: 100 : if (!is_parallel())
666 [ # # ][ # # ]: 0 : throw semantic_error(_("aggregating non-parallel map type"));
667 : :
668 [ + - ][ + - ]: 100 : return function_keysym("agg") + " (" + value() + ")";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
669 : : }
670 : :
671 : 303 : string fetch_existing_aggregate() const
672 : : {
673 [ - + ]: 303 : if (!is_parallel())
674 [ # # ][ # # ]: 0 : throw semantic_error(_("fetching aggregate of non-parallel map type"));
675 : :
676 [ + - ][ + - ]: 303 : return "_stp_pmap_get_agg(" + value() + ")";
[ + - ]
677 : : }
678 : :
679 : 1665 : string del (vector<tmpvar> const & indices) const
680 : : {
681 [ + - ][ + - ]: 1665 : return (call_prefix("del", indices) + ")");
[ + - ][ + - ]
[ + - ]
682 : : }
683 : :
684 : 358 : string exists (vector<tmpvar> const & indices) const
685 : : {
686 [ + + ][ + + ]: 358 : if (type() == pe_long || type() == pe_string)
[ + + ]
687 [ + - ][ + - ]: 357 : return (call_prefix("exists", indices) + ")");
[ + - ][ + - ]
[ + - ]
688 [ + - ]: 1 : else if (type() == pe_stats)
689 : : return ("((uintptr_t)" + call_prefix("get", indices)
690 [ + - ][ + - ]: 1 : + ") != (uintptr_t) 0)");
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
691 : : else
692 [ # # ][ # # ]: 358 : throw semantic_error(_("checking existence of an unsupported map type"));
693 : : }
694 : :
695 : 4627 : string get (vector<tmpvar> const & indices, bool pre_agg=false) const
696 : : {
697 : : // see also itervar::get_key
698 [ + + ]: 4627 : if (type() == pe_string)
699 : : // impedance matching: NULL -> empty strings
700 : : return ("({ char *v = " + call_prefix("get", indices, pre_agg) + ");"
701 [ + - ][ + - ]: 1229 : + "if (!v) v = \"\"; v; })");
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
702 [ + + ][ + - ]: 3398 : else if (type() == pe_long || type() == pe_stats)
[ + - ]
703 [ + - ][ + - ]: 3398 : return call_prefix("get", indices, pre_agg) + ")";
[ + - ][ + - ]
[ + - ]
704 : : else
705 [ # # ][ # # ]: 4627 : throw semantic_error(_("getting a value from an unsupported map type"));
706 : : }
707 : :
708 : 7383 : string add (vector<tmpvar> const & indices, tmpvar const & val) const
709 : : {
710 [ + - ]: 7383 : string res = "{ int rc = ";
711 : :
712 : : // impedance matching: empty strings -> NULL
713 [ + - ]: 7383 : if (type() == pe_stats)
714 [ + - ][ + - ]: 7383 : res += (call_prefix("add", indices) + ", " + val.value() + ")");
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
715 : : else
716 [ # # ][ # # ]: 0 : throw semantic_error(_("adding a value of an unsupported map type"));
717 : :
718 [ + - ]: 7383 : res += "; if (unlikely(rc)) { c->last_error = ";
719 : 7383 : res += STAP_T_01 +
720 : : lex_cast(maxsize > 0 ?
721 : : "size limit (" + lex_cast(maxsize) + ")" : "MAXMAPENTRIES")
722 [ + + ][ + - ]: 7383 : + "\"; goto out; }}";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + + ]
[ + + ][ + - ]
[ + + ][ + - ]
[ # # # #
# # ]
723 : :
724 : 7383 : return res;
725 : : }
726 : :
727 : 11089 : string set (vector<tmpvar> const & indices, tmpvar const & val) const
728 : : {
729 [ + - ]: 11089 : string res = "{ int rc = ";
730 : :
731 : : // impedance matching: empty strings -> NULL
732 [ + + ]: 11089 : if (type() == pe_string)
733 : : res += (call_prefix("set", indices)
734 [ + - ][ + - ]: 2089 : + ", (" + val.value() + "[0] ? " + val.value() + " : NULL))");
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
735 [ + - ]: 9000 : else if (type() == pe_long)
736 [ + - ][ + - ]: 9000 : res += (call_prefix("set", indices) + ", " + val.value() + ")");
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
737 : : else
738 [ # # ][ # # ]: 0 : throw semantic_error(_("setting a value of an unsupported map type"));
739 : :
740 [ + - ]: 11089 : res += "; if (unlikely(rc)) { c->last_error = ";
741 : 11089 : res += STAP_T_01 +
742 : : lex_cast(maxsize > 0 ?
743 : : "size limit (" + lex_cast(maxsize) + ")" : "MAXMAPENTRIES")
744 [ + + ][ + - ]: 11089 : + "\"; goto out; }}";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + + ]
[ + + ][ + - ]
[ + + ][ + - ]
[ # # # #
# # ]
745 : :
746 : 11089 : return res;
747 : : }
748 : :
749 : 9 : string hist() const
750 : : {
751 [ - + ]: 9 : assert (ty == pe_stats);
752 [ - + ]: 9 : assert (sd.type != statistic_decl::none);
753 [ + - ][ + - ]: 9 : return "(&(" + fetch_existing_aggregate() + "->hist))";
[ + - ]
754 : : }
755 : :
756 : 9 : string buckets() const
757 : : {
758 [ - + ]: 9 : assert (ty == pe_stats);
759 [ - + ]: 9 : assert (sd.type != statistic_decl::none);
760 [ + - ][ + - ]: 9 : return "(" + fetch_existing_aggregate() + "->hist.buckets)";
[ + - ]
761 : : }
762 : :
763 : 1311 : string init () const
764 : : {
765 [ - + ]: 1311 : if (local)
766 [ # # ][ # # ]: 0 : throw semantic_error(_F("unsupported local map init for %s", value().c_str()));
[ # # ][ # # ]
767 : :
768 [ + - ][ + - ]: 1311 : string prefix = "global_set(" + c_name() + ", ";
[ + - ][ + - ]
[ + - ]
769 : : prefix += function_keysym("new") + " ("
770 : : + (maxsize > 0 ? lex_cast(maxsize) : "MAXMAPENTRIES")
771 [ + - ][ + - ]: 1311 : + ((wrap == true) ? ", 1" : ", 0");
[ + - ][ + + ]
[ + - ][ + - ]
[ + - ][ + + ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + + ]
[ + - ][ + - ]
[ + - ][ # # ]
772 : :
773 : : // See also var::init().
774 : :
775 : : // Check for errors during allocation.
776 [ + - ][ + - ]: 1311 : string suffix = "if (" + value () + " == NULL) rc = -ENOMEM;";
[ + - ][ + - ]
[ + - ]
777 : :
778 [ + + ]: 1311 : if (type() == pe_stats)
779 : : {
780 [ + - + - ]: 98 : switch (sdecl().type)
781 : : {
782 : : case statistic_decl::none:
783 [ + - ][ + - ]: 91 : prefix = prefix + ", HIST_NONE";
[ + - ]
784 : 91 : break;
785 : :
786 : : case statistic_decl::linear:
787 : : // FIXME: check for "reasonable" values in linear stats
788 : : prefix = prefix + ", HIST_LINEAR"
789 : 0 : + ", " + lex_cast(sdecl().linear_low)
790 : 0 : + ", " + lex_cast(sdecl().linear_high)
791 [ # # ]: 0 : + ", " + lex_cast(sdecl().linear_step);
[ # # # # ]
[ # # ]
[ # # # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
792 : 0 : break;
793 : :
794 : : case statistic_decl::logarithmic:
795 [ + - ][ + - ]: 7 : prefix = prefix + ", HIST_LOG";
[ + - ]
796 : 98 : break;
797 : : }
798 : : }
799 : :
800 [ + - ][ + - ]: 1311 : prefix = prefix + ")); ";
[ + - ]
801 [ + - ][ + - ]: 1311 : return (prefix + suffix);
[ + - ]
802 : : }
803 : :
804 : 2622 : string fini () const
805 : : {
806 : : // NB: fini() is safe to call even for globals that have not
807 : : // successfully initialized (that is to say, on NULL pointers),
808 : : // because the runtime specifically tolerates that in its _del
809 : : // functions.
810 : :
811 [ + + ]: 2622 : if (is_parallel())
812 [ + - ][ + - ]: 196 : return "_stp_pmap_del (" + value() + ");";
[ + - ]
813 : : else
814 [ + - ][ + - ]: 2622 : return "_stp_map_del (" + value() + ");";
[ + - ]
815 : : }
816 : : };
817 : :
818 : :
819 : 540 : class itervar
820 : : {
821 : : exp_type referent_ty;
822 : : string name;
823 : :
824 : : public:
825 : :
826 : 540 : itervar (symbol* e, unsigned & counter)
827 : : : referent_ty(e->referent->type),
828 [ + - ][ + - ]: 540 : name("__tmp" + lex_cast(counter++))
[ + - ]
829 : : {
830 [ - + ]: 540 : if (referent_ty == pe_unknown)
831 [ # # ][ # # ]: 0 : throw semantic_error(_("iterating over unknown reference type"), e->tok);
832 : 540 : }
833 : :
834 : 270 : string declare () const
835 : : {
836 [ + - ]: 270 : return "struct map_node *" + name + ";";
837 : : }
838 : :
839 : 270 : string start (mapvar const & mv) const
840 : : {
841 [ + - ]: 270 : string res;
842 : :
843 [ - + ]: 270 : if (mv.type() != referent_ty)
844 [ # # ][ # # ]: 0 : throw semantic_error(_("inconsistent iterator type in itervar::start()"));
845 : :
846 [ + + ]: 270 : if (mv.is_parallel())
847 [ + - ][ + - ]: 100 : return "_stp_map_start (" + mv.fetch_existing_aggregate() + ")";
[ + - ][ + - ]
[ + - ]
848 : : else
849 [ + - ][ + - ]: 270 : return "_stp_map_start (" + mv.value() + ")";
[ + - ][ + - ]
[ + - ][ + - ]
850 : : }
851 : :
852 : 270 : string next (mapvar const & mv) const
853 : : {
854 [ - + ]: 270 : if (mv.type() != referent_ty)
855 [ # # ][ # # ]: 0 : throw semantic_error(_("inconsistent iterator type in itervar::next()"));
856 : :
857 [ + + ]: 270 : if (mv.is_parallel())
858 [ + - ][ + - ]: 100 : return "_stp_map_iter (" + mv.fetch_existing_aggregate() + ", " + value() + ")";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
859 : : else
860 [ + - ][ + - ]: 270 : return "_stp_map_iter (" + mv.value() + ", " + value() + ")";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
861 : : }
862 : :
863 : 1988 : string value () const
864 : : {
865 : 1988 : return "l->" + name;
866 : : }
867 : :
868 : 596 : string get_key (mapvar const& mv, exp_type ty, unsigned i) const
869 : : {
870 : : // bug translator/1175: runtime uses base index 1 for the first dimension
871 : : // see also mapval::get
872 [ + + - ]: 596 : switch (ty)
873 : : {
874 : : case pe_long:
875 : : return mv.function_keysym("key_get_int64", true)
876 [ + - ][ + - ]: 358 : + " (" + value() + ", " + lex_cast(i+1) + ")";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
877 : : case pe_string:
878 : : // impedance matching: NULL -> empty strings
879 : : return "(" + mv.function_keysym("key_get_str", true)
880 [ + - ][ + - ]: 238 : + " (" + value() + ", " + lex_cast(i+1) + ") ?: \"\")";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
881 : : default:
882 [ # # ][ # # ]: 596 : throw semantic_error(_("illegal key type"));
883 : : }
884 : : }
885 : :
886 : 312 : string get_value (mapvar const& mv, exp_type ty) const
887 : : {
888 [ - + ]: 312 : if (ty != referent_ty)
889 [ # # ][ # # ]: 0 : throw semantic_error(_("inconsistent iterator value in itervar::get_value()"));
890 : :
891 [ + + + - ]: 312 : switch (ty)
892 : : {
893 : : case pe_long:
894 [ + - ][ + - ]: 136 : return mv.function_keysym("get_int64", true) + " ("+ value() + ")";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
895 : : case pe_string:
896 : : // impedance matching: NULL -> empty strings
897 [ + - ][ + - ]: 76 : return "(" + mv.function_keysym("get_str", true) + " ("+ value() + ") ?: \"\")";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
898 : : case pe_stats:
899 [ + - ][ + - ]: 100 : return mv.function_keysym("get_stat_data", true) + " ("+ value() + ")";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
900 : : default:
901 [ # # ][ # # ]: 312 : throw semantic_error(_("illegal value type"));
902 : : }
903 : : }
904 : : };
905 : :
906 : 810 : ostream & operator<<(ostream & o, itervar const & v)
907 : : {
908 [ + - ]: 810 : return o << v.value();
909 : : }
910 : :
911 : : // ------------------------------------------------------------------------
912 : :
913 : :
914 : 46130 : translator_output::translator_output (ostream& f):
915 : 46130 : buf(0), o2 (0), o (f), tablevel (0)
916 : : {
917 : 46130 : }
918 : :
919 : :
920 : 755 : translator_output::translator_output (const string& filename, size_t bufsize):
921 : 755 : buf (new char[bufsize]),
922 [ + - ]: 755 : o2 (new ofstream (filename.c_str ())),
923 : : o (*o2),
924 : : tablevel (0),
925 : 1510 : filename (filename)
926 : : {
927 [ + - ][ + - ]: 755 : o2->rdbuf()->pubsetbuf(buf, bufsize);
928 : 755 : }
929 : :
930 : :
931 : 93550 : translator_output::~translator_output ()
932 : : {
933 [ + + ][ + - ]: 46775 : delete o2;
934 [ + + ]: 46775 : delete [] buf;
935 : 46775 : }
936 : :
937 : :
938 : : ostream&
939 : 2431953 : translator_output::newline (int indent)
940 : : {
941 [ + + ][ - + ]: 2431953 : if (! (indent > 0 || tablevel >= (unsigned)-indent)) o.flush ();
942 [ + + ][ - + ]: 2431953 : assert (indent > 0 || tablevel >= (unsigned)-indent);
943 : :
944 : 2431953 : tablevel += indent;
945 : 2431953 : o << "\n";
946 [ + + ]: 8376450 : for (unsigned i=0; i<tablevel; i++)
947 : 5944497 : o << " ";
948 : 2431953 : return o;
949 : : }
950 : :
951 : :
952 : : void
953 : 371285 : translator_output::indent (int indent)
954 : : {
955 [ + + ][ - + ]: 371285 : if (! (indent > 0 || tablevel >= (unsigned)-indent)) o.flush ();
956 [ + + ][ - + ]: 371285 : assert (indent > 0 || tablevel >= (unsigned)-indent);
957 : 371285 : tablevel += indent;
958 : 371285 : }
959 : :
960 : :
961 : : ostream&
962 : 955795 : translator_output::line ()
963 : : {
964 : 955795 : return o;
965 : : }
966 : :
967 : :
968 : : // ------------------------------------------------------------------------
969 : :
970 : : void
971 : 645 : c_unparser::emit_common_header ()
972 : : {
973 [ + - ]: 645 : o->newline();
974 : :
975 : : // Per CPU context for probes. Includes common shared state held for
976 : : // all probes (defined in common_probe_context), the probe locals (union)
977 : : // and the function locals (union).
978 [ + - ][ + - ]: 645 : o->newline() << "struct context {";
979 : :
980 : : // Common state held shared by probes.
981 [ + - ][ + - ]: 645 : o->newline(1) << "#include \"common_probe_context.h\"";
982 : :
983 : : // PR10516: probe locals
984 [ + - ][ + - ]: 645 : o->newline() << "union {";
985 [ + - ]: 645 : o->indent(1);
986 : :
987 : : // To elide context variables for probe handler functions that
988 : : // themselves are about to get duplicate-eliminated, we XXX
989 : : // duplicate the parse-tree-hash method from ::emit_probe().
990 [ + - ]: 645 : map<string, string> tmp_probe_contents;
991 : : // The reason we don't use c_unparser::probe_contents itself
992 : : // for this is that we don't want to muck up the data for
993 : : // that later routine.
994 : :
995 [ + + ]: 17506 : for (unsigned i=0; i<session->probes.size(); i++)
996 : : {
997 : 16861 : derived_probe* dp = session->probes[i];
998 : :
999 : : // NB: see c_unparser::emit_probe() for original copy of duplicate-hashing logic.
1000 [ + - ]: 16861 : ostringstream oss;
1001 [ + - ][ + - ]: 16861 : oss << "# needs_global_locks: " << dp->needs_global_locks () << endl;
[ + - ][ + - ]
1002 [ + - ]: 16861 : dp->print_dupe_stamp (oss);
1003 [ + - ]: 16861 : dp->body->print(oss);
1004 : : // NB: dependent probe conditions *could* be listed here, but don't need to be.
1005 : : // That's because they're only dependent on the probe body, which is already
1006 : : // "hashed" in above.
1007 : :
1008 [ + - ][ + - ]: 16861 : if (tmp_probe_contents.count(oss.str()) == 0) // unique
[ + - ][ + + ]
1009 : : {
1010 [ + - ][ + - ]: 8570 : tmp_probe_contents[oss.str()] = dp->name; // save it
[ + - ][ + - ]
1011 : :
1012 [ + - ][ + - ]: 8570 : o->newline() << "struct " << dp->name << "_locals {";
[ + - ][ + - ]
1013 [ + - ]: 8570 : o->indent(1);
1014 [ + + ]: 23725 : for (unsigned j=0; j<dp->locals.size(); j++)
1015 : : {
1016 : 15155 : vardecl* v = dp->locals[j];
1017 : : try
1018 : : {
1019 [ + - ][ + - ]: 30310 : o->newline() << c_typename (v->type) << " "
[ + - ][ + - ]
[ + - ]
1020 [ + - ][ + - ]: 15155 : << c_localname (v->name) << ";";
[ + - ][ + - ]
1021 [ # # ]: : } catch (const semantic_error& e) {
1022 [ # # ]: : semantic_error e2 (e);
1023 [ # # ]: : if (e2.tok1 == 0) e2.tok1 = v->tok;
1024 [ # # ]: : throw e2;
1025 : : }
1026 : : }
1027 : :
1028 : : // NB: This part is finicky. The logic here must
1029 : : // match up with
1030 [ + - ]: 8570 : c_tmpcounter ct (this);
1031 [ + - ]: 8570 : dp->body->visit (& ct);
1032 : :
1033 [ + - ][ + - ]: 8570 : o->newline(-1) << "} " << dp->name << ";";
[ + - ][ + - ]
[ + - ]
1034 : : }
1035 [ + - ]: 16861 : }
1036 [ + - ][ + - ]: 645 : o->newline(-1) << "} probe_locals;";
1037 : :
1038 : : // PR10516: function locals
1039 [ + - ][ + - ]: 645 : o->newline() << "union {";
1040 [ + - ]: 645 : o->indent(1);
1041 : :
1042 [ + - ][ + - ]: 7022 : for (map<string,functiondecl*>::iterator it = session->functions.begin(); it != session->functions.end(); it++)
[ + + ]
1043 : : {
1044 [ + - ]: 6377 : functiondecl* fd = it->second;
1045 [ + - ]: 6377 : o->newline()
1046 [ + - ][ + - ]: 6377 : << "struct " << c_funcname (fd->name) << "_locals {";
[ + - ][ + - ]
[ + - ]
1047 [ + - ]: 6377 : o->indent(1);
1048 [ + + ]: 7152 : for (unsigned j=0; j<fd->locals.size(); j++)
1049 : : {
1050 : 775 : vardecl* v = fd->locals[j];
1051 : : try
1052 : : {
1053 [ - + ]: 775 : if (fd->mangle_oldstyle)
1054 : : {
1055 : : // PR14524: retain old way of referring to the locals
1056 [ # # ][ # # ]: 0 : o->newline() << "union { "
1057 [ # # ][ # # ]: 0 : << c_typename (v->type) << " "
[ # # ][ # # ]
1058 [ # # ][ # # ]: 0 : << c_localname (v->name) << "; "
[ # # ][ # # ]
1059 [ # # ][ # # ]: 0 : << c_typename (v->type) << " "
[ # # ][ # # ]
1060 [ # # ][ # # ]: 0 : << c_localname (v->name, true) << "; };";
[ # # ][ # # ]
1061 : : }
1062 : : else
1063 : : {
1064 [ + - ][ + - ]: 1550 : o->newline() << c_typename (v->type) << " "
[ + - ][ + - ]
[ + - ]
1065 [ + - ][ + - ]: 775 : << c_localname (v->name) << ";";
[ + - ][ + - ]
1066 : : }
1067 [ # # ]: : } catch (const semantic_error& e) {
1068 [ # # ]: : semantic_error e2 (e);
1069 [ # # ]: : if (e2.tok1 == 0) e2.tok1 = v->tok;
1070 [ # # ]: : throw e2;
1071 : : }
1072 : : }
1073 [ + + ]: 10546 : for (unsigned j=0; j<fd->formal_args.size(); j++)
1074 : : {
1075 : 4169 : vardecl* v = fd->formal_args[j];
1076 : : try
1077 : : {
1078 [ + + ]: 4169 : if (fd->mangle_oldstyle)
1079 : : {
1080 : : // PR14524: retain old way of referring to the locals
1081 [ + - ][ + - ]: 2 : o->newline() << "union { "
1082 [ + - ][ + - ]: 4 : << c_typename (v->type) << " "
[ + - ][ + - ]
1083 [ + - ][ + - ]: 4 : << c_localname (v->name) << "; "
[ + - ][ + - ]
1084 [ + - ][ + - ]: 4 : << c_typename (v->type) << " "
[ + - ][ + - ]
1085 [ + - ][ + - ]: 2 : << c_localname (v->name, true) << "; };";
[ + - ][ + - ]
1086 : : }
1087 : : else
1088 : : {
1089 [ + - ][ + - ]: 8334 : o->newline() << c_typename (v->type) << " "
[ + - ][ + - ]
[ + - ]
1090 [ + - ][ + - ]: 4167 : << c_localname (v->name) << ";";
[ + - ][ + - ]
1091 : : }
1092 [ # # ]: : } catch (const semantic_error& e) {
1093 [ # # ]: : semantic_error e2 (e);
1094 [ # # ]: : if (e2.tok1 == 0) e2.tok1 = v->tok;
1095 [ # # ]: : throw e2;
1096 : : }
1097 : : }
1098 [ + - ]: 6377 : c_tmpcounter ct (this);
1099 [ + - ]: 6377 : fd->body->visit (& ct);
1100 [ + + ]: 6377 : if (fd->type == pe_unknown)
1101 [ + - ][ + - ]: 613 : o->newline() << "/* no return value */";
1102 : : else
1103 : : {
1104 [ + - ][ + - ]: 5764 : o->newline() << c_typename (fd->type) << " __retvalue;";
[ + - ][ + - ]
[ + - ]
1105 : : }
1106 [ + - ][ + - ]: 6377 : o->newline(-1) << "} " << c_funcname (fd->name) << ";";
[ + - ][ + - ]
[ + - ][ + - ]
1107 [ + - ]: 6377 : }
1108 [ + - ][ + - ]: 645 : o->newline(-1) << "} locals [MAXNESTING+1];";
1109 : :
1110 : : // NB: The +1 above for extra room for outgoing arguments of next nested function.
1111 : : // If MAXNESTING is set too small, the args will be written, but the MAXNESTING
1112 : : // check done at c_unparser::emit_function will reject.
1113 : : //
1114 : : // This policy wastes memory (one row of locals[] that cannot really
1115 : : // be used), but trades that for smaller code (not having to check
1116 : : // c->nesting against MAXNESTING at every call site).
1117 : :
1118 : : // Try to catch a crazy user dude passing in -DMAXNESTING=-1, leading to a [0]-sized
1119 : : // locals[] array.
1120 [ + - ][ + - ]: 645 : o->newline() << "#if MAXNESTING < 0";
1121 [ + - ][ + - ]: 645 : o->newline() << "#error \"MAXNESTING must be positive\"";
1122 [ + - ][ + - ]: 645 : o->newline() << "#endif";
1123 : :
1124 : : // Use a separate union for compiled-printf locals, no nesting required.
1125 [ + - ]: 645 : emit_compiled_printf_locals ();
1126 : :
1127 [ + - ][ + - ]: 645 : o->newline(-1) << "};\n"; // end of struct context
1128 : :
1129 [ + - ][ + - ]: 645 : o->newline() << "#include \"runtime_context.h\"";
1130 : :
1131 [ + - ]: 645 : emit_map_type_instantiations ();
1132 : :
1133 [ + - ]: 645 : emit_compiled_printfs();
1134 : :
1135 [ + - ][ + - ]: 645 : o->newline();
1136 : 645 : }
1137 : :
1138 : :
1139 : : void
1140 : 10829 : c_unparser::declare_compiled_printf (bool print_to_stream, const string& format)
1141 : : {
1142 [ + - ]: 10829 : pair<bool, string> index (print_to_stream, format);
1143 [ + - ]: 10829 : map<pair<bool, string>, string>::iterator it = compiled_printfs.find(index);
1144 [ + - ][ + + ]: 10829 : if (it == compiled_printfs.end())
1145 [ + - ]: 4783 : compiled_printfs[index] = (print_to_stream ? "stp_printf_" : "stp_sprintf_")
1146 [ + + ][ + - ]: 10829 : + lex_cast(compiled_printfs.size() + 1);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1147 : 10829 : }
1148 : :
1149 : : const string&
1150 : 10828 : c_unparser::get_compiled_printf (bool print_to_stream, const string& format)
1151 : : {
1152 : : map<pair<bool, string>, string>::iterator it =
1153 [ + - ][ + - ]: 10828 : compiled_printfs.find(make_pair(print_to_stream, format));
[ + - ][ + - ]
[ + - ]
1154 [ + - ][ - + ]: 10828 : if (it == compiled_printfs.end())
1155 [ # # ][ # # ]: 0 : throw semantic_error (_("internal error translating printf"));
1156 [ + - ]: 10828 : return it->second;
1157 : : }
1158 : :
1159 : : void
1160 : 645 : c_unparser::emit_compiled_printf_locals ()
1161 : : {
1162 [ + - ][ + - ]: 645 : o->newline() << "#ifndef STP_LEGACY_PRINT";
1163 [ + - ][ + - ]: 645 : o->newline() << "union {";
1164 [ + - ]: 645 : o->indent(1);
1165 : 645 : map<pair<bool, string>, string>::iterator it;
1166 [ + - ][ + - ]: 5428 : for (it = compiled_printfs.begin(); it != compiled_printfs.end(); ++it)
[ + + ]
1167 : : {
1168 [ + - ]: 4783 : bool print_to_stream = it->first.first;
1169 [ + - ]: 4783 : const string& format_string = it->first.second;
1170 [ + - ]: 4783 : const string& name = it->second;
1171 : : vector<print_format::format_component> components =
1172 [ + - ]: 4783 : print_format::string_to_components(format_string);
1173 : :
1174 [ + - ][ + - ]: 4783 : o->newline() << "struct " << name << "_locals {";
[ + - ][ + - ]
1175 [ + - ]: 4783 : o->indent(1);
1176 : :
1177 : 4783 : size_t arg_ix = 0;
1178 : 4783 : vector<print_format::format_component>::const_iterator c;
1179 [ + - ][ + - ]: 31389 : for (c = components.begin(); c != components.end(); ++c)
[ + - ][ + - ]
[ + + ]
1180 : : {
1181 [ + + ]: 26606 : if (c->type == print_format::conv_literal)
1182 : 13597 : continue;
1183 : :
1184 : : // Take note of the width and precision arguments, if any.
1185 [ + + ]: 13009 : if (c->widthtype == print_format::width_dynamic)
1186 [ + - ][ + - ]: 17 : o->newline() << "int64_t arg" << arg_ix++ << ";";
[ + - ][ + - ]
1187 [ + + ]: 13009 : if (c->prectype == print_format::prec_dynamic)
1188 [ + - ][ + - ]: 14 : o->newline() << "int64_t arg" << arg_ix++ << ";";
[ + - ][ + - ]
1189 : :
1190 : : // Output the actual argument.
1191 [ + + - ]: 13009 : switch (c->type)
1192 : : {
1193 : : case print_format::conv_pointer:
1194 : : case print_format::conv_number:
1195 : : case print_format::conv_char:
1196 : : case print_format::conv_memory:
1197 : : case print_format::conv_memory_hex:
1198 : : case print_format::conv_binary:
1199 [ + - ][ + - ]: 10607 : o->newline() << "int64_t arg" << arg_ix++ << ";";
[ + - ][ + - ]
1200 : 10607 : break;
1201 : :
1202 : : case print_format::conv_string:
1203 : : // NB: Since we know incoming strings are immutable, we can use
1204 : : // const char* rather than a private char[] copy. This is a
1205 : : // special case of the sort of optimizations desired in PR11528.
1206 [ + - ][ + - ]: 2402 : o->newline() << "const char* arg" << arg_ix++ << ";";
[ + - ][ + - ]
1207 : 2402 : break;
1208 : :
1209 : : default:
1210 : 0 : assert(false); // XXX
1211 : : break;
1212 : : }
1213 : : }
1214 : :
1215 : :
1216 [ + + ]: 4783 : if (!print_to_stream)
1217 [ + - ][ + - ]: 3471 : o->newline() << "char * __retvalue;";
1218 : :
1219 [ + - ][ + - ]: 4783 : o->newline(-1) << "} " << name << ";";
[ + - ][ + - ]
1220 [ + - ]: 4783 : }
1221 [ + - ][ + - ]: 645 : o->newline(-1) << "} printf_locals;";
1222 [ + - ][ + - ]: 645 : o->newline() << "#endif // STP_LEGACY_PRINT";
1223 : 645 : }
1224 : :
1225 : : void
1226 : 645 : c_unparser::emit_compiled_printfs ()
1227 : : {
1228 [ + - ][ + - ]: 645 : o->newline() << "#ifndef STP_LEGACY_PRINT";
1229 : 645 : map<pair<bool, string>, string>::iterator it;
1230 [ + - ][ + - ]: 5428 : for (it = compiled_printfs.begin(); it != compiled_printfs.end(); ++it)
[ + + ]
1231 : : {
1232 [ + - ]: 4783 : bool print_to_stream = it->first.first;
1233 [ + - ]: 4783 : const string& format_string = it->first.second;
1234 [ + - ]: 4783 : const string& name = it->second;
1235 : : vector<print_format::format_component> components =
1236 [ + - ]: 4783 : print_format::string_to_components(format_string);
1237 : :
1238 [ + - ]: 4783 : o->newline();
1239 : :
1240 : : // Might be nice to output the format string in a comment, but we'd have
1241 : : // to be extra careful about format strings not escaping the comment...
1242 [ + - ][ + - ]: 4783 : o->newline() << "static void " << name
[ + - ]
1243 [ + - ]: 4783 : << " (struct context* __restrict__ c) {";
1244 [ + - ][ + - ]: 4783 : o->newline(1) << "struct " << name << "_locals * __restrict__ l = "
[ + - ][ + - ]
1245 [ + - ][ + - ]: 4783 : << "& c->printf_locals." << name << ";";
[ + - ]
1246 [ + - ][ + - ]: 4783 : o->newline() << "char *str = NULL, *end = NULL;";
1247 [ + - ][ + - ]: 4783 : o->newline() << "const char *src;";
1248 [ + - ][ + - ]: 4783 : o->newline() << "int width;";
1249 [ + - ][ + - ]: 4783 : o->newline() << "int precision;";
1250 [ + - ][ + - ]: 4783 : o->newline() << "unsigned long ptr_value;";
1251 [ + - ][ + - ]: 4783 : o->newline() << "int num_bytes;";
1252 : :
1253 [ + - ][ + - ]: 4783 : o->newline() << "(void) width;";
1254 [ + - ][ + - ]: 4783 : o->newline() << "(void) precision;";
1255 [ + - ][ + - ]: 4783 : o->newline() << "(void) ptr_value;";
1256 [ + - ][ + - ]: 4783 : o->newline() << "(void) num_bytes;";
1257 : :
1258 [ + + ]: 4783 : if (print_to_stream)
1259 : : {
1260 : : // Compute the buffer size needed for these arguments.
1261 : 1312 : size_t arg_ix = 0;
1262 [ + - ][ + - ]: 1312 : o->newline() << "num_bytes = 0;";
1263 : 1312 : vector<print_format::format_component>::const_iterator c;
1264 [ + - ][ + - ]: 8176 : for (c = components.begin(); c != components.end(); ++c)
[ + - ][ + - ]
[ + + ]
1265 : : {
1266 [ + + ]: 6864 : if (c->type == print_format::conv_literal)
1267 : : {
1268 [ + - ]: 3592 : literal_string ls(c->literal_string);
1269 [ + - ][ + - ]: 3592 : o->newline() << "num_bytes += sizeof(";
1270 [ + - ]: 3592 : visit_literal_string(&ls);
1271 [ + - ]: 3592 : o->line() << ") - 1;"; // don't count the '\0'
1272 [ + - ]: 3592 : continue;
1273 : : }
1274 : :
1275 [ + - ][ + - ]: 3272 : o->newline() << "width = ";
1276 [ + + ]: 3272 : if (c->widthtype == print_format::width_dynamic)
1277 [ + - ][ + - ]: 4 : o->line() << "clamp_t(int, l->arg" << arg_ix++
1278 [ + - ]: 4 : << ", 0, STP_BUFFER_SIZE);";
1279 [ + + ]: 3268 : else if (c->widthtype == print_format::width_static)
1280 [ + - ][ + - ]: 696 : o->line() << "clamp_t(int, " << c->width
1281 [ + - ]: 696 : << ", 0, STP_BUFFER_SIZE);";
1282 : : else
1283 [ + - ]: 2572 : o->line() << "-1;";
1284 : :
1285 [ + - ][ + - ]: 3272 : o->newline() << "precision = ";
1286 [ + + ]: 3272 : if (c->prectype == print_format::prec_dynamic)
1287 [ + - ][ + - ]: 4 : o->line() << "clamp_t(int, l->arg" << arg_ix++
1288 [ + - ]: 4 : << ", 0, STP_BUFFER_SIZE);";
1289 [ + + ]: 3268 : else if (c->prectype == print_format::prec_static)
1290 [ + - ][ + - ]: 34 : o->line() << "clamp_t(int, " << c->precision
1291 [ + - ]: 34 : << ", 0, STP_BUFFER_SIZE);";
1292 : : else
1293 [ + - ]: 3234 : o->line() << "-1;";
1294 : :
1295 [ + - ][ + - ]: 3272 : string value = "l->arg" + lex_cast(arg_ix++);
[ + - ]
1296 [ + + + + : 3272 : switch (c->type)
+ + - ]
1297 : : {
1298 : : case print_format::conv_pointer:
1299 : : // NB: stap < 1.3 had odd %p behavior... see _stp_vsnprintf
1300 [ + - ][ + + ]: 96 : if (strverscmp(session->compatible.c_str(), "1.3") < 0)
1301 : : {
1302 [ + - ][ + - ]: 12 : o->newline() << "ptr_value = " << value << ";";
[ + - ][ + - ]
1303 [ + - ][ + - ]: 12 : o->newline() << "if (width == -1)";
1304 [ + - ][ + - ]: 12 : o->newline(1) << "width = 2 + 2 * sizeof(void*);";
1305 [ + - ][ + - ]: 12 : o->newline(-1) << "precision = width - 2;";
1306 [ + + ]: 12 : if (!c->test_flag(print_format::fmt_flag_left))
1307 [ + - ][ + - ]: 8 : o->newline() << "precision = min_t(int, precision, 2 * sizeof(void*));";
1308 [ + - ][ + - ]: 12 : o->newline() << "num_bytes += number_size(ptr_value, "
1309 [ + - ][ + - ]: 12 : << c->base << ", width, precision, " << c->flags << ");";
[ + - ][ + - ]
1310 : 12 : break;
1311 : : }
1312 : : // else fall-through to conv_number
1313 : : case print_format::conv_number:
1314 [ + - ][ + - ]: 1984 : o->newline() << "num_bytes += number_size(" << value << ", "
[ + - ][ + - ]
1315 [ + - ][ + - ]: 1984 : << c->base << ", width, precision, " << c->flags << ");";
[ + - ][ + - ]
1316 : 1984 : break;
1317 : :
1318 : : case print_format::conv_char:
1319 [ + - ][ + - ]: 23 : o->newline() << "num_bytes += _stp_vsprint_char_size("
1320 [ + - ][ + - ]: 23 : << value << ", width, " << c->flags << ");";
[ + - ][ + - ]
1321 : 23 : break;
1322 : :
1323 : : case print_format::conv_string:
1324 [ + - ][ + - ]: 1144 : o->newline() << "num_bytes += _stp_vsprint_memory_size("
1325 [ + - ][ + - ]: 1144 : << value << ", width, precision, 's', "
1326 [ + - ][ + - ]: 1144 : << c->flags << ");";
1327 : 1144 : break;
1328 : :
1329 : : case print_format::conv_memory:
1330 : : case print_format::conv_memory_hex:
1331 [ + - ][ + - ]: 24 : o->newline() << "num_bytes += _stp_vsprint_memory_size("
1332 [ + - ][ + - ]: 24 : << "(const char*)(intptr_t)" << value
1333 [ + - ]: 24 : << ", width, precision, '"
1334 [ + + ][ + - ]: 24 : << ((c->type == print_format::conv_memory) ? "m" : "M")
1335 [ + - ][ + - ]: 24 : << "', " << c->flags << ");";
[ + - ]
1336 : 24 : break;
1337 : :
1338 : : case print_format::conv_binary:
1339 [ + - ][ + - ]: 85 : o->newline() << "num_bytes += _stp_vsprint_binary_size("
1340 [ + - ][ + - ]: 85 : << value << ", width, precision);";
1341 : 85 : break;
1342 : :
1343 : : default:
1344 : 0 : assert(false); // XXX
1345 : : break;
1346 : : }
1347 [ + - ]: 3272 : }
1348 : :
1349 [ + - ][ + - ]: 1312 : o->newline() << "num_bytes = clamp(num_bytes, 0, STP_BUFFER_SIZE);";
1350 [ + - ][ + - ]: 1312 : o->newline() << "str = (char*)_stp_reserve_bytes(num_bytes);";
1351 [ + - ][ + - ]: 1312 : o->newline() << "end = str ? str + num_bytes - 1 : 0;";
1352 : : }
1353 : : else // !print_to_stream
1354 : : {
1355 : : // String results are a known buffer and size;
1356 [ + - ][ + - ]: 3471 : o->newline() << "str = l->__retvalue;";
1357 [ + - ][ + - ]: 3471 : o->newline() << "end = str + MAXSTRINGLEN - 1;";
1358 : : }
1359 : :
1360 [ + - ][ + - ]: 4783 : o->newline() << "if (str && str <= end) {";
1361 [ + - ]: 4783 : o->indent(1);
1362 : :
1363 : : // Generate code to print the actual arguments.
1364 : 4783 : size_t arg_ix = 0;
1365 : 4783 : vector<print_format::format_component>::const_iterator c;
1366 [ + - ][ + - ]: 31389 : for (c = components.begin(); c != components.end(); ++c)
[ + - ][ + - ]
[ + + ]
1367 : : {
1368 [ + + ]: 26606 : if (c->type == print_format::conv_literal)
1369 : : {
1370 [ + - ]: 13597 : literal_string ls(c->literal_string);
1371 [ + - ][ + - ]: 13597 : o->newline() << "src = ";
1372 [ + - ]: 13597 : visit_literal_string(&ls);
1373 [ + - ]: 13597 : o->line() << ";";
1374 [ + - ][ + - ]: 13597 : o->newline() << "while (*src && str <= end)";
1375 [ + - ][ + - ]: 13597 : o->newline(1) << "*str++ = *src++;";
1376 [ + - ]: 13597 : o->indent(-1);
1377 [ + - ]: 13597 : continue;
1378 : : }
1379 : :
1380 [ + - ][ + - ]: 13009 : o->newline() << "width = ";
1381 [ + + ]: 13009 : if (c->widthtype == print_format::width_dynamic)
1382 [ + - ][ + - ]: 17 : o->line() << "clamp_t(int, l->arg" << arg_ix++
1383 [ + - ]: 17 : << ", 0, end - str + 1);";
1384 [ + + ]: 12992 : else if (c->widthtype == print_format::width_static)
1385 [ + - ][ + - ]: 744 : o->line() << "clamp_t(int, " << c->width
1386 [ + - ]: 744 : << ", 0, end - str + 1);";
1387 : : else
1388 [ + - ]: 12248 : o->line() << "-1;";
1389 : :
1390 [ + - ][ + - ]: 13009 : o->newline() << "precision = ";
1391 [ + + ]: 13009 : if (c->prectype == print_format::prec_dynamic)
1392 [ + - ][ + - ]: 14 : o->line() << "clamp_t(int, l->arg" << arg_ix++
1393 [ + - ]: 14 : << ", 0, end - str + 1);";
1394 [ + + ]: 12995 : else if (c->prectype == print_format::prec_static)
1395 [ + - ][ + - ]: 53 : o->line() << "clamp_t(int, " << c->precision
1396 [ + - ]: 53 : << ", 0, end - str + 1);";
1397 : : else
1398 [ + - ]: 12942 : o->line() << "-1;";
1399 : :
1400 [ + - ][ + - ]: 13009 : string value = "l->arg" + lex_cast(arg_ix++);
[ + - ]
1401 [ + + + + : 13009 : switch (c->type)
+ + - ]
1402 : : {
1403 : : case print_format::conv_pointer:
1404 : : // NB: stap < 1.3 had odd %p behavior... see _stp_vsnprintf
1405 [ + - ][ + + ]: 1858 : if (strverscmp(session->compatible.c_str(), "1.3") < 0)
1406 : : {
1407 [ + - ][ + - ]: 12 : o->newline() << "ptr_value = " << value << ";";
[ + - ][ + - ]
1408 [ + - ][ + - ]: 12 : o->newline() << "if (width == -1)";
1409 [ + - ][ + - ]: 12 : o->newline(1) << "width = 2 + 2 * sizeof(void*);";
1410 [ + - ][ + - ]: 12 : o->newline(-1) << "precision = width - 2;";
1411 [ + + ]: 12 : if (!c->test_flag(print_format::fmt_flag_left))
1412 [ + - ][ + - ]: 8 : o->newline() << "precision = min_t(int, precision, 2 * sizeof(void*));";
1413 [ + - ][ + - ]: 12 : o->newline() << "str = number(str, end, ptr_value, "
1414 [ + - ][ + - ]: 12 : << c->base << ", width, precision, " << c->flags << ");";
[ + - ][ + - ]
1415 : 12 : break;
1416 : : }
1417 : : // else fall-through to conv_number
1418 : : case print_format::conv_number:
1419 [ + - ][ + - ]: 10398 : o->newline() << "str = number(str, end, " << value << ", "
[ + - ][ + - ]
1420 [ + - ][ + - ]: 10398 : << c->base << ", width, precision, " << c->flags << ");";
[ + - ][ + - ]
1421 : 10398 : break;
1422 : :
1423 : : case print_format::conv_char:
1424 [ + - ][ + - ]: 40 : o->newline() << "str = _stp_vsprint_char(str, end, "
1425 [ + - ][ + - ]: 40 : << value << ", width, " << c->flags << ");";
[ + - ][ + - ]
1426 : 40 : break;
1427 : :
1428 : : case print_format::conv_string:
1429 [ + - ][ + - ]: 2402 : o->newline() << "str = _stp_vsprint_memory(str, end, "
1430 [ + - ][ + - ]: 2402 : << value << ", width, precision, 's', "
1431 [ + - ][ + - ]: 2402 : << c->flags << ");";
1432 : 2402 : break;
1433 : :
1434 : : case print_format::conv_memory:
1435 : : case print_format::conv_memory_hex:
1436 [ + - ][ + - ]: 72 : o->newline() << "str = _stp_vsprint_memory(str, end, "
1437 [ + - ][ + - ]: 72 : << "(const char*)(intptr_t)" << value
1438 [ + - ]: 72 : << ", width, precision, '"
1439 [ + + ][ + - ]: 72 : << ((c->type == print_format::conv_memory) ? "m" : "M")
1440 [ + - ][ + - ]: 72 : << "', " << c->flags << ");";
[ + - ]
1441 [ + - ][ + - ]: 72 : o->newline() << "if (unlikely(str == NULL)) {";
1442 [ + - ]: 72 : o->indent(1);
1443 [ + + ]: 72 : if (print_to_stream)
1444 [ + - ][ + - ]: 24 : o->newline() << "_stp_unreserve_bytes(num_bytes);";
1445 [ + - ][ + - ]: 72 : o->newline() << "return;";
1446 [ + - ][ + - ]: 72 : o->newline(-1) << "}";
1447 : 72 : break;
1448 : :
1449 : : case print_format::conv_binary:
1450 [ + - ][ + - ]: 85 : o->newline() << "str = _stp_vsprint_binary(str, end, "
1451 [ + - ][ + - ]: 85 : << value << ", width, precision, "
1452 [ + - ][ + - ]: 85 : << c->flags << ");";
1453 : 85 : break;
1454 : :
1455 : : default:
1456 : 0 : assert(false); // XXX
1457 : : break;
1458 : : }
1459 [ + - ]: 13009 : }
1460 : :
1461 [ + + ]: 4783 : if (!print_to_stream)
1462 : : {
1463 [ + - ][ + - ]: 3471 : o->newline() << "if (str <= end)";
1464 [ + - ][ + - ]: 3471 : o->newline(1) << "*str = '\\0';";
1465 [ + - ][ + - ]: 3471 : o->newline(-1) << "else";
1466 [ + - ][ + - ]: 3471 : o->newline(1) << "*end = '\\0';";
1467 [ + - ]: 3471 : o->indent(-1);
1468 : : }
1469 : :
1470 [ + - ][ + - ]: 4783 : o->newline(-1) << "}";
1471 : :
1472 [ + - ][ + - ]: 4783 : o->newline(-1) << "}";
1473 [ + - ]: 4783 : }
1474 [ + - ][ + - ]: 645 : o->newline() << "#endif // STP_LEGACY_PRINT";
1475 : 645 : }
1476 : :
1477 : :
1478 : : void
1479 : 1734 : c_unparser::emit_global_param (vardecl *v)
1480 : : {
1481 [ + - ]: 1734 : string vn = c_globalname (v->name);
1482 : :
1483 : : // XXX: No module parameters with dyninst.
1484 [ - + ]: 1734 : if (session->runtime_usermode_p())
1485 : 1734 : return;
1486 : :
1487 : : // NB: systemtap globals can collide with linux macros,
1488 : : // e.g. VM_FAULT_MAJOR. We want the parameter name anyway. This
1489 : : // #undef is spit out at the end of the C file, so that removing the
1490 : : // definition won't affect any other embedded-C or generated code.
1491 : : // XXX: better not have a global variable named module_param_named etc.!
1492 [ + - ][ + - ]: 1734 : o->newline() << "#undef " << v->name; // avoid colliding with non-mangled name
[ + - ]
1493 : :
1494 : : // Emit module_params for this global, if its type is convenient.
1495 [ + + ][ + + ]: 1734 : if (v->arity == 0 && v->type == pe_long)
1496 : : {
1497 [ + - ][ + - ]: 298 : o->newline() << "module_param_named (" << v->name << ", "
[ + - ][ + - ]
1498 [ + - ][ + - ]: 298 : << "global(" << vn << "), int64_t, 0);";
[ + - ]
1499 : : }
1500 [ + + ][ + + ]: 1436 : else if (v->arity == 0 && v->type == pe_string)
1501 : : {
1502 : : // NB: no special copying is needed.
1503 [ + - ][ + - ]: 54 : o->newline() << "module_param_string (" << v->name << ", "
[ + - ][ + - ]
1504 [ + - ][ + - ]: 1734 : << "global(" << vn << "), MAXSTRINGLEN, 0);";
[ + - ]
1505 [ + - ][ + - ]: 1734 : }
1506 : : }
1507 : :
1508 : :
1509 : : void
1510 : 1734 : c_unparser::emit_global (vardecl *v)
1511 : : {
1512 [ + - ]: 1734 : string vn = c_globalname (v->name);
1513 : :
1514 [ + - ]: 1734 : string type;
1515 [ + + ]: 1734 : if (v->arity > 0)
1516 [ + + ][ + - ]: 1311 : type = (v->type == pe_stats) ? "PMAP" : "MAP";
1517 : : else
1518 [ + - ][ + - ]: 423 : type = c_typename (v->type);
[ + - ]
1519 : :
1520 [ - + ]: 1734 : if (session->runtime_usermode_p())
1521 : : {
1522 : : // In stapdyn mode, the stat/map/pmap pointers are stored as offptr_t in
1523 : : // shared memory. However, we can keep a little type safety by emitting
1524 : : // FOO_typed and using typeof(FOO_typed) in the global() macros.
1525 [ # # ][ # # ]: 0 : bool offptr_p = (v->type == pe_stats) || (v->arity > 0);
1526 [ # # ][ # # ]: 0 : string stored_type = offptr_p ? "offptr_t" : type;
[ # # ][ # # ]
[ # # ]
1527 : :
1528 : : // NB: The casted_type is in the unused side of a __builtin_choose_expr
1529 : : // for non-offptr types, so it doesn't matter what we put for them, as
1530 : : // long as it passes syntax long enough for gcc to choose the other expr.
1531 [ # # ][ # # ]: 0 : string casted_type = offptr_p ? type : "void*";
[ # # ][ # # ]
[ # # ]
1532 : :
1533 [ # # ][ # # ]: 0 : o->newline() << "union {";
1534 [ # # ][ # # ]: 0 : o->newline(1) << casted_type << " " << vn << "_typed;";
[ # # ][ # # ]
[ # # ]
1535 [ # # ][ # # ]: 0 : o->newline() << stored_type << " " << vn << ";";
[ # # ][ # # ]
[ # # ]
1536 [ # # ][ # # ]: 0 : o->newline(-1) << "};";
[ # # ][ # # ]
1537 : : }
1538 : : else
1539 [ + - ][ + - ]: 1734 : o->newline() << type << " " << vn << ";";
[ + - ][ + - ]
[ + - ]
1540 : :
1541 [ + - ][ + - ]: 1734 : o->newline() << "rwlock_t " << vn << "_lock;";
[ + - ][ + - ]
1542 [ + - ][ + - ]: 1734 : o->newline() << "#ifdef STP_TIMING";
1543 [ + - ][ + - ]: 1734 : o->newline() << "atomic_t " << vn << "_lock_skip_count;";
[ + - ][ + - ]
1544 [ + - ][ + - ]: 1734 : o->newline() << "#endif\n";
[ + - ][ + - ]
1545 : 1734 : }
1546 : :
1547 : :
1548 : : void
1549 : 1734 : c_unparser::emit_global_init (vardecl *v)
1550 : : {
1551 : : // We can only statically initialize some scalars.
1552 [ + + ][ + + ]: 1734 : if (v->arity == 0 && v->init)
1553 : : {
1554 [ + - ][ + - ]: 121 : o->newline() << "." << c_globalname (v->name) << " = ";
1555 : 121 : v->init->visit(this);
1556 : 121 : o->line() << ",";
1557 : : }
1558 : : // The lock and lock_skip_count are handled in emit_module_init.
1559 : 1734 : }
1560 : :
1561 : :
1562 : :
1563 : : void
1564 : 6377 : c_unparser::emit_functionsig (functiondecl* v)
1565 : : {
1566 [ + - ]: 12754 : o->newline() << "static void " << c_funcname(v->name)
1567 [ + - ]: 6377 : << " (struct context * __restrict__ c);";
1568 : 6377 : }
1569 : :
1570 : :
1571 : : void
1572 : 644 : c_unparser::emit_module_init ()
1573 : : {
1574 [ + - ]: 644 : vector<derived_probe_group*> g = all_session_groups (*session);
1575 [ + + ]: 1556 : for (unsigned i=0; i<g.size(); i++)
1576 : : {
1577 [ + - ]: 912 : g[i]->emit_module_decls (*session);
1578 [ + - ]: 912 : o->assert_0_indent();
1579 : : }
1580 : :
1581 [ + - ]: 644 : o->newline();
1582 [ + - ][ + - ]: 644 : o->newline() << "static int systemtap_module_init (void) {";
1583 [ + - ][ + - ]: 644 : o->newline(1) << "int rc = 0;";
1584 [ + - ][ + - ]: 644 : o->newline() << "int cpu;";
1585 [ + - ][ + - ]: 644 : o->newline() << "int i=0, j=0;"; // for derived_probe_group use
1586 [ + - ][ + - ]: 644 : o->newline() << "const char *probe_point = \"\";";
1587 : :
1588 : : // NB: This block of initialization only makes sense in kernel
1589 [ + - ]: 644 : if (! session->runtime_usermode_p())
1590 : : {
1591 : : // XXX Plus, most of this code is completely static, so it probably should
1592 : : // move into the runtime, where kernel/dyninst is more easily separated.
1593 : :
1594 : : // Compare actual and targeted kernel releases/machines. Sometimes
1595 : : // one may install the incorrect debuginfo or -devel RPM, and try to
1596 : : // run a probe compiled for a different version. Catch this early,
1597 : : // just in case modversions didn't.
1598 [ + - ][ + - ]: 644 : o->newline() << "{";
1599 [ + - ][ + - ]: 644 : o->newline(1) << "const char* release = UTS_RELEASE;";
1600 [ + - ][ + - ]: 644 : o->newline() << "#ifdef STAPCONF_GENERATED_COMPILE";
1601 [ + - ][ + - ]: 644 : o->newline() << "const char* version = UTS_VERSION;";
1602 [ + - ][ + - ]: 644 : o->newline() << "#endif";
1603 : :
1604 : : // NB: This UTS_RELEASE compile-time macro directly checks only that
1605 : : // the compile-time kbuild tree matches the compile-time debuginfo/etc.
1606 : : // It does not check the run time kernel value. However, this is
1607 : : // probably OK since the kbuild modversions system aims to prevent
1608 : : // mismatches between kbuild and runtime versions at module-loading time.
1609 : :
1610 : : // o->newline() << "const char* machine = UTS_MACHINE;";
1611 : : // NB: We could compare UTS_MACHINE too, but on x86 it lies
1612 : : // (UTS_MACHINE=i386, but uname -m is i686). Sheesh.
1613 : :
1614 [ + - ][ + - ]: 644 : o->newline() << "if (strcmp (release, "
1615 [ + - ][ + - ]: 644 : << lex_cast_qstring (session->kernel_release) << ")) {";
[ + - ][ + - ]
1616 [ + - ][ + - ]: 644 : o->newline(1) << "_stp_error (\"module release mismatch (%s vs %s)\", "
1617 [ + - ]: 644 : << "release, "
1618 [ + - ][ + - ]: 1288 : << lex_cast_qstring (session->kernel_release)
[ + - ]
1619 [ + - ]: 644 : << ");";
1620 [ + - ][ + - ]: 644 : o->newline() << "rc = -EINVAL;";
1621 [ + - ][ + - ]: 644 : o->newline(-1) << "}";
1622 : :
1623 [ + - ][ + - ]: 644 : o->newline() << "#ifdef STAPCONF_GENERATED_COMPILE";
1624 [ + - ][ + - ]: 644 : o->newline() << "if (strcmp (utsname()->version, version)) {";
1625 [ + - ][ + - ]: 644 : o->newline(1) << "_stp_error (\"module version mismatch (%s vs %s), release %s\", "
1626 [ + - ]: 644 : << "version, "
1627 [ + - ]: 644 : << "utsname()->version, "
1628 [ + - ]: 644 : << "release"
1629 [ + - ]: 644 : << ");";
1630 [ + - ][ + - ]: 644 : o->newline() << "rc = -EINVAL;";
1631 [ + - ][ + - ]: 644 : o->newline(-1) << "}";
1632 [ + - ][ + - ]: 644 : o->newline() << "#endif";
1633 : :
1634 : : // perform buildid-based checking if able
1635 [ + - ][ + - ]: 644 : o->newline() << "if (_stp_module_check()) rc = -EINVAL;";
1636 : :
1637 : : // Perform checking on the user's credentials vs those required to load/run this module.
1638 [ + - ][ + - ]: 644 : o->newline() << "if (_stp_privilege_credentials == 0) {";
1639 [ + - ][ + - ]: 644 : o->newline(1) << "if (STP_PRIVILEGE_CONTAINS(STP_PRIVILEGE, STP_PR_STAPDEV) ||";
1640 [ + - ][ + - ]: 644 : o->newline() << " STP_PRIVILEGE_CONTAINS(STP_PRIVILEGE, STP_PR_STAPUSR)) {";
1641 [ + - ][ + - ]: 644 : o->newline(1) << "_stp_privilege_credentials = STP_PRIVILEGE;";
1642 [ + - ][ + - ]: 644 : o->newline() << "#ifdef DEBUG_PRIVILEGE";
1643 [ + - ][ + - ]: 644 : o->newline(1) << "_dbug(\"User's privilege credentials default to %s\\n\",";
1644 [ + - ][ + - ]: 644 : o->newline() << " privilege_to_text(_stp_privilege_credentials));";
1645 [ + - ][ + - ]: 644 : o->newline(-1) << "#endif";
1646 [ + - ][ + - ]: 644 : o->newline(-1) << "}";
1647 [ + - ][ + - ]: 644 : o->newline() << "else {";
1648 [ + - ][ + - ]: 644 : o->newline(1) << "_stp_error (\"Unable to verify that you have the required privilege credentials to run this module (%s required). You must use staprun version 1.7 or higher.\",";
1649 [ + - ][ + - ]: 644 : o->newline() << " privilege_to_text(STP_PRIVILEGE));";
1650 [ + - ][ + - ]: 644 : o->newline() << "rc = -EINVAL;";
1651 [ + - ][ + - ]: 644 : o->newline(-1) << "}";
1652 [ + - ][ + - ]: 644 : o->newline(-1) << "}";
1653 [ + - ][ + - ]: 644 : o->newline() << "else {";
1654 [ + - ][ + - ]: 644 : o->newline(1) << "#ifdef DEBUG_PRIVILEGE";
1655 [ + - ][ + - ]: 644 : o->newline(1) << "_dbug(\"User's privilege credentials provided as %s\\n\",";
1656 [ + - ][ + - ]: 644 : o->newline() << " privilege_to_text(_stp_privilege_credentials));";
1657 [ + - ][ + - ]: 644 : o->newline(-1) << "#endif";
1658 [ + - ][ + - ]: 644 : o->newline() << "if (! STP_PRIVILEGE_CONTAINS(_stp_privilege_credentials, STP_PRIVILEGE)) {";
1659 [ + - ][ + - ]: 644 : o->newline(1) << "_stp_error (\"Your privilege credentials (%s) are insufficient to run this module (%s required).\",";
1660 [ + - ][ + - ]: 644 : o->newline () << " privilege_to_text(_stp_privilege_credentials), privilege_to_text(STP_PRIVILEGE));";
1661 [ + - ][ + - ]: 644 : o->newline() << "rc = -EINVAL;";
1662 [ + - ][ + - ]: 644 : o->newline(-1) << "}";
1663 [ + - ][ + - ]: 644 : o->newline(-1) << "}";
1664 : :
1665 [ + - ][ + - ]: 644 : o->newline(-1) << "}";
1666 : :
1667 [ + - ][ + - ]: 644 : o->newline() << "if (rc) goto out;";
1668 : : }
1669 : :
1670 : : // Now that kernel version and permissions are correct,
1671 : : // initialize the global session states before anything else.
1672 [ + - ][ + - ]: 644 : o->newline() << "rc = stp_session_init();";
1673 [ + - ][ + - ]: 644 : o->newline() << "if (rc) {";
1674 [ + - ][ + - ]: 644 : o->newline(1) << "_stp_error (\"couldn't initialize the main session (rc %d)\", rc);";
1675 [ + - ][ + - ]: 644 : o->newline() << "goto out;";
1676 [ + - ][ + - ]: 644 : o->newline(-1) << "}";
1677 : :
1678 : : // initialize gettimeofday (if needed)
1679 [ + - ][ + - ]: 644 : o->newline() << "#ifdef STAP_NEED_GETTIMEOFDAY";
1680 [ + - ][ + - ]: 644 : o->newline() << "rc = _stp_init_time();"; // Kick off the Big Bang.
1681 [ + - ][ + - ]: 644 : o->newline() << "if (rc) {";
1682 [ + - ][ + - ]: 644 : o->newline(1) << "_stp_error (\"couldn't initialize gettimeofday\");";
1683 [ + - ][ + - ]: 644 : o->newline() << "goto out;";
1684 [ + - ][ + - ]: 644 : o->newline(-1) << "}";
1685 [ + - ][ + - ]: 644 : o->newline() << "#endif";
1686 : :
1687 : : // NB: we don't need per-_stp_module task_finders, since a single common one
1688 : : // set up in runtime/sym.c's _stp_sym_init() will scan through all _stp_modules. XXX - check this!
1689 [ + - ][ + - ]: 644 : o->newline() << "(void) probe_point;";
1690 [ + - ][ + - ]: 644 : o->newline() << "(void) i;";
1691 [ + - ][ + - ]: 644 : o->newline() << "(void) j;";
1692 [ + - ][ + - ]: 644 : o->newline() << "atomic_set (session_state(), STAP_SESSION_STARTING);";
1693 : : // This signals any other probes that may be invoked in the next little
1694 : : // while to abort right away. Currently running probes are allowed to
1695 : : // terminate. These may set STAP_SESSION_ERROR!
1696 : :
1697 : : // Allocate context structures.
1698 [ + - ][ + - ]: 644 : o->newline() << "rc = _stp_runtime_contexts_alloc();";
1699 [ + - ][ + - ]: 644 : o->newline() << "if (rc != 0)";
1700 [ + - ][ + - ]: 644 : o->newline(1) << "goto out;";
1701 [ + - ]: 644 : o->indent(-1);
1702 : :
1703 [ + + ]: 2378 : for (unsigned i=0; i<session->globals.size(); i++)
1704 : : {
1705 : 1734 : vardecl* v = session->globals[i];
1706 [ + + ]: 1734 : if (v->index_types.size() > 0)
1707 [ + - ][ + - ]: 1311 : o->newline() << getmap (v).init();
[ + - ][ + - ]
[ + - ][ + - ]
1708 [ + + ][ - + ]: 423 : else if (v->init && session->runtime_usermode_p())
[ - + ]
1709 [ # # ][ # # ]: 0 : c_assign(getvar (v).value(), v->init, "global initialization");
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1710 : : else
1711 [ + - ][ + - ]: 423 : o->newline() << getvar (v).init();
[ + - ][ + - ]
[ + - ][ + - ]
1712 : : // NB: in case of failure of allocation, "rc" will be set to non-zero.
1713 : : // Allocation can in general continue.
1714 : :
1715 [ + - ][ + - ]: 1734 : o->newline() << "if (rc) {";
1716 [ + - ][ + - ]: 1734 : o->newline(1) << "_stp_error (\"global variable '" << v->name << "' allocation failed\");";
[ + - ][ + - ]
1717 [ + - ][ + - ]: 1734 : o->newline() << "goto out;";
1718 [ + - ][ + - ]: 1734 : o->newline(-1) << "}";
1719 : :
1720 [ + - ][ + - ]: 1734 : o->newline() << "global_lock_init(" << c_globalname (v->name) << ");";
[ + - ][ + - ]
[ + - ][ + - ]
1721 [ + - ][ + - ]: 1734 : o->newline() << "#ifdef STP_TIMING";
1722 [ + - ][ + - ]: 1734 : o->newline() << "atomic_set(global_skipped(" << c_globalname (v->name) << "), 0);";
[ + - ][ + - ]
[ + - ][ + - ]
1723 [ + - ][ + - ]: 1734 : o->newline() << "#endif";
1724 : : }
1725 : :
1726 : : // Print a message to the kernel log about this module. This is
1727 : : // intended to help debug problems with systemtap modules.
1728 [ + - ]: 644 : if (! session->runtime_usermode_p())
1729 [ + - ][ + - ]: 644 : o->newline() << "_stp_print_kernel_info("
1730 [ + - ][ + - ]: 644 : << "\"" << VERSION
1731 [ + - ][ + - ]: 644 : << "/" << dwfl_version (NULL) << "\""
[ + - ][ + - ]
1732 [ + - ]: 644 : << ", (num_online_cpus() * sizeof(struct context))"
1733 [ + - ][ + - ]: 644 : << ", " << session->probes.size()
1734 [ + - ]: 644 : << ");";
1735 : :
1736 : : // Run all probe registrations. This actually runs begin probes.
1737 : :
1738 [ + + ]: 1556 : for (unsigned i=0; i<g.size(); i++)
1739 : : {
1740 [ + - ]: 912 : g[i]->emit_module_init (*session);
1741 : : // NB: this gives O(N**2) amount of code, but luckily there
1742 : : // are only seven or eight derived_probe_groups, so it's ok.
1743 [ + - ][ + - ]: 912 : o->newline() << "if (rc) {";
1744 : : // If a probe types's emit_module_init() wants to handle error
1745 : : // messages itself, it should set probe_point to NULL,
1746 [ + - ][ + - ]: 912 : o->newline(1) << "if (probe_point)";
1747 [ + - ][ + - ]: 912 : o->newline(1) << "_stp_error (\"probe %s registration error (rc %d)\", probe_point, rc);";
1748 [ + - ]: 912 : o->indent(-1);
1749 : : // NB: we need to be in the error state so timers can shutdown cleanly,
1750 : : // and so end probes don't run. OTOH, error probes can run.
1751 [ + - ][ + - ]: 912 : o->newline() << "atomic_set (session_state(), STAP_SESSION_ERROR);";
1752 [ + + ]: 912 : if (i>0)
1753 [ + + ]: 610 : for (int j=i-1; j>=0; j--)
1754 [ + - ]: 342 : g[j]->emit_module_exit (*session);
1755 [ + - ][ + - ]: 912 : o->newline() << "goto out;";
1756 [ + - ][ + - ]: 912 : o->newline(-1) << "}";
1757 : : }
1758 : :
1759 : : // All registrations were successful. Consider the system started.
1760 [ + - ][ + - ]: 644 : o->newline() << "if (atomic_read (session_state()) == STAP_SESSION_STARTING)";
1761 : : // NB: only other valid state value is ERROR, in which case we don't
1762 [ + - ][ + - ]: 644 : o->newline(1) << "atomic_set (session_state(), STAP_SESSION_RUNNING);";
1763 : :
1764 : : // Run all post-session starting code.
1765 [ + + ]: 1556 : for (unsigned i=0; i<g.size(); i++)
1766 : : {
1767 [ + - ]: 912 : g[i]->emit_module_post_init (*session);
1768 : : }
1769 [ + - ][ + - ]: 644 : o->newline(-1) << "return 0;";
1770 : :
1771 : : // Error handling path; by now all partially registered probe groups
1772 : : // have been unregistered.
1773 [ + - ][ + - ]: 644 : o->newline(-1) << "out:";
1774 [ + - ]: 644 : o->indent(1);
1775 : :
1776 : : // If any registrations failed, we will need to deregister the globals,
1777 : : // as this is our only chance.
1778 [ + + ]: 2378 : for (unsigned i=0; i<session->globals.size(); i++)
1779 : : {
1780 : 1734 : vardecl* v = session->globals[i];
1781 [ + + ]: 1734 : if (v->index_types.size() > 0)
1782 [ + - ][ + - ]: 1311 : o->newline() << getmap (v).fini();
[ + - ][ + - ]
[ + - ][ + - ]
1783 : : else
1784 [ + - ][ + - ]: 423 : o->newline() << getvar (v).fini();
[ + - ][ + - ]
[ + - ][ + - ]
1785 : : }
1786 : :
1787 : : // For any partially registered/unregistered kernel facilities.
1788 [ + - ][ + - ]: 644 : o->newline() << "atomic_set (session_state(), STAP_SESSION_STOPPED);";
1789 [ + - ][ + - ]: 644 : o->newline() << "#ifdef STAPCONF_SYNCHRONIZE_SCHED";
1790 [ + - ][ + - ]: 644 : o->newline() << "synchronize_sched();";
1791 [ + - ][ + - ]: 644 : o->newline() << "#endif";
1792 : :
1793 : : // In case gettimeofday was started, it needs to be stopped
1794 [ + - ][ + - ]: 644 : o->newline() << "#ifdef STAP_NEED_GETTIMEOFDAY";
1795 [ + - ][ + - ]: 644 : o->newline() << " _stp_kill_time();"; // An error is no cause to hurry...
1796 [ + - ][ + - ]: 644 : o->newline() << "#endif";
1797 : :
1798 : : // Free up the context memory after an error too
1799 [ + - ][ + - ]: 644 : o->newline() << "_stp_runtime_contexts_free();";
1800 : :
1801 [ + - ][ + - ]: 644 : o->newline() << "return rc;";
1802 [ + - ][ + - ]: 644 : o->newline(-1) << "}\n";
[ + - ]
1803 : 644 : }
1804 : :
1805 : :
1806 : : void
1807 : 644 : c_unparser::emit_module_refresh ()
1808 : : {
1809 [ + - ][ + - ]: 644 : o->newline() << "static void systemtap_module_refresh (void) {";
1810 [ + - ][ + - ]: 644 : o->newline(1) << "int i=0, j=0;"; // for derived_probe_group use
1811 [ + - ][ + - ]: 644 : o->newline() << "(void) i;";
1812 [ + - ][ + - ]: 644 : o->newline() << "(void) j;";
1813 [ + - ]: 644 : vector<derived_probe_group*> g = all_session_groups (*session);
1814 [ + + ]: 1556 : for (unsigned i=0; i<g.size(); i++)
1815 : : {
1816 [ + - ]: 912 : g[i]->emit_module_refresh (*session);
1817 : : }
1818 [ + - ][ + - ]: 644 : o->newline(-1) << "}\n";
[ + - ]
1819 : 644 : }
1820 : :
1821 : :
1822 : : void
1823 : 644 : c_unparser::emit_module_exit ()
1824 : : {
1825 [ + - ][ + - ]: 644 : o->newline() << "static void systemtap_module_exit (void) {";
1826 : : // rc?
1827 [ + - ][ + - ]: 644 : o->newline(1) << "int i=0, j=0;"; // for derived_probe_group use
1828 [ + - ][ + - ]: 644 : o->newline() << "(void) i;";
1829 [ + - ][ + - ]: 644 : o->newline() << "(void) j;";
1830 : : // If we aborted startup, then everything has been cleaned up already, and
1831 : : // module_exit shouldn't even have been called. But since it might be, let's
1832 : : // beat a hasty retreat to avoid double uninitialization.
1833 [ + - ][ + - ]: 644 : o->newline() << "if (atomic_read (session_state()) == STAP_SESSION_STARTING)";
1834 [ + - ][ + - ]: 644 : o->newline(1) << "return;";
1835 [ + - ]: 644 : o->indent(-1);
1836 : :
1837 [ + - ][ + - ]: 644 : o->newline() << "if (atomic_read (session_state()) == STAP_SESSION_RUNNING)";
1838 : : // NB: only other valid state value is ERROR, in which case we don't
1839 [ + - ][ + - ]: 644 : o->newline(1) << "atomic_set (session_state(), STAP_SESSION_STOPPING);";
1840 [ + - ]: 644 : o->indent(-1);
1841 : : // This signals any other probes that may be invoked in the next little
1842 : : // while to abort right away. Currently running probes are allowed to
1843 : : // terminate. These may set STAP_SESSION_ERROR!
1844 : :
1845 : : // We're processing the derived_probe_group list in reverse
1846 : : // order. This ensures that probes get unregistered in reverse
1847 : : // order of the way they were registered.
1848 [ + - ]: 644 : vector<derived_probe_group*> g = all_session_groups (*session);
1849 [ + - ][ + - ]: 3112 : for (vector<derived_probe_group*>::reverse_iterator i = g.rbegin();
[ + - ][ + + ]
1850 [ + - ]: 1556 : i != g.rend(); i++)
1851 [ + - ][ + - ]: 912 : (*i)->emit_module_exit (*session); // NB: runs "end" probes
1852 : :
1853 : : // But some other probes may have launched too during unregistration.
1854 : : // Let's wait a while to make sure they're all done, done, done.
1855 : :
1856 : : // cargo cult prologue
1857 [ + - ][ + - ]: 644 : o->newline() << "#ifdef STAPCONF_SYNCHRONIZE_SCHED";
1858 [ + - ][ + - ]: 644 : o->newline() << "synchronize_sched();";
1859 [ + - ][ + - ]: 644 : o->newline() << "#endif";
1860 : :
1861 : : // NB: systemtap_module_exit is assumed to be called from ordinary
1862 : : // user context, say during module unload. Among other things, this
1863 : : // means we can sleep a while.
1864 [ + - ][ + - ]: 644 : o->newline() << "_stp_runtime_context_wait();";
1865 : :
1866 : : // cargo cult epilogue
1867 [ + - ][ + - ]: 644 : o->newline() << "atomic_set (session_state(), STAP_SESSION_STOPPED);";
1868 [ + - ][ + - ]: 644 : o->newline() << "#ifdef STAPCONF_SYNCHRONIZE_SCHED";
1869 [ + - ][ + - ]: 644 : o->newline() << "synchronize_sched();";
1870 [ + - ][ + - ]: 644 : o->newline() << "#endif";
1871 : :
1872 : : // XXX: might like to have an escape hatch, in case some probe is
1873 : : // genuinely stuck somehow
1874 : :
1875 [ + + ]: 2378 : for (unsigned i=0; i<session->globals.size(); i++)
1876 : : {
1877 : 1734 : vardecl* v = session->globals[i];
1878 [ + + ]: 1734 : if (v->index_types.size() > 0)
1879 [ + - ][ + - ]: 1311 : o->newline() << getmap (v).fini();
[ + - ][ + - ]
[ + - ][ + - ]
1880 : : else
1881 [ + - ][ + - ]: 423 : o->newline() << getvar (v).fini();
[ + - ][ + - ]
[ + - ][ + - ]
1882 : : }
1883 : :
1884 : : // We're finished with the contexts.
1885 [ + - ][ + - ]: 644 : o->newline() << "_stp_runtime_contexts_free();";
1886 : :
1887 : : // teardown gettimeofday (if needed)
1888 [ + - ][ + - ]: 644 : o->newline() << "#ifdef STAP_NEED_GETTIMEOFDAY";
1889 [ + - ][ + - ]: 644 : o->newline() << " _stp_kill_time();"; // Go to a beach. Drink a beer.
1890 [ + - ][ + - ]: 644 : o->newline() << "#endif";
1891 : :
1892 : : // NB: PR13386 points out that _stp_printf may be called from contexts
1893 : : // without already active preempt disabling, which breaks various uses
1894 : : // of smp_processor_id(). So we temporary block preemption around this
1895 : : // whole printing block. XXX: get_cpu() / put_cpu() may work just as well.
1896 [ + - ][ + - ]: 644 : o->newline() << "preempt_disable();";
1897 : :
1898 : : // print per probe point timing/alibi statistics
1899 [ + - ][ + - ]: 644 : o->newline() << "#if defined(STP_TIMING) || defined(STP_ALIBI)";
1900 [ + - ][ + - ]: 644 : o->newline() << "_stp_printf(\"----- probe hit report: \\n\");";
1901 [ + - ][ + - ]: 644 : o->newline() << "for (i = 0; i < ARRAY_SIZE(stap_probes); ++i) {";
1902 [ + - ][ + - ]: 644 : o->newline(1) << "const struct stap_probe *const p = &stap_probes[i];";
1903 [ + - ][ + - ]: 644 : o->newline() << "#ifdef STP_ALIBI";
1904 [ + - ][ + - ]: 644 : o->newline() << "int alibi = atomic_read(probe_alibi(i));";
1905 [ + - ][ + - ]: 644 : o->newline() << "if (alibi)";
1906 [ + - ][ + - ]: 644 : o->newline(1) << "_stp_printf (\"%s, (%s), hits: %d,%s, index: %d\\n\",";
1907 [ + - ][ + - ]: 644 : o->newline(2) << "p->pp, p->location, alibi, p->derivation, i);";
1908 [ + - ][ + - ]: 644 : o->newline(-3) << "#endif"; // STP_ALIBI
1909 [ + - ][ + - ]: 644 : o->newline() << "#ifdef STP_TIMING";
1910 [ + - ][ + - ]: 644 : o->newline() << "if (likely (probe_timing(i))) {"; // NB: check for null stat object
1911 [ + - ][ + - ]: 644 : o->newline(1) << "struct stat_data *stats = _stp_stat_get (probe_timing(i), 0);";
1912 [ + - ][ + - ]: 644 : o->newline() << "if (stats->count) {";
1913 [ + - ][ + - ]: 644 : o->newline(1) << "int64_t avg = _stp_div64 (NULL, stats->sum, stats->count);";
1914 [ + - ][ + - ]: 644 : o->newline() << "_stp_printf (\"%s, (%s), hits: %lld, "
1915 [ + - ][ + - ]: 644 : << (!session->runtime_usermode_p() ? "cycles" : "nsecs")
1916 [ + - ]: 644 : << ": %lldmin/%lldavg/%lldmax,%s, index: %d\\n\",";
1917 [ + - ][ + - ]: 644 : o->newline(2) << "p->pp, p->location, (long long) stats->count,";
1918 [ + - ][ + - ]: 644 : o->newline() << "(long long) stats->min, (long long) avg, (long long) stats->max,";
1919 [ + - ][ + - ]: 644 : o->newline() << "p->derivation, i);";
1920 [ + - ][ + - ]: 644 : o->newline(-3) << "}";
1921 [ + - ][ + - ]: 644 : o->newline() << "_stp_stat_del (probe_timing(i));";
1922 [ + - ][ + - ]: 644 : o->newline(-1) << "}";
1923 [ + - ][ + - ]: 644 : o->newline() << "#endif"; // STP_TIMING
1924 [ + - ][ + - ]: 644 : o->newline(-1) << "}";
1925 [ + - ][ + - ]: 644 : o->newline() << "_stp_print_flush();";
1926 [ + - ][ + - ]: 644 : o->newline() << "#endif";
1927 : :
1928 : : // print final error/skipped counts if non-zero
1929 [ + - ][ + - ]: 644 : o->newline() << "if (atomic_read (skipped_count()) || "
1930 [ + - ]: 644 : << "atomic_read (error_count()) || "
1931 [ + - ]: 644 : << "atomic_read (skipped_count_reentrant())) {"; // PR9967
1932 [ + - ][ + - ]: 644 : o->newline(1) << "_stp_warn (\"Number of errors: %d, "
1933 [ + - ]: 644 : << "skipped probes: %d\\n\", "
1934 [ + - ]: 644 : << "(int) atomic_read (error_count()), "
1935 [ + - ]: 644 : << "(int) atomic_read (skipped_count()));";
1936 [ + - ][ + - ]: 644 : o->newline() << "#ifdef STP_TIMING";
1937 [ + - ][ + - ]: 644 : o->newline() << "{";
1938 [ + - ][ + - ]: 644 : o->newline(1) << "int ctr;";
1939 [ + + ]: 2378 : for (unsigned i=0; i<session->globals.size(); i++)
1940 : : {
1941 [ + - ]: 1734 : string orig_vn = session->globals[i]->name;
1942 [ + - ]: 1734 : string vn = c_globalname (orig_vn);
1943 [ + - ][ + - ]: 1734 : o->newline() << "ctr = atomic_read (global_skipped(" << vn << "));";
[ + - ][ + - ]
1944 [ + - ][ + - ]: 1734 : o->newline() << "if (ctr) _stp_warn (\"Skipped due to global '%s' lock timeout: %d\\n\", "
1945 [ + - ][ + - ]: 1734 : << lex_cast_qstring(orig_vn) << ", ctr);";
[ + - ][ + - ]
1946 [ + - ][ + - ]: 1734 : }
1947 [ + - ][ + - ]: 644 : o->newline() << "ctr = atomic_read (skipped_count_lowstack());";
1948 [ + - ][ + - ]: 644 : o->newline() << "if (ctr) _stp_warn (\"Skipped due to low stack: %d\\n\", ctr);";
1949 [ + - ][ + - ]: 644 : o->newline() << "ctr = atomic_read (skipped_count_reentrant());";
1950 [ + - ][ + - ]: 644 : o->newline() << "if (ctr) _stp_warn (\"Skipped due to reentrancy: %d\\n\", ctr);";
1951 [ + - ][ + - ]: 644 : o->newline() << "ctr = atomic_read (skipped_count_uprobe_reg());";
1952 [ + - ][ + - ]: 644 : o->newline() << "if (ctr) _stp_warn (\"Skipped due to uprobe register failure: %d\\n\", ctr);";
1953 [ + - ][ + - ]: 644 : o->newline() << "ctr = atomic_read (skipped_count_uprobe_unreg());";
1954 [ + - ][ + - ]: 644 : o->newline() << "if (ctr) _stp_warn (\"Skipped due to uprobe unregister failure: %d\\n\", ctr);";
1955 [ + - ][ + - ]: 644 : o->newline(-1) << "}";
1956 [ + - ][ + - ]: 644 : o->newline () << "#endif";
1957 [ + - ][ + - ]: 644 : o->newline() << "_stp_print_flush();";
1958 [ + - ][ + - ]: 644 : o->newline(-1) << "}";
1959 : :
1960 : : // NB: PR13386 needs to restore preemption-blocking counts
1961 [ + - ][ + - ]: 644 : o->newline() << "preempt_enable_no_resched();";
1962 : :
1963 [ + - ][ + - ]: 644 : o->newline(-1) << "}\n";
[ + - ]
1964 : 644 : }
1965 : :
1966 : :
1967 : : void
1968 : 6377 : c_unparser::emit_function (functiondecl* v)
1969 : : {
1970 [ + - ]: 12754 : o->newline() << "static void " << c_funcname (v->name)
1971 [ + - ]: 6377 : << " (struct context* __restrict__ c) {";
1972 : 6377 : o->indent(1);
1973 : 6377 : this->current_probe = 0;
1974 : 6377 : this->current_function = v;
1975 : 6377 : this->tmpvar_counter = 0;
1976 : 6377 : this->action_counter = 0;
1977 : :
1978 : 6377 : o->newline() << "__label__ out;";
1979 : 6377 : o->newline()
1980 [ + - ][ + - ]: 12754 : << "struct " << c_funcname (v->name) << "_locals * "
1981 [ + - ]: 6377 : << " __restrict__ l = "
1982 [ + - ][ + - ]: 12754 : << "& c->locals[c->nesting+1]." << c_funcname (v->name) // NB: nesting+1
[ + - ][ + - ]
1983 [ + - ]: 6377 : << ";";
1984 : 6377 : o->newline() << "(void) l;"; // make sure "l" is marked used
1985 : 6377 : o->newline() << "#define CONTEXT c";
1986 : 6377 : o->newline() << "#define THIS l";
1987 [ + + ]: 10546 : for (unsigned i = 0; i < v->formal_args.size(); i++) {
1988 [ + - ]: 4169 : o->newline() << c_arg_define(v->formal_args[i]->name); // #define STAP_ARG_foo ...
1989 : : }
1990 [ + + ]: 7152 : for (unsigned i = 0; i < v->locals.size(); i++) {
1991 [ + - ]: 775 : o->newline() << c_arg_define(v->locals[i]->name); // #define STAP_ARG_foo ...
1992 : : }
1993 : : // define STAP_RETVALUE only if the function is non-void
1994 [ + + ]: 6377 : if (v->type != pe_unknown)
1995 : 5764 : o->newline() << "#define STAP_RETVALUE THIS->__retvalue";
1996 : :
1997 : : // set this, in case embedded-c code sets last_error but doesn't otherwise identify itself
1998 [ + - ][ + - ]: 6377 : o->newline() << "c->last_stmt = " << lex_cast_qstring(*v->tok) << ";";
1999 : :
2000 : : // check/increment nesting level
2001 : : // NB: incoming c->nesting level will be -1 (if we're called directly from a probe),
2002 : : // or 0...N (if we're called from another function). Incoming parameters are already
2003 : : // stored in c->locals[c->nesting+1]. See also ::emit_common_header() for more.
2004 : :
2005 : 6377 : o->newline() << "if (unlikely (c->nesting+1 >= MAXNESTING)) {";
2006 : 6377 : o->newline(1) << "c->last_error = ";
2007 : 6377 : o->line() << STAP_T_02;
2008 : 6377 : o->newline() << "return;";
2009 : 6377 : o->newline(-1) << "} else {";
2010 : 6377 : o->newline(1) << "c->nesting ++;";
2011 : 6377 : o->newline(-1) << "}";
2012 : :
2013 : : // initialize locals
2014 : : // XXX: optimization: use memset instead
2015 [ + + ]: 7152 : for (unsigned i=0; i<v->locals.size(); i++)
2016 : : {
2017 [ - + ]: 775 : if (v->locals[i]->index_types.size() > 0) // array?
2018 : 0 : throw semantic_error (_("array locals not supported, missing global declaration?"),
2019 [ # # ][ # # ]: 0 : v->locals[i]->tok);
2020 : :
2021 [ + - ][ + - ]: 775 : o->newline() << getvar (v->locals[i]).init();
[ + - ]
2022 : : }
2023 : :
2024 : : // initialize return value, if any
2025 [ + + ]: 6377 : if (v->type != pe_unknown)
2026 : : {
2027 [ + - ][ + - ]: 5764 : var retvalue = var(this, true, v->type, "__retvalue", false); // not mangled
[ + - ]
2028 [ + - ][ + - ]: 5764 : o->newline() << retvalue.init();
[ + - ][ + - ]
[ + - ]
2029 : : }
2030 : :
2031 : 6377 : o->newline() << "#define return goto out"; // redirect embedded-C return
2032 : 6377 : v->body->visit (this);
2033 : 6377 : o->newline() << "#undef return";
2034 : :
2035 : 6377 : this->current_function = 0;
2036 : :
2037 : 6377 : record_actions(0, v->body->tok, true);
2038 : :
2039 : 6377 : o->newline(-1) << "out:";
2040 : 6377 : o->newline(1) << "if (0) goto out;"; // make sure out: is marked used
2041 : :
2042 : : // Function prologue: this is why we redirect the "return" above.
2043 : : // Decrement nesting level.
2044 : 6377 : o->newline() << "c->nesting --;";
2045 : :
2046 : 6377 : o->newline() << "#undef CONTEXT";
2047 : 6377 : o->newline() << "#undef THIS";
2048 [ + + ]: 10546 : for (unsigned i = 0; i < v->formal_args.size(); i++) {
2049 [ + - ]: 4169 : o->newline() << c_arg_undef(v->formal_args[i]->name); // #undef STAP_ARG_foo
2050 : : }
2051 [ + + ]: 7152 : for (unsigned i = 0; i < v->locals.size(); i++) {
2052 [ + - ]: 775 : o->newline() << c_arg_undef(v->locals[i]->name); // #undef STAP_ARG_foo
2053 : : }
2054 : 6377 : o->newline() << "#undef STAP_RETVALUE";
2055 : 6377 : o->newline(-1) << "}\n";
2056 : 6377 : }
2057 : :
2058 : :
2059 : : #define DUPMETHOD_CALL 0
2060 : : #define DUPMETHOD_ALIAS 0
2061 : : #define DUPMETHOD_RENAME 1
2062 : :
2063 : : void
2064 : 16861 : c_unparser::emit_probe (derived_probe* v)
2065 : : {
2066 : 16861 : this->current_function = 0;
2067 : 16861 : this->current_probe = v;
2068 : 16861 : this->tmpvar_counter = 0;
2069 : 16861 : this->action_counter = 0;
2070 : :
2071 : : // If we about to emit a probe that is exactly the same as another
2072 : : // probe previously emitted, make the second probe just call the
2073 : : // first one.
2074 : : //
2075 : : // Notice we're using the probe body itself instead of the emitted C
2076 : : // probe body to compare probes. We need to do this because the
2077 : : // emitted C probe body has stuff in it like:
2078 : : // c->last_stmt = "identifier 'printf' at foo.stp:<line>:<column>";
2079 : : //
2080 : : // which would make comparisons impossible.
2081 : : //
2082 : : // --------------------------------------------------------------------------
2083 : : // NB: see also c_unparser:emit_common_header(), which deliberately but sadly
2084 : : // duplicates this calculation.
2085 : : // --------------------------------------------------------------------------
2086 : : //
2087 [ + - ]: 16861 : ostringstream oss;
2088 : :
2089 [ + - ]: 16861 : v->print_dupe_stamp (oss);
2090 [ + - ]: 16861 : v->body->print(oss);
2091 : :
2092 : : // Since the generated C changes based on whether or not the probe
2093 : : // needs locks around global variables, this needs to be reflected
2094 : : // here. We don't want to treat as duplicate the handlers of
2095 : : // begin/end and normal probes that differ only in need_global_locks.
2096 [ + - ][ + - ]: 16861 : oss << "# needs_global_locks: " << v->needs_global_locks () << endl;
[ + - ][ + - ]
2097 : :
2098 : : // If an identical probe has already been emitted, just call that
2099 : : // one.
2100 [ + - ][ + - ]: 16861 : if (probe_contents.count(oss.str()) != 0)
[ + - ][ + + ]
2101 : : {
2102 [ + - ][ + - ]: 8291 : string dupe = probe_contents[oss.str()];
[ + - ][ + - ]
2103 : :
2104 : : // NB: Elision of context variable structs is a separate
2105 : : // operation which has already taken place by now.
2106 [ + + ]: 8291 : if (session->verbose > 1)
2107 [ + - ][ + - ]: 33 : clog << _F("%s elided, duplicates %s\n", v->name.c_str(), dupe.c_str());
[ + - ][ + - ]
[ + - ]
2108 : :
2109 : : #if DUPMETHOD_CALL
2110 : : // This one emits a direct call to the first copy.
2111 : : o->newline();
2112 : : o->newline() << "static void " << v->name << " (struct context * __restrict__ c) ";
2113 : : o->newline() << "{ " << dupe << " (c); }";
2114 : : #elif DUPMETHOD_ALIAS
2115 : : // This one defines a function alias, arranging gcc to emit
2116 : : // several equivalent symbols for the same function body.
2117 : : // For some reason, on gcc 4.1, this is twice as slow as
2118 : : // the CALL option.
2119 : : o->newline();
2120 : : o->newline() << "static void " << v->name << " (struct context * __restrict__ c) ";
2121 : : o->line() << "__attribute__ ((alias (\"" << dupe << "\")));";
2122 : : #elif DUPMETHOD_RENAME
2123 : : // This one is sneaky. It emits nothing for duplicate probe
2124 : : // handlers. It instead redirects subsequent references to the
2125 : : // probe handler function to the first copy, *by name*.
2126 [ + - ][ + - ]: 8291 : v->name = dupe;
2127 : : #else
2128 : : #error "Unknown duplicate elimination method"
2129 : : #endif
2130 : : }
2131 : : else // This probe is unique. Remember it and output it.
2132 : : {
2133 [ + - ]: 8570 : o->newline();
2134 [ + - ][ + - ]: 8570 : o->newline() << "static void " << v->name << " (struct context * __restrict__ c) ";
[ + - ][ + - ]
2135 [ + - ]: 8570 : o->line () << "{";
2136 [ + - ]: 8570 : o->indent (1);
2137 : :
2138 [ + - ][ + - ]: 8570 : probe_contents[oss.str()] = v->name;
[ + - ][ + - ]
2139 : :
2140 [ + - ][ + - ]: 8570 : o->newline() << "__label__ out;";
2141 : :
2142 : : // emit static read/write lock decls for global variables
2143 [ + - ]: 8570 : varuse_collecting_visitor vut(*session);
2144 [ + - ][ + + ]: 8570 : if (v->needs_global_locks ())
2145 : : {
2146 [ + - ]: 7673 : v->body->visit (& vut);
2147 [ + - ]: 7673 : emit_lock_decls (vut);
2148 : : }
2149 : :
2150 : : // initialize frame pointer
2151 [ + - ][ + - ]: 8570 : o->newline() << "struct " << v->name << "_locals * __restrict__ l = "
[ + - ][ + - ]
2152 [ + - ][ + - ]: 8570 : << "& c->probe_locals." << v->name << ";";
[ + - ]
2153 [ + - ][ + - ]: 8570 : o->newline() << "(void) l;"; // make sure "l" is marked used
2154 : :
2155 : : // Emit runtime safety net for unprivileged mode.
2156 : : // NB: In usermode, the system restricts our privilege for us.
2157 [ + - ]: 8570 : if (!session->runtime_usermode_p())
2158 [ + - ]: 8570 : v->emit_privilege_assertion (o);
2159 : :
2160 : : // emit probe local initialization block
2161 : :
2162 [ + - ]: 8570 : v->emit_probe_local_init(*this->session, o);
2163 : :
2164 : : // emit all read/write locks for global variables
2165 [ + - ][ + + ]: 8570 : if (v->needs_global_locks ())
2166 [ + - ]: 7673 : emit_locks (vut);
2167 : :
2168 : : // initialize locals
2169 [ + + ]: 23725 : for (unsigned j=0; j<v->locals.size(); j++)
2170 : : {
2171 [ + + ]: 15155 : if (v->locals[j]->synthetic)
2172 : 1256 : continue;
2173 [ - + ]: 13899 : if (v->locals[j]->index_types.size() > 0) // array?
2174 : 0 : throw semantic_error (_("array locals not supported, missing global declaration?"),
2175 [ # # ][ # # ]: 0 : v->locals[j]->tok);
2176 [ + + ]: 13899 : else if (v->locals[j]->type == pe_long)
2177 [ + - ][ + - ]: 13644 : o->newline() << "l->" << c_localname (v->locals[j]->name)
[ + - ][ + - ]
[ + - ]
2178 [ + - ]: 6822 : << " = 0;";
2179 [ + - ]: 7077 : else if (v->locals[j]->type == pe_string)
2180 [ + - ][ + - ]: 14154 : o->newline() << "l->" << c_localname (v->locals[j]->name)
[ + - ][ + - ]
[ + - ]
2181 [ + - ]: 7077 : << "[0] = '\\0';";
2182 : : else
2183 : 0 : throw semantic_error (_("unsupported local variable type"),
2184 [ # # ][ # # ]: 0 : v->locals[j]->tok);
2185 : : }
2186 : :
2187 [ + - ]: 8570 : v->initialize_probe_context_vars (o);
2188 : :
2189 [ + + ]: 8570 : v->body->visit (this);
2190 : :
2191 [ + - ]: 8569 : record_actions(0, v->body->tok, true);
2192 : :
2193 [ + - ][ + - ]: 8569 : o->newline(-1) << "out:";
2194 : : // NB: no need to uninitialize locals, except if arrays/stats can
2195 : : // someday be local
2196 : :
2197 [ + - ]: 8569 : o->indent(1);
2198 [ + - ][ + + ]: 8569 : if (v->needs_global_locks ())
2199 [ + - ]: 7673 : emit_unlocks (vut);
2200 : :
2201 : : // XXX: do this flush only if the body included a
2202 : : // print/printf/etc. routine!
2203 [ + - ][ + - ]: 8569 : o->newline() << "_stp_print_flush();";
2204 [ + - ][ + - ]: 8570 : o->newline(-1) << "}\n";
[ + - ]
2205 : : }
2206 : :
2207 : :
2208 [ + - ]: 16861 : this->current_probe = 0;
2209 : 16860 : }
2210 : :
2211 : :
2212 : : void
2213 : 7673 : c_unparser::emit_lock_decls(const varuse_collecting_visitor& vut)
2214 : : {
2215 : 7673 : unsigned numvars = 0;
2216 : :
2217 [ + + ]: 7673 : if (session->verbose > 1)
2218 : 516 : clog << "probe " << *current_probe->sole_location() << " locks ";
2219 : :
2220 : : // We can only make this static in kernel mode. In stapdyn mode,
2221 : : // the globals and their locks are in shared memory.
2222 : 7673 : o->newline();
2223 [ + - ]: 7673 : if (!session->runtime_usermode_p())
2224 : 7673 : o->line() << "static ";
2225 : 7673 : o->line() << "const struct stp_probe_lock locks[] = {";
2226 : 7673 : o->indent(1);
2227 : :
2228 [ + + ]: 500141 : for (unsigned i = 0; i < session->globals.size(); i++)
2229 : : {
2230 : 492468 : vardecl* v = session->globals[i];
2231 [ + - ][ + - ]: 492468 : bool read_p = vut.read.find(v) != vut.read.end();
2232 [ + - ][ + - ]: 492468 : bool write_p = vut.written.find(v) != vut.written.end();
2233 [ + + ][ + + ]: 492468 : if (!read_p && !write_p) continue;
2234 : :
2235 [ + + ]: 12032 : if (v->type == pe_stats) // read and write locks are flipped
2236 : : // Specifically, a "<<<" to a stats object is considered a
2237 : : // "shared-lock" operation, since it's implicitly done
2238 : : // per-cpu. But a "@op(x)" extraction is an "exclusive-lock"
2239 : : // one, as is a (sorted or unsorted) foreach, so those cases
2240 : : // are excluded by the w & !r condition below.
2241 : : {
2242 [ + - ][ + + ]: 1551 : if (write_p && !read_p) { read_p = true; write_p = false; }
2243 [ + - ][ - + ]: 1551 : else if (read_p && !write_p) { read_p = false; write_p = true; }
2244 : : }
2245 : :
2246 : : // We don't need to read lock "read-mostly" global variables. A
2247 : : // "read-mostly" global variable is only written to within
2248 : : // probes that don't need global variable locking (such as
2249 : : // begin/end probes). If vcv_needs_global_locks doesn't mark
2250 : : // the global as written to, then we don't have to lock it
2251 : : // here to read it safely.
2252 [ + + ][ + + ]: 12032 : if (read_p && !write_p)
2253 : : {
2254 [ + + ]: 3748 : if (vcv_needs_global_locks.written.find(v)
2255 [ + - ][ + - ]: 3748 : == vcv_needs_global_locks.written.end())
2256 : 2172 : continue;
2257 : : }
2258 : :
2259 [ + - ][ + - ]: 9860 : o->newline() << "{";
2260 [ + - ][ + - ]: 9860 : o->newline(1) << ".lock = global_lock(" + c_globalname(v->name) + "),";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
2261 [ + - ][ + - ]: 9860 : o->newline() << ".write_p = " << (write_p ? 1 : 0) << ",";
[ + + ][ + - ]
[ + - ]
2262 [ + - ][ + - ]: 9860 : o->newline() << "#ifdef STP_TIMING";
2263 [ + - ][ + - ]: 9860 : o->newline() << ".skipped = global_skipped(" << c_globalname (v->name) << "),";
[ + - ][ + - ]
[ + - ][ + - ]
2264 [ + - ][ + - ]: 9860 : o->newline() << "#endif";
2265 [ + - ][ + - ]: 9860 : o->newline(-1) << "},";
2266 : :
2267 : 9860 : numvars ++;
2268 [ + + ]: 9860 : if (session->verbose > 1)
2269 [ + - ][ + - ]: 507 : clog << v->name << "[" << (read_p ? "r" : "")
[ + - ][ + - ]
2270 [ + - ][ + - ]: 492468 : << (write_p ? "w" : "") << "] ";
[ + - ]
2271 : : }
2272 : :
2273 : 7673 : o->newline(-1) << "};";
2274 : :
2275 [ + + ]: 7673 : if (session->verbose > 1)
2276 : : {
2277 [ + + ]: 516 : if (!numvars)
2278 : 9 : clog << _("nothing");
2279 : 516 : clog << endl;
2280 : : }
2281 : 7673 : }
2282 : :
2283 : :
2284 : : void
2285 : 7673 : c_unparser::emit_locks(const varuse_collecting_visitor&)
2286 : : {
2287 : 7673 : o->newline() << "if (!stp_lock_probe(locks, ARRAY_SIZE(locks)))";
2288 : 7673 : o->newline(1) << "return;";
2289 : 7673 : o->indent(-1);
2290 : 7673 : }
2291 : :
2292 : :
2293 : : void
2294 : 7673 : c_unparser::emit_unlocks(const varuse_collecting_visitor&)
2295 : : {
2296 : 7673 : o->newline() << "stp_unlock_probe(locks, ARRAY_SIZE(locks));";
2297 : 7673 : }
2298 : :
2299 : :
2300 : : void
2301 : 23883 : c_unparser::collect_map_index_types(vector<vardecl *> const & vars,
2302 : : set< pair<vector<exp_type>, exp_type> > & types)
2303 : : {
2304 [ + + ]: 45881 : for (unsigned i = 0; i < vars.size(); ++i)
2305 : : {
2306 : 21998 : vardecl *v = vars[i];
2307 [ + + ]: 21998 : if (v->arity > 0)
2308 : : {
2309 [ + - ][ + - ]: 1311 : types.insert(make_pair(v->index_types, v->type));
[ + - ]
2310 : : }
2311 : : }
2312 : 23883 : }
2313 : :
2314 : : string
2315 : 327 : mapvar::value_typename(exp_type e)
2316 : : {
2317 [ + + + - ]: 327 : switch (e)
2318 : : {
2319 : : case pe_long:
2320 [ + - ]: 162 : return "INT64";
2321 : : case pe_string:
2322 [ + - ]: 81 : return "STRING";
2323 : : case pe_stats:
2324 [ + - ]: 84 : return "STAT";
2325 : : default:
2326 [ # # ][ # # ]: 327 : throw semantic_error(_("array type is neither string nor long"));
2327 : : }
2328 : : }
2329 : :
2330 : : string
2331 : 668 : mapvar::key_typename(exp_type e)
2332 : : {
2333 [ + + - ]: 668 : switch (e)
2334 : : {
2335 : : case pe_long:
2336 [ + - ]: 423 : return "INT64";
2337 : : case pe_string:
2338 [ + - ]: 245 : return "STRING";
2339 : : default:
2340 [ # # ][ # # ]: 668 : throw semantic_error(_("array key is neither string nor long"));
2341 : : }
2342 : : }
2343 : :
2344 : : string
2345 : 0 : mapvar::shortname(exp_type e)
2346 : : {
2347 [ # # # ]: 0 : switch (e)
2348 : : {
2349 : : case pe_long:
2350 [ # # ]: 0 : return "i";
2351 : : case pe_string:
2352 [ # # ]: 0 : return "s";
2353 : : default:
2354 [ # # ][ # # ]: 0 : throw semantic_error(_("array type is neither string nor long"));
2355 : : }
2356 : : }
2357 : :
2358 : :
2359 : : void
2360 : 645 : c_unparser::emit_map_type_instantiations ()
2361 : : {
2362 [ + - ]: 645 : set< pair<vector<exp_type>, exp_type> > types;
2363 : :
2364 [ + - ]: 645 : collect_map_index_types(session->globals, types);
2365 : :
2366 [ + + ]: 17506 : for (unsigned i = 0; i < session->probes.size(); ++i)
2367 [ + - ]: 16861 : collect_map_index_types(session->probes[i]->locals, types);
2368 : :
2369 [ + - ][ + - ]: 7022 : for (map<string,functiondecl*>::iterator it = session->functions.begin(); it != session->functions.end(); it++)
[ + + ]
2370 [ + - ][ + - ]: 6377 : collect_map_index_types(it->second->locals, types);
2371 : :
2372 [ + - ][ + + ]: 645 : if (!types.empty())
2373 [ + - ][ + - ]: 182 : o->newline() << "#include \"alloc.c\"";
2374 : :
2375 [ + - ][ + + ]: 1944 : for (set< pair<vector<exp_type>, exp_type> >::const_iterator i = types.begin();
2376 [ + - ]: 972 : i != types.end(); ++i)
2377 : : {
2378 [ + - ][ + - ]: 327 : o->newline() << "#define VALUE_TYPE " << mapvar::value_typename(i->second);
[ + - ][ + - ]
[ + - ][ + - ]
2379 [ + - ][ + + ]: 995 : for (unsigned j = 0; j < i->first.size(); ++j)
2380 : : {
2381 [ + - ][ + - ]: 668 : string ktype = mapvar::key_typename(i->first.at(j));
[ + - ]
2382 [ + - ][ + - ]: 668 : o->newline() << "#define KEY" << (j+1) << "_TYPE " << ktype;
[ + - ][ + - ]
[ + - ]
2383 [ + - ]: 668 : }
2384 : : /* For statistics, flag map-gen to pull in nested pmap-gen too. */
2385 [ + - ][ + + ]: 327 : if (i->second == pe_stats)
2386 [ + - ][ + - ]: 84 : o->newline() << "#define MAP_DO_PMAP 1";
2387 [ + - ][ + - ]: 327 : o->newline() << "#include \"map-gen.c\"";
2388 [ + - ][ + - ]: 327 : o->newline() << "#undef MAP_DO_PMAP";
2389 [ + - ][ + - ]: 327 : o->newline() << "#undef VALUE_TYPE";
2390 [ + - ][ + + ]: 995 : for (unsigned j = 0; j < i->first.size(); ++j)
2391 : : {
2392 [ + - ][ + - ]: 668 : o->newline() << "#undef KEY" << (j+1) << "_TYPE";
[ + - ][ + - ]
2393 : : }
2394 : : }
2395 : :
2396 [ + - ][ + + ]: 645 : if (!types.empty())
2397 [ + - ][ + - ]: 645 : o->newline() << "#include \"map.c\"";
[ + - ]
2398 : :
2399 : 645 : };
2400 : :
2401 : :
2402 : : string
2403 : 126963 : c_unparser::c_typename (exp_type e)
2404 : : {
2405 [ + + + - ]: 126963 : switch (e)
2406 : : {
2407 [ + - ]: 85923 : case pe_long: return string("int64_t");
2408 [ + - ]: 40969 : case pe_string: return string("string_t");
2409 [ + - ]: 71 : case pe_stats: return string("Stat");
2410 : : case pe_unknown:
2411 : : default:
2412 [ # # ][ # # ]: 126963 : throw semantic_error (_("cannot expand unknown type"));
2413 : : }
2414 : : }
2415 : :
2416 : :
2417 : : // XXX: the below is just for the sake of example; it's possibly
2418 : : // better to expose the hash function in hash.cxx
2419 : :
2420 : : // unsigned int
2421 : : // do_hash (const char *e)
2422 : : // {
2423 : : // unsigned int foo = 0;
2424 : : // while (*e) {
2425 : : // foo *= 101; foo += *e; e++;
2426 : : // }
2427 : : // return foo;
2428 : : // }
2429 : :
2430 : :
2431 : : string
2432 : 105478 : c_unparser::c_localname (const string& e, bool mangle_oldstyle)
2433 : : {
2434 [ + + ][ + + ]: 105478 : if (strverscmp(session->compatible.c_str(), "1.8") < 0 || mangle_oldstyle)
[ + + ]
2435 : 20 : return e; // old mangling behaviour
2436 : : else
2437 : : // XXX: we may wish to invent and/or test other mangling schemes, e.g.:
2438 : : // return "l_" + e + "_" + lex_cast(do_hash(e.c_str()));
2439 : 105478 : return "l_" + e;
2440 : : }
2441 : :
2442 : :
2443 : : string
2444 : 67006 : c_unparser::c_globalname (const string& e)
2445 : : {
2446 : : // XXX uncomment to test custom mangling:
2447 : : // return "s_" + e + "_" + lex_cast(do_hash(e.c_str()));
2448 : 67006 : return "s_" + e;
2449 : : }
2450 : :
2451 : :
2452 : : string
2453 : 111578 : c_unparser::c_funcname (const string& e)
2454 : : {
2455 : : // XXX uncomment to test custom mangling:
2456 : : // return "function_" + e + "_" + lex_cast(do_hash(e.c_str()));
2457 : 111578 : return "function_" + e;
2458 : : }
2459 : :
2460 : :
2461 : : string
2462 : 4944 : c_unparser::c_arg_define (const string& e)
2463 : : {
2464 [ + - ][ + - ]: 4944 : return "#define STAP_ARG_" + e + " THIS->" + c_localname(e);
[ + - ][ + - ]
[ + - ]
2465 : : }
2466 : :
2467 : :
2468 : : string
2469 : 4944 : c_unparser::c_arg_undef (const string& e)
2470 : : {
2471 : 4944 : return "#undef STAP_ARG_" + e;
2472 : : }
2473 : :
2474 : :
2475 : : string
2476 : 46130 : c_unparser::c_expression (expression *e)
2477 : : {
2478 : : // We want to evaluate expression 'e' and return its value as a
2479 : : // string. In the case of expressions that are just numeric
2480 : : // constants, if we just print the value into a string, it won't
2481 : : // have the same value as being visited by c_unparser. For
2482 : : // instance, a numeric constant evaluated using print() would return
2483 : : // "5", while c_unparser::visit_literal_number() would
2484 : : // return "((int64_t)5LL)". String constants evaluated using
2485 : : // print() would just return the string, while
2486 : : // c_unparser::visit_literal_string() would return the string with
2487 : : // escaped double quote characters. So, we need to "visit" the
2488 : : // expression.
2489 : :
2490 : : // However, we have to be careful of side effects. Currently this
2491 : : // code is only being used for evaluating literal numbers and
2492 : : // strings, which currently have no side effects. Until needed
2493 : : // otherwise, limit the use of this function to literal numbers and
2494 : : // strings.
2495 [ + + ][ - + ]: 46130 : if (e->tok->type != tok_number && e->tok->type != tok_string)
2496 [ # # ][ # # ]: 0 : throw semantic_error(_("unsupported c_expression token type"));
2497 : :
2498 : : // Create a fake output stream so we can grab the string output.
2499 [ + - ]: 46130 : ostringstream oss;
2500 [ + - ]: 46130 : translator_output tmp_o(oss);
2501 : :
2502 : : // Temporarily swap out the real translator_output stream with our
2503 : : // fake one.
2504 : 46130 : translator_output *saved_o = o;
2505 : 46130 : o = &tmp_o;
2506 : :
2507 : : // Visit the expression then restore the original output stream
2508 [ + - ]: 46130 : e->visit (this);
2509 : 46130 : o = saved_o;
2510 : :
2511 [ + - ][ + - ]: 46130 : return (oss.str());
[ + - ]
2512 : : }
2513 : :
2514 : :
2515 : : void
2516 : 6420 : c_unparser::c_assign (var& lvalue, const string& rvalue, const token *tok)
2517 : : {
2518 [ + + - ]: 6420 : switch (lvalue.type())
2519 : : {
2520 : : case pe_string:
2521 [ + - ]: 1483 : c_strcpy(lvalue.value(), rvalue);
2522 : 1483 : break;
2523 : : case pe_long:
2524 : 4937 : o->newline() << lvalue << " = " << rvalue << ";";
2525 : 4937 : break;
2526 : : default:
2527 [ # # ][ # # ]: 0 : throw semantic_error (_("unknown lvalue type in assignment"), tok);
2528 : : }
2529 : 6420 : }
2530 : :
2531 : : void
2532 : 68517 : c_unparser::c_assign (const string& lvalue, expression* rvalue,
2533 : : const string& msg)
2534 : : {
2535 [ + + ]: 68517 : if (rvalue->type == pe_long)
2536 : : {
2537 : 41375 : o->newline() << lvalue << " = ";
2538 : 41375 : rvalue->visit (this);
2539 : 41375 : o->line() << ";";
2540 : : }
2541 [ + - ]: 27142 : else if (rvalue->type == pe_string)
2542 : : {
2543 : 27142 : c_strcpy (lvalue, rvalue);
2544 : : }
2545 : : else
2546 : : {
2547 [ # # ]: 0 : string fullmsg = msg + _(" type unsupported");
2548 [ # # ]: 0 : throw semantic_error (fullmsg, rvalue->tok);
2549 : : }
2550 : 68517 : }
2551 : :
2552 : :
2553 : : void
2554 : 13372 : c_unparser::c_assign (const string& lvalue, const string& rvalue,
2555 : : exp_type type, const string& msg, const token* tok)
2556 : : {
2557 [ + + ]: 13372 : if (type == pe_long)
2558 : : {
2559 : 10784 : o->newline() << lvalue << " = " << rvalue << ";";
2560 : : }
2561 [ + - ]: 2588 : else if (type == pe_string)
2562 : : {
2563 : 2588 : c_strcpy (lvalue, rvalue);
2564 : : }
2565 : : else
2566 : : {
2567 [ # # ]: 0 : string fullmsg = msg + _(" type unsupported");
2568 [ # # ]: 0 : throw semantic_error (fullmsg, tok);
2569 : : }
2570 : 13372 : }
2571 : :
2572 : :
2573 : : void
2574 : 28875 : c_unparser_assignment::c_assignop(tmpvar & res,
2575 : : var const & lval,
2576 : : tmpvar const & rval,
2577 : : token const * tok)
2578 : : {
2579 : : // This is common code used by scalar and array-element assignments.
2580 : : // It assumes an operator-and-assignment (defined by the 'pre' and
2581 : : // 'op' fields of c_unparser_assignment) is taking place between the
2582 : : // following set of variables:
2583 : : //
2584 : : // res: the result of evaluating the expression, a temporary
2585 : : // lval: the lvalue of the expression, which may be damaged
2586 : : // rval: the rvalue of the expression, which is a temporary or constant
2587 : :
2588 : : // we'd like to work with a local tmpvar so we can overwrite it in
2589 : : // some optimized cases
2590 : :
2591 : 28875 : translator_output* o = parent->o;
2592 : :
2593 [ + + ]: 28875 : if (res.type() == pe_string)
2594 : : {
2595 [ - + ]: 9793 : if (post)
2596 : 0 : throw semantic_error (_("post assignment on strings not supported"),
2597 [ # # ][ # # ]: 0 : tok);
2598 [ + + ]: 9793 : if (op == "=")
2599 : : {
2600 [ + - ][ + - ]: 9751 : parent->c_strcpy (lval.value(), rval.value());
[ + - ]
2601 : : // no need for second copy
2602 : 9751 : res = rval;
2603 : : }
2604 [ + - ]: 42 : else if (op == ".=")
2605 : : {
2606 [ + - ][ + - ]: 42 : parent->c_strcat (lval.value(), rval.value());
[ + - ]
2607 [ + - ]: 42 : res = lval;
2608 : : }
2609 : : else
2610 [ # # ][ # # ]: 0 : throw semantic_error (_F("string assignment operator %s unsupported", op.c_str()), tok);
[ # # ]
2611 : : }
2612 [ + + ]: 19082 : else if (op == "<<<")
2613 : : {
2614 [ - + ]: 238 : assert(lval.type() == pe_stats);
2615 [ - + ]: 238 : assert(rval.type() == pe_long);
2616 [ - + ]: 238 : assert(res.type() == pe_long);
2617 : 238 : o->newline() << res << " = " << rval << ";";
2618 : 238 : o->newline() << "_stp_stat_add (" << lval << ", " << res << ");";
2619 : : }
2620 [ + - ]: 18844 : else if (res.type() == pe_long)
2621 : : {
2622 : : // a lot of operators come through this "gate":
2623 : : // - vanilla assignment "="
2624 : : // - stats aggregation "<<<"
2625 : : // - modify-accumulate "+=" and many friends
2626 : : // - pre/post-crement "++"/"--"
2627 : : // - "/" and "%" operators, but these need special handling in kernel
2628 : :
2629 : : // compute the modify portion of a modify-accumulate
2630 [ + - ]: 18844 : string macop;
2631 [ + - ]: 18844 : unsigned oplen = op.size();
2632 [ + - ][ + + ]: 18844 : if (op == "=")
2633 [ + - ]: 15885 : macop = "*error*"; // special shortcuts below
2634 [ + - ][ + + ]: 2959 : else if (op == "++" || op == "+=")
[ + - ][ + + ]
[ + + ]
2635 [ + - ]: 2267 : macop = "+=";
2636 [ + - ][ + + ]: 692 : else if (op == "--" || op == "-=")
[ + - ][ + + ]
[ + + ]
2637 [ + - ]: 418 : macop = "-=";
2638 [ + - ][ + - ]: 274 : else if (oplen > 1 && op[oplen-1] == '=') // for *=, <<=, etc...
[ + - ][ + - ]
2639 [ + - ]: 274 : macop = op;
2640 : : else
2641 : : // internal error
2642 [ # # ][ # # ]: 0 : throw semantic_error (_("unknown macop for assignment"), tok);
2643 : :
2644 [ + + ]: 18844 : if (post)
2645 : : {
2646 [ + - ][ + - ]: 1509 : if (macop == "/" || macop == "%" || op == "=")
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ]
2647 [ # # ][ # # ]: 0 : throw semantic_error (_("invalid post-mode operator"), tok);
2648 : :
2649 [ + - ][ + - ]: 1509 : o->newline() << res << " = " << lval << ";";
[ + - ][ + - ]
[ + - ]
2650 : :
2651 [ + - ][ + + ]: 1509 : if (macop == "+=" || macop == "-=")
[ + - ][ + - ]
[ + - ]
2652 [ + - ][ + - ]: 1509 : o->newline() << lval << " " << macop << " " << rval << ";";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2653 : : else
2654 [ # # ][ # # ]: 0 : o->newline() << lval << " = " << res << " " << macop << " " << rval << ";";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2655 : : }
2656 : : else
2657 : : {
2658 [ + - ][ + + ]: 17335 : if (op == "=") // shortcut simple assignment
2659 : : {
2660 [ + - ][ + - ]: 15885 : o->newline() << lval << " = " << rval << ";";
[ + - ][ + - ]
[ + - ]
2661 [ + - ]: 15885 : res = rval;
2662 : : }
2663 : : else
2664 : : {
2665 [ + - ][ + + ]: 1450 : if (macop == "/=" || macop == "%=")
[ + - ][ + + ]
[ + + ]
2666 : : {
2667 [ + - ][ + - ]: 6 : o->newline() << "if (unlikely(!" << rval << ")) {";
[ + - ][ + - ]
2668 [ + - ][ + - ]: 6 : o->newline(1) << "c->last_error = ";
2669 [ + - ]: 6 : o->line() << STAP_T_03;
2670 [ + - ][ + - ]: 6 : o->newline() << "c->last_stmt = " << lex_cast_qstring(*rvalue->tok) << ";";
[ + - ][ + - ]
[ + - ][ + - ]
2671 [ + - ][ + - ]: 6 : o->newline() << "goto out;";
2672 [ + - ][ + - ]: 6 : o->newline(-1) << "}";
2673 [ + - ][ + - ]: 6 : o->newline() << lval << " = "
[ + - ]
2674 [ + - ][ + + ]: 6 : << ((macop == "/=") ? "_stp_div64" : "_stp_mod64")
[ + - ]
2675 [ + - ][ + - ]: 6 : << " (NULL, " << lval << ", " << rval << ");";
[ + - ][ + - ]
[ + - ]
2676 : : }
2677 : : else
2678 [ + - ][ + - ]: 1444 : o->newline() << lval << " " << macop << " " << rval << ";";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2679 [ + - ][ + - ]: 1450 : res = lval;
[ + - ]
2680 : : }
2681 [ + - ]: 18844 : }
2682 : : }
2683 : : else
2684 [ # # ][ # # ]: 0 : throw semantic_error (_("assignment type not yet implemented"), tok);
2685 : 28875 : }
2686 : :
2687 : :
2688 : : void
2689 : 100675 : c_unparser::c_declare(exp_type ty, const string &ident)
2690 : : {
2691 [ + - ][ + - ]: 100675 : o->newline() << c_typename (ty) << " " << ident << ";";
[ + - ][ + - ]
2692 : 100675 : }
2693 : :
2694 : :
2695 : : void
2696 : 0 : c_unparser::c_declare_static(exp_type ty, const string &ident)
2697 : : {
2698 [ # # ][ # # ]: 0 : o->newline() << "static " << c_typename (ty) << " " << ident << ";";
[ # # ][ # # ]
2699 : 0 : }
2700 : :
2701 : :
2702 : : void
2703 : 13824 : c_unparser::c_strcpy (const string& lvalue, const string& rvalue)
2704 : : {
2705 : 13824 : o->newline() << "strlcpy ("
2706 : 13824 : << lvalue << ", "
2707 : 13824 : << rvalue << ", MAXSTRINGLEN);";
2708 : 13824 : }
2709 : :
2710 : :
2711 : : void
2712 : 27142 : c_unparser::c_strcpy (const string& lvalue, expression* rvalue)
2713 : : {
2714 : 27142 : o->newline() << "strlcpy (" << lvalue << ", ";
2715 : 27142 : rvalue->visit (this);
2716 : 27142 : o->line() << ", MAXSTRINGLEN);";
2717 : 27142 : }
2718 : :
2719 : :
2720 : : void
2721 : 42 : c_unparser::c_strcat (const string& lvalue, const string& rvalue)
2722 : : {
2723 : 42 : o->newline() << "strlcat ("
2724 : 42 : << lvalue << ", "
2725 : 42 : << rvalue << ", MAXSTRINGLEN);";
2726 : 42 : }
2727 : :
2728 : :
2729 : : void
2730 : 1646 : c_unparser::c_strcat (const string& lvalue, expression* rvalue)
2731 : : {
2732 : 1646 : o->newline() << "strlcat (" << lvalue << ", ";
2733 : 1646 : rvalue->visit (this);
2734 : 1646 : o->line() << ", MAXSTRINGLEN);";
2735 : 1646 : }
2736 : :
2737 : :
2738 : : bool
2739 : 85733 : c_unparser::is_local(vardecl const *r, token const *tok)
2740 : : {
2741 [ + + ]: 85733 : if (current_probe)
2742 : : {
2743 [ + + ]: 157946 : for (unsigned i=0; i<current_probe->locals.size(); i++)
2744 : : {
2745 [ + + ]: 129714 : if (current_probe->locals[i] == r)
2746 : 37853 : return true;
2747 : : }
2748 : : }
2749 [ + + ]: 19648 : else if (current_function)
2750 : : {
2751 [ + + ]: 29434 : for (unsigned i=0; i<current_function->locals.size(); i++)
2752 : : {
2753 [ + + ]: 19909 : if (current_function->locals[i] == r)
2754 : 4921 : return true;
2755 : : }
2756 : :
2757 [ + + ]: 13850 : for (unsigned i=0; i<current_function->formal_args.size(); i++)
2758 : : {
2759 [ + + ]: 12240 : if (current_function->formal_args[i] == r)
2760 : 7915 : return true;
2761 : : }
2762 : : }
2763 : :
2764 [ + - ]: 1715571 : for (unsigned i=0; i<session->globals.size(); i++)
2765 : : {
2766 [ + + ]: 1715571 : if (session->globals[i] == r)
2767 : 35044 : return false;
2768 : : }
2769 : :
2770 [ # # ]: 0 : if (tok)
2771 [ # # ][ # # ]: 0 : throw semantic_error (_("unresolved symbol"), tok);
2772 : : else
2773 [ # # ][ # # ]: 85733 : throw semantic_error (_("unresolved symbol: ") + r->name);
2774 : : }
2775 : :
2776 : :
2777 : : tmpvar
2778 : 367968 : c_unparser::gensym(exp_type ty)
2779 : : {
2780 : 367968 : return tmpvar (this, ty, tmpvar_counter);
2781 : : }
2782 : :
2783 : : aggvar
2784 : 1388 : c_unparser::gensym_aggregate()
2785 : : {
2786 : 1388 : return aggvar (this, tmpvar_counter);
2787 : : }
2788 : :
2789 : :
2790 : : var
2791 : 57247 : c_unparser::getvar(vardecl *v, token const *tok)
2792 : : {
2793 : 57247 : bool loc = is_local (v, tok);
2794 [ + + ]: 57247 : if (loc)
2795 : 50689 : return var (this, loc, v->type, v->name);
2796 : : else
2797 : : {
2798 : 6558 : statistic_decl sd;
2799 : 6558 : std::map<std::string, statistic_decl>::const_iterator i;
2800 [ + - ]: 6558 : i = session->stat_decls.find(v->name);
2801 [ + - ][ + + ]: 6558 : if (i != session->stat_decls.end())
2802 [ + - ]: 765 : sd = i->second;
2803 [ + - ]: 57247 : return var (this, loc, v->type, sd, v->name);
2804 : : }
2805 : : }
2806 : :
2807 : :
2808 : : mapvar
2809 : 28486 : c_unparser::getmap(vardecl *v, token const *tok)
2810 : : {
2811 [ - + ]: 28486 : if (v->arity < 1)
2812 [ # # ][ # # ]: 0 : throw semantic_error(_("attempt to use scalar where map expected"), tok);
2813 : 28486 : statistic_decl sd;
2814 : 28486 : std::map<std::string, statistic_decl>::const_iterator i;
2815 [ + - ]: 28486 : i = session->stat_decls.find(v->name);
2816 [ + - ][ + + ]: 28486 : if (i != session->stat_decls.end())
2817 [ + - ]: 8263 : sd = i->second;
2818 : : return mapvar (this, is_local (v, tok), v->type, sd,
2819 [ + - ][ + - ]: 28486 : v->name, v->index_types, v->maxsize, v->wrap);
2820 : : }
2821 : :
2822 : :
2823 : : itervar
2824 : 540 : c_unparser::getiter(symbol *s)
2825 : : {
2826 : 540 : return itervar (s, tmpvar_counter);
2827 : : }
2828 : :
2829 : :
2830 : : // Queue up some actions to remove from actionremaining. Set update=true at
2831 : : // the end of basic blocks to actually update actionremaining and check it
2832 : : // against MAXACTION.
2833 : : void
2834 : 93056 : c_unparser::record_actions (unsigned actions, const token* tok, bool update)
2835 : : {
2836 : 93056 : action_counter += actions;
2837 : :
2838 : : // Update if needed, or after queueing up a few actions, in case of very
2839 : : // large code sequences.
2840 [ + + ][ + + ]: 93056 : if (((update && action_counter > 0) || action_counter >= 10/*<-arbitrary*/) && !session->suppress_time_limits)
[ + + ][ + + ]
2841 : : {
2842 : 31593 : o->newline() << "c->actionremaining -= " << action_counter << ";";
2843 : 31593 : o->newline() << "if (unlikely (c->actionremaining <= 0)) {";
2844 : 31593 : o->newline(1) << "c->last_error = ";
2845 : 31593 : o->line() << STAP_T_04;
2846 : :
2847 : : // XXX it really ought to be illegal for anything to be missing a token,
2848 : : // but until we're sure of that, we need to defend against NULL.
2849 [ + - ]: 31593 : if (tok)
2850 [ + - ][ + - ]: 31593 : o->newline() << "c->last_stmt = " << lex_cast_qstring(*tok) << ";";
2851 : :
2852 : 31593 : o->newline() << "goto out;";
2853 : 31593 : o->newline(-1) << "}";
2854 : 31593 : action_counter = 0;
2855 : : }
2856 : 93056 : }
2857 : :
2858 : :
2859 : : void
2860 : 9460 : c_unparser::visit_block (block *s)
2861 : : {
2862 : 9460 : o->newline() << "{";
2863 : 9460 : o->indent (1);
2864 : :
2865 [ + + ]: 61189 : for (unsigned i=0; i<s->statements.size(); i++)
2866 : : {
2867 : : try
2868 : : {
2869 [ + + ]: 51729 : s->statements[i]->visit (this);
2870 [ + - ]: 51727 : o->newline();
2871 : : }
2872 [ - + ]: 4 : catch (const semantic_error& e)
2873 : : {
2874 [ - + ]: 2 : session->print_error (e);
2875 : : }
2876 : : }
2877 : 9460 : o->newline(-1) << "}";
2878 : 9460 : }
2879 : :
2880 : :
2881 : 188 : void c_unparser::visit_try_block (try_block *s)
2882 : : {
2883 : 188 : record_actions(0, s->tok, true); // flush prior actions
2884 : :
2885 : 188 : o->newline() << "{";
2886 : 188 : o->newline(1) << "__label__ normal_fallthrough;";
2887 : 188 : o->newline(1) << "{";
2888 : 188 : o->newline() << "__label__ out;";
2889 : :
2890 [ + + ][ - + ]: 188 : assert (!session->unoptimized || s->try_block); // dead_stmtexpr_remover would zap it
2891 [ + - ]: 188 : if (s->try_block)
2892 : : {
2893 : 188 : s->try_block->visit (this);
2894 : 188 : record_actions(0, s->try_block->tok, true); // flush accumulated actions
2895 : : }
2896 : 188 : o->newline() << "goto normal_fallthrough;";
2897 : :
2898 : 188 : o->newline() << "if (0) goto out;"; // to prevent 'unused label' warnings
2899 : 188 : o->newline() << "out:";
2900 : 188 : o->newline() << ";"; // to have _some_ statement
2901 : :
2902 : : // Close the scope of the above nested 'out' label, to make sure
2903 : : // that the catch block, should it encounter errors, does not resolve
2904 : : // a 'goto out;' to the above label, causing infinite looping.
2905 : 188 : o->newline(-1) << "}";
2906 : :
2907 : 188 : o->newline() << "if (likely(c->last_error == NULL)) goto out;";
2908 : :
2909 [ + + ]: 188 : if (s->catch_error_var)
2910 : : {
2911 [ + - ]: 2 : var cev(getvar(s->catch_error_var->referent, s->catch_error_var->tok));
2912 [ + - ][ + - ]: 2 : c_strcpy (cev.value(), "c->last_error");
[ + - ][ + - ]
[ + - ][ + - ]
2913 : : }
2914 : 188 : o->newline() << "c->last_error = NULL;";
2915 : :
2916 : : // Prevent the catch{} handler from even starting if MAXACTIONS have
2917 : : // already been used up. Add one for the act of catching too.
2918 : 188 : record_actions(1, s->tok, true);
2919 : :
2920 [ + + ]: 188 : if (s->catch_block)
2921 : : {
2922 : 180 : s->catch_block->visit (this);
2923 : 180 : record_actions(0, s->catch_block->tok, true); // flush accumulated actions
2924 : : }
2925 : :
2926 : 188 : o->newline() << "normal_fallthrough:";
2927 : 188 : o->newline() << ";"; // to have _some_ statement
2928 : 188 : o->newline(-1) << "}";
2929 : 188 : }
2930 : :
2931 : :
2932 : : void
2933 : 4877 : c_unparser::visit_embeddedcode (embeddedcode *s)
2934 : : {
2935 : : // Automatically add a call to assert_is_myproc to any code tagged with
2936 : : // /* myproc-unprivileged */
2937 [ + + ]: 4877 : if (s->code.find ("/* myproc-unprivileged */") != string::npos)
2938 : 343 : o->newline() << "assert_is_myproc();";
2939 : 4877 : o->newline() << "{";
2940 : 4877 : o->newline(1) << s->code;
2941 : 4877 : o->newline(-1) << "}";
2942 : 4877 : }
2943 : :
2944 : :
2945 : : void
2946 : 63 : c_unparser::visit_null_statement (null_statement *)
2947 : : {
2948 : 63 : o->newline() << "/* null */;";
2949 : 63 : }
2950 : :
2951 : :
2952 : : void
2953 : 46050 : c_unparser::visit_expr_statement (expr_statement *s)
2954 : : {
2955 : 46050 : o->newline() << "(void) ";
2956 : 46050 : s->value->visit (this);
2957 : 46049 : o->line() << ";";
2958 : 46049 : record_actions(1, s->tok);
2959 : 46049 : }
2960 : :
2961 : :
2962 : : void
2963 : 10423 : c_unparser::visit_if_statement (if_statement *s)
2964 : : {
2965 : 10423 : record_actions(1, s->tok, true);
2966 : 10423 : o->newline() << "if (";
2967 : 10423 : o->indent (1);
2968 : 10423 : s->condition->visit (this);
2969 : 10423 : o->indent (-1);
2970 : 10423 : o->line() << ") {";
2971 : 10423 : o->indent (1);
2972 : 10423 : s->thenblock->visit (this);
2973 : 10423 : record_actions(0, s->thenblock->tok, true);
2974 : 10423 : o->newline(-1) << "}";
2975 [ + + ]: 10423 : if (s->elseblock)
2976 : : {
2977 : 1143 : o->newline() << "else {";
2978 : 1143 : o->indent (1);
2979 : 1143 : s->elseblock->visit (this);
2980 : 1143 : record_actions(0, s->elseblock->tok, true);
2981 : 1143 : o->newline(-1) << "}";
2982 : : }
2983 : 10423 : }
2984 : :
2985 : :
2986 : : void
2987 : 9460 : c_tmpcounter::visit_block (block *s)
2988 : : {
2989 : : // Key insight: individual statements of a block can reuse
2990 : : // temporary variable slots, since temporaries don't survive
2991 : : // statement boundaries. So we use gcc's anonymous union/struct
2992 : : // facility to explicitly overlay the temporaries.
2993 : 9460 : parent->o->newline() << "union {";
2994 : 9460 : parent->o->indent(1);
2995 [ + + ]: 61189 : for (unsigned i=0; i<s->statements.size(); i++)
2996 : : {
2997 : : // To avoid lots of empty structs inside the union, remember
2998 : : // where we are now. Then, output the struct start and remember
2999 : : // that positon. If when we get done with the statement we
3000 : : // haven't moved, then we don't really need the struct. To get
3001 : : // rid of the struct start we output, we'll seek back to where
3002 : : // we were before we output the struct.
3003 [ + - ]: 51729 : std::ostream::pos_type before_struct_pos = parent->o->tellp();
3004 [ + - ][ + - ]: 51729 : parent->o->newline() << "struct {";
3005 [ + - ]: 51729 : parent->o->indent(1);
3006 [ + - ]: 51729 : std::ostream::pos_type after_struct_pos = parent->o->tellp();
3007 [ + - ]: 51729 : s->statements[i]->visit (this);
3008 [ + - ]: 51729 : parent->o->indent(-1);
3009 [ + - ][ + - ]: 51729 : if (after_struct_pos == parent->o->tellp())
[ + + ]
3010 [ + - ]: 11624 : parent->o->seekp(before_struct_pos);
3011 : : else
3012 [ + - ][ + - ]: 40105 : parent->o->newline() << "};";
3013 : : }
3014 : 9460 : parent->o->newline(-1) << "};";
3015 : 9460 : }
3016 : :
3017 : : void
3018 : 209 : c_tmpcounter::visit_for_loop (for_loop *s)
3019 : : {
3020 [ + + ]: 209 : if (s->init) s->init->visit (this);
3021 : 209 : s->cond->visit (this);
3022 : 209 : s->block->visit (this);
3023 [ + + ]: 209 : if (s->incr) s->incr->visit (this);
3024 : 209 : }
3025 : :
3026 : :
3027 : : void
3028 : 209 : c_unparser::visit_for_loop (for_loop *s)
3029 : : {
3030 [ + - ]: 209 : string ctr = lex_cast (label_counter++);
3031 [ + - ]: 209 : string toplabel = "top_" + ctr;
3032 [ + - ]: 209 : string contlabel = "continue_" + ctr;
3033 [ + - ]: 209 : string breaklabel = "break_" + ctr;
3034 : :
3035 : : // initialization
3036 [ + + ][ + - ]: 209 : if (s->init) s->init->visit (this);
3037 [ + - ]: 209 : record_actions(1, s->tok, true);
3038 : :
3039 : : // condition
3040 [ + - ][ + - ]: 209 : o->newline(-1) << toplabel << ":";
[ + - ]
3041 : :
3042 : : // Emit an explicit action here to cover the act of iteration.
3043 : : // Equivalently, it can stand for the evaluation of the condition
3044 : : // expression.
3045 [ + - ]: 209 : o->indent(1);
3046 [ + - ]: 209 : record_actions(1, s->tok);
3047 : :
3048 [ + - ][ + - ]: 209 : o->newline() << "if (! (";
3049 [ - + ]: 209 : if (s->cond->type != pe_long)
3050 [ # # ][ # # ]: 0 : throw semantic_error (_("expected numeric type"), s->cond->tok);
3051 [ + - ]: 209 : s->cond->visit (this);
3052 [ + - ][ + - ]: 209 : o->line() << ")) goto " << breaklabel << ";";
[ + - ]
3053 : :
3054 : : // body
3055 [ + - ]: 209 : loop_break_labels.push_back (breaklabel);
3056 [ + - ]: 209 : loop_continue_labels.push_back (contlabel);
3057 [ + - ]: 209 : s->block->visit (this);
3058 [ + - ]: 209 : record_actions(0, s->block->tok, true);
3059 [ + - ]: 209 : loop_break_labels.pop_back ();
3060 [ + - ]: 209 : loop_continue_labels.pop_back ();
3061 : :
3062 : : // iteration
3063 [ + - ][ + - ]: 209 : o->newline(-1) << contlabel << ":";
[ + - ]
3064 [ + - ]: 209 : o->indent(1);
3065 [ + + ][ + - ]: 209 : if (s->incr) s->incr->visit (this);
3066 [ + - ][ + - ]: 209 : o->newline() << "goto " << toplabel << ";";
[ + - ][ + - ]
3067 : :
3068 : : // exit
3069 [ + - ][ + - ]: 209 : o->newline(-1) << breaklabel << ":";
[ + - ]
3070 [ + - ][ + - ]: 209 : o->newline(1) << "; /* dummy statement */";
[ + - ][ + - ]
[ + - ][ + - ]
3071 : 209 : }
3072 : :
3073 : :
3074 [ - + ]: 1139 : struct arrayindex_downcaster
3075 : : : public traversing_visitor
3076 : : {
3077 : : arrayindex *& arr;
3078 : :
3079 : 1139 : arrayindex_downcaster (arrayindex *& arr)
3080 : 1139 : : arr(arr)
3081 : 1139 : {}
3082 : :
3083 : 890 : void visit_arrayindex (arrayindex* e)
3084 : : {
3085 : 890 : arr = e;
3086 : 890 : }
3087 : : };
3088 : :
3089 : :
3090 : : static bool
3091 : 1139 : expression_is_arrayindex (expression *e,
3092 : : arrayindex *& hist)
3093 : : {
3094 : 1139 : arrayindex *h = NULL;
3095 [ + - ]: 1139 : arrayindex_downcaster d(h);
3096 [ + - ]: 1139 : e->visit (&d);
3097 [ + + ]: 1139 : if (static_cast<void*>(h) == static_cast<void*>(e))
3098 : : {
3099 : 890 : hist = h;
3100 : 890 : return true;
3101 : : }
3102 [ + - ]: 1139 : return false;
3103 : : }
3104 : :
3105 : :
3106 : : // Look for opportunities to used a saved value at the beginning of the loop
3107 : : void
3108 : 558 : c_unparser::visit_foreach_loop_value (visitor* vis, foreach_loop* s,
3109 : : const string& value)
3110 : : {
3111 : 558 : bool stable_value = false;
3112 : :
3113 : : // There are three possible cases that we might easily retrieve the value:
3114 : : // 1. foreach ([keys] in any_array_type)
3115 : : // 2. foreach (idx in @hist_*(stat))
3116 : : // 3. foreach (idx in @hist_*(stat[keys]))
3117 : : //
3118 : : // For 1 and 2, we just need to check that the keys/idx are const throughout
3119 : : // the loop. For 3, we'd have to check also that the arbitrary keys
3120 : : // expressions indexing the stat are const -- much harder, so I'm punting
3121 : : // that case for now.
3122 : :
3123 : : symbol *array;
3124 : : hist_op *hist;
3125 [ + - ]: 558 : classify_indexable (s->base, array, hist);
3126 : :
3127 [ + + ][ + - ]: 558 : if (!(hist && get_symbol_within_expression(hist->stat)->referent->arity > 0))
[ + + ][ + + ]
3128 : : {
3129 [ + - ]: 554 : set<vardecl*> indexes;
3130 [ + + ]: 1760 : for (unsigned i=0; i < s->indexes.size(); ++i)
3131 [ + - ]: 1206 : indexes.insert(s->indexes[i]->referent);
3132 : :
3133 [ + - ]: 554 : varuse_collecting_visitor v(*session);
3134 [ + - ]: 554 : s->block->visit (&v);
3135 : 554 : v.embedded_seen = false; // reset because we only care about the indexes
3136 [ + - ][ + - ]: 554 : if (v.side_effect_free_wrt(indexes))
3137 [ + - ][ + - ]: 554 : stable_value = true;
3138 : : }
3139 : :
3140 [ + + ]: 558 : if (stable_value)
3141 : : {
3142 : : // Rather than trying to compare arrayindexes to this foreach_loop
3143 : : // manually, we just create a fake arrayindex that would match the
3144 : : // foreach_loop, render it as a string, and later render encountered
3145 : : // arrayindexes as strings and compare.
3146 [ + - ]: 554 : arrayindex ai;
3147 : 554 : ai.base = s->base;
3148 [ + + ]: 1760 : for (unsigned i=0; i < s->indexes.size(); ++i)
3149 [ + - ]: 1206 : ai.indexes.push_back(s->indexes[i]);
3150 [ + - ]: 554 : string loopai = lex_cast(ai);
3151 [ + - ][ + - ]: 554 : foreach_loop_values[loopai] = value;
3152 [ + - ]: 554 : s->block->visit (vis);
3153 [ + - ][ + - ]: 554 : foreach_loop_values.erase(loopai);
[ + - ]
3154 : : }
3155 : : else
3156 [ + - ]: 4 : s->block->visit (vis);
3157 : 558 : }
3158 : :
3159 : :
3160 : : bool
3161 : 7728 : c_unparser::get_foreach_loop_value (arrayindex* ai, string& value)
3162 : : {
3163 [ - + ]: 7728 : if (!ai)
3164 : 0 : return false;
3165 [ + - ][ + - ]: 7728 : map<string,string>::iterator it = foreach_loop_values.find(lex_cast(*ai));
[ + - ]
3166 [ + - ][ + + ]: 7728 : if (it == foreach_loop_values.end())
3167 : 6740 : return false;
3168 [ + - ][ + - ]: 988 : value = it->second;
3169 : 7728 : return true;
3170 : : }
3171 : :
3172 : :
3173 : : void
3174 : 279 : c_tmpcounter::visit_foreach_loop (foreach_loop *s)
3175 : : {
3176 : : symbol *array;
3177 : : hist_op *hist;
3178 [ + - ]: 279 : classify_indexable (s->base, array, hist);
3179 : :
3180 [ + + ]: 279 : if (array)
3181 : : {
3182 [ + - ]: 270 : itervar iv = parent->getiter (array);
3183 [ + - ][ + - ]: 270 : parent->o->newline() << iv.declare();
[ + - ][ + - ]
[ + - ]
3184 : : }
3185 : : else
3186 : : {
3187 : : // See commentary in c_tmpcounter::visit_arrayindex for
3188 : : // discussion of tmpvars required to look into @hist_op(...)
3189 : : // expressions.
3190 : :
3191 : : // First make sure we have exactly one pe_long variable to use as
3192 : : // our bucket index.
3193 : :
3194 [ + - ][ - + ]: 9 : if (s->indexes.size() != 1 || s->indexes[0]->referent->type != pe_long)
[ - + ]
3195 [ # # ][ # # ]: 0 : throw semantic_error(_("Invalid indexing of histogram"), s->tok);
3196 : :
3197 : : // Then declare what we need to form the aggregate we're
3198 : : // iterating over, and all the tmpvars needed by our call to
3199 : : // load_aggregate().
3200 : :
3201 [ + - ]: 9 : aggvar agg = parent->gensym_aggregate ();
3202 [ + - ]: 9 : agg.declare(*(this->parent));
3203 [ + - ][ + - ]: 9 : load_aggregate (hist->stat);
3204 : : }
3205 : :
3206 : : // Create a temporary for the loop limit counter and the limit
3207 : : // expression result.
3208 [ + + ]: 279 : if (s->limit)
3209 : : {
3210 [ + - ]: 38 : tmpvar res_limit = parent->gensym (pe_long);
3211 [ + - ]: 38 : res_limit.declare(*parent);
3212 : :
3213 [ + - ]: 38 : s->limit->visit (this);
3214 : :
3215 [ + - ]: 38 : tmpvar limitv = parent->gensym (pe_long);
3216 [ + - ][ + - ]: 38 : limitv.declare(*parent);
[ + - ]
3217 : : }
3218 : :
3219 [ + - ][ + - ]: 279 : parent->visit_foreach_loop_value(this, s);
[ + - ]
3220 : 279 : }
3221 : :
3222 : : void
3223 : 279 : c_unparser::visit_foreach_loop (foreach_loop *s)
3224 : : {
3225 : : symbol *array;
3226 : : hist_op *hist;
3227 [ + - ]: 279 : classify_indexable (s->base, array, hist);
3228 : :
3229 [ + - ]: 279 : string ctr = lex_cast (label_counter++);
3230 [ + - ]: 279 : string toplabel = "top_" + ctr;
3231 [ + - ]: 279 : string contlabel = "continue_" + ctr;
3232 [ + - ]: 279 : string breaklabel = "break_" + ctr;
3233 : :
3234 [ + + ]: 279 : if (array)
3235 : : {
3236 [ + - ]: 270 : mapvar mv = getmap (array->referent, s->tok);
3237 [ + - ]: 270 : itervar iv = getiter (array);
3238 [ + - ]: 270 : vector<var> keys;
3239 : :
3240 : : // NB: structure parallels for_loop
3241 : :
3242 : : // initialization
3243 : :
3244 : 270 : tmpvar *res_limit = NULL;
3245 [ + + ]: 270 : if (s->limit)
3246 : : {
3247 : : // Evaluate the limit expression once.
3248 [ + - ][ + - ]: 37 : res_limit = new tmpvar(gensym(pe_long));
3249 [ + - ][ + - ]: 37 : c_assign (res_limit->value(), s->limit, "foreach limit");
[ + - ][ + - ]
[ + - ]
3250 : : }
3251 : :
3252 : : // aggregate array if required
3253 [ + + ]: 270 : if (mv.is_parallel())
3254 : : {
3255 [ + - ][ + - ]: 100 : o->newline() << "if (unlikely(NULL == " << mv.calculate_aggregate() << ")) {";
[ + - ][ + - ]
[ + - ][ + - ]
3256 [ + - ][ + - ]: 100 : o->newline(1) << "c->last_error = ";
3257 [ + - ][ + - ]: 100 : o->line() << STAP_T_05 << mv << "\";";
[ + - ]
3258 [ + - ][ + - ]: 100 : o->newline() << "c->last_stmt = " << lex_cast_qstring(*s->tok) << ";";
[ + - ][ + - ]
[ + - ][ + - ]
3259 [ + - ][ + - ]: 100 : o->newline() << "goto out;";
3260 [ + - ][ + - ]: 100 : o->newline(-1) << "}";
3261 : :
3262 : : // sort array if desired
3263 [ + + ]: 100 : if (s->sort_direction)
3264 : : {
3265 [ + - ]: 85 : string sort_column;
3266 : :
3267 : : // If the user wanted us to sort by value, we'll sort by
3268 : : // @count or selected function instead for aggregates.
3269 : : // See runtime/map.c
3270 [ + + ]: 85 : if (s->sort_column == 0)
3271 [ + + + + : 66 : switch (s->sort_aggr) {
+ ]
3272 [ + - ]: 58 : default: case sc_none: case sc_count: sort_column = "SORT_COUNT"; break;
3273 [ + - ]: 2 : case sc_sum: sort_column = "SORT_SUM"; break;
3274 [ + - ]: 2 : case sc_min: sort_column = "SORT_MIN"; break;
3275 [ + - ]: 2 : case sc_max: sort_column = "SORT_MAX"; break;
3276 [ + - ]: 66 : case sc_average: sort_column = "SORT_AVG"; break;
3277 : : }
3278 : : else
3279 [ + - ][ + - ]: 19 : sort_column = lex_cast(s->sort_column);
[ + - ]
3280 : :
3281 [ + - ][ + - ]: 85 : o->newline() << "else"; // only sort if aggregation was ok
3282 [ + + ]: 85 : if (s->limit)
3283 : : {
3284 [ + - ][ + - ]: 36 : o->newline(1) << mv.function_keysym("sortn", true) <<" ("
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3285 [ + - ][ + - ]: 36 : << mv.fetch_existing_aggregate() << ", "
[ + - ][ + - ]
3286 [ + - ][ + - ]: 18 : << *res_limit << ", " << sort_column << ", "
[ + - ][ + - ]
3287 [ + - ][ + - ]: 18 : << - s->sort_direction << ");";
3288 : : }
3289 : : else
3290 : : {
3291 [ + - ][ + - ]: 134 : o->newline(1) << mv.function_keysym("sort", true) <<" ("
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3292 [ + - ][ + - ]: 134 : << mv.fetch_existing_aggregate() << ", "
[ + - ][ + - ]
3293 [ + - ][ + - ]: 67 : << sort_column << ", "
3294 [ + - ][ + - ]: 67 : << - s->sort_direction << ");";
3295 : : }
3296 [ + - ][ + - ]: 85 : o->indent(-1);
3297 : : }
3298 : : }
3299 : : else
3300 : : {
3301 : : // sort array if desired
3302 [ + + ]: 170 : if (s->sort_direction)
3303 : : {
3304 [ + + ]: 79 : if (s->limit)
3305 : : {
3306 [ + - ][ + - ]: 36 : o->newline() << mv.function_keysym("sortn") <<" ("
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3307 [ + - ][ + - ]: 36 : << mv.value() << ", "
[ + - ][ + - ]
3308 [ + - ][ + - ]: 18 : << *res_limit << ", " << s->sort_column << ", "
[ + - ][ + - ]
3309 [ + - ][ + - ]: 18 : << - s->sort_direction << ");";
3310 : : }
3311 : : else
3312 : : {
3313 [ + - ][ + - ]: 122 : o->newline() << mv.function_keysym("sort") <<" ("
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3314 [ + - ][ + - ]: 122 : << mv.value() << ", "
[ + - ][ + - ]
3315 [ + - ][ + - ]: 61 : << s->sort_column << ", "
3316 [ + - ][ + - ]: 61 : << - s->sort_direction << ");";
3317 : : }
3318 : : }
3319 : : }
3320 : :
3321 : : // NB: sort direction sense is opposite in runtime, thus the negation
3322 : :
3323 [ + + ]: 270 : if (mv.is_parallel())
3324 [ + - ][ + - ]: 100 : aggregations_active.insert(mv.value());
[ + - ]
3325 [ + - ][ + - ]: 270 : o->newline() << iv << " = " << iv.start (mv) << ";";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3326 : :
3327 : 270 : tmpvar *limitv = NULL;
3328 [ + + ]: 270 : if (s->limit)
3329 : : {
3330 : : // Create the loop limit variable here and initialize it.
3331 [ + - ][ + - ]: 37 : limitv = new tmpvar(gensym (pe_long));
3332 [ + - ][ + - ]: 37 : o->newline() << *limitv << " = 0LL;";
[ + - ]
3333 : : }
3334 : :
3335 [ + - ]: 270 : record_actions(1, s->tok, true);
3336 : :
3337 : : // condition
3338 [ + - ][ + - ]: 270 : o->newline(-1) << toplabel << ":";
[ + - ]
3339 : :
3340 : : // Emit an explicit action here to cover the act of iteration.
3341 : : // Equivalently, it can stand for the evaluation of the
3342 : : // condition expression.
3343 [ + - ]: 270 : o->indent(1);
3344 [ + - ]: 270 : record_actions(1, s->tok);
3345 : :
3346 [ + - ][ + - ]: 270 : o->newline() << "if (! (" << iv << ")) goto " << breaklabel << ";";
[ + - ][ + - ]
[ + - ][ + - ]
3347 : :
3348 : : // body
3349 [ + - ]: 270 : loop_break_labels.push_back (breaklabel);
3350 [ + - ]: 270 : loop_continue_labels.push_back (contlabel);
3351 [ + - ][ + - ]: 270 : o->newline() << "{";
3352 [ + - ]: 270 : o->indent (1);
3353 : :
3354 [ + + ]: 270 : if (s->limit)
3355 : : {
3356 : : // If we've been through LIMIT loop iterations, quit.
3357 [ + - ][ + - ]: 37 : o->newline() << "if (" << *limitv << "++ >= " << *res_limit
[ + - ][ + - ]
[ + - ]
3358 [ + - ][ + - ]: 37 : << ") goto " << breaklabel << ";";
[ + - ]
3359 : :
3360 : : // We're done with limitv and res_limit.
3361 [ + - ][ + - ]: 37 : delete limitv;
3362 [ + - ][ + - ]: 37 : delete res_limit;
3363 : : }
3364 : :
3365 [ + + ]: 866 : for (unsigned i = 0; i < s->indexes.size(); ++i)
3366 : : {
3367 : : // copy the iter values into the specified locals
3368 [ + - ]: 596 : var v = getvar (s->indexes[i]->referent);
3369 [ + - ][ + - ]: 596 : c_assign (v, iv.get_key (mv, v.type(), i), s->tok);
[ + - ]
3370 [ + - ]: 596 : }
3371 : :
3372 [ + + ]: 270 : if (s->value)
3373 : : {
3374 [ + - ]: 42 : var v = getvar (s->value->referent);
3375 [ + - ][ + - ]: 42 : c_assign (v, iv.get_value (mv, v.type()), s->tok);
[ + - ][ + - ]
3376 : : }
3377 : :
3378 [ + - ][ + - ]: 270 : visit_foreach_loop_value(this, s, iv.get_value(mv, array->type));
[ + - ]
3379 [ + - ]: 270 : record_actions(0, s->block->tok, true);
3380 [ + - ][ + - ]: 270 : o->newline(-1) << "}";
3381 [ + - ]: 270 : loop_break_labels.pop_back ();
3382 [ + - ]: 270 : loop_continue_labels.pop_back ();
3383 : :
3384 : : // iteration
3385 [ + - ][ + - ]: 270 : o->newline(-1) << contlabel << ":";
[ + - ]
3386 [ + - ][ + - ]: 270 : o->newline(1) << iv << " = " << iv.next (mv) << ";";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3387 [ + - ][ + - ]: 270 : o->newline() << "goto " << toplabel << ";";
[ + - ][ + - ]
3388 : :
3389 : : // exit
3390 [ + - ][ + - ]: 270 : o->newline(-1) << breaklabel << ":";
[ + - ]
3391 [ + - ][ + - ]: 270 : o->newline(1) << "; /* dummy statement */";
3392 : :
3393 [ + + ]: 270 : if (mv.is_parallel())
3394 [ + - ][ + - ]: 270 : aggregations_active.erase(mv.value());
[ + - ][ + - ]
[ + - ][ + - ]
3395 : : }
3396 : : else
3397 : : {
3398 : : // Iterating over buckets in a histogram.
3399 [ - + ]: 9 : assert(s->indexes.size() == 1);
3400 [ - + ]: 9 : assert(s->indexes[0]->referent->type == pe_long);
3401 [ + - ]: 9 : var bucketvar = getvar (s->indexes[0]->referent);
3402 : :
3403 [ + - ]: 9 : aggvar agg = gensym_aggregate ();
3404 : :
3405 [ + - ]: 9 : var *v = load_aggregate(hist->stat, agg);
3406 [ + - ]: 9 : v->assert_hist_compatible(*hist);
3407 : :
3408 : 9 : tmpvar *res_limit = NULL;
3409 : 9 : tmpvar *limitv = NULL;
3410 [ + + ]: 9 : if (s->limit)
3411 : : {
3412 : : // Evaluate the limit expression once.
3413 [ + - ][ + - ]: 1 : res_limit = new tmpvar(gensym(pe_long));
3414 [ + - ][ + - ]: 1 : c_assign (res_limit->value(), s->limit, "foreach limit");
[ + - ][ + - ]
[ + - ]
3415 : :
3416 : : // Create the loop limit variable here and initialize it.
3417 [ + - ][ + - ]: 1 : limitv = new tmpvar(gensym (pe_long));
3418 [ + - ][ + - ]: 1 : o->newline() << *limitv << " = 0LL;";
[ + - ]
3419 : : }
3420 : :
3421 [ + - ]: 9 : record_actions(1, s->tok, true);
3422 [ + - ][ + - ]: 9 : o->newline() << "for (" << bucketvar << " = 0; "
[ + - ][ + - ]
3423 [ + - ][ + - ]: 18 : << bucketvar << " < " << v->buckets() << "; "
[ + - ][ + - ]
[ + - ][ + - ]
3424 [ + - ][ + - ]: 9 : << bucketvar << "++) { ";
3425 [ + - ]: 9 : o->newline(1);
3426 [ + - ]: 9 : loop_break_labels.push_back (breaklabel);
3427 [ + - ]: 9 : loop_continue_labels.push_back (contlabel);
3428 : :
3429 [ + + ]: 9 : if (s->limit)
3430 : : {
3431 : : // If we've been through LIMIT loop iterations, quit.
3432 [ + - ][ + - ]: 1 : o->newline() << "if (" << *limitv << "++ >= " << *res_limit
[ + - ][ + - ]
[ + - ]
3433 [ + - ]: 1 : << ") break;";
3434 : :
3435 : : // We're done with limitv and res_limit.
3436 [ + - ][ + - ]: 1 : delete limitv;
3437 [ + - ][ + - ]: 1 : delete res_limit;
3438 : : }
3439 : :
3440 [ + + ]: 9 : if (s->value)
3441 : : {
3442 [ + - ]: 2 : var v = getvar (s->value->referent);
3443 [ + - ][ + - ]: 2 : c_assign (v, agg.get_hist (bucketvar), s->tok);
[ + - ][ + - ]
3444 : : }
3445 : :
3446 [ + - ][ + - ]: 9 : visit_foreach_loop_value(this, s, agg.get_hist(bucketvar));
[ + - ]
3447 [ + - ]: 9 : record_actions(1, s->block->tok, true);
3448 : :
3449 [ + - ][ + - ]: 9 : o->newline(-1) << contlabel << ":";
[ + - ]
3450 [ + - ][ + - ]: 9 : o->newline(1) << "continue;";
3451 [ + - ][ + - ]: 9 : o->newline(-1) << breaklabel << ":";
[ + - ]
3452 [ + - ][ + - ]: 9 : o->newline(1) << "break;";
3453 [ + - ][ + - ]: 9 : o->newline(-1) << "}";
3454 [ + - ]: 9 : loop_break_labels.pop_back ();
3455 [ + - ]: 9 : loop_continue_labels.pop_back ();
3456 : :
3457 [ + - ][ + - ]: 9 : delete v;
[ + - ][ + - ]
3458 [ + - ][ + - ]: 279 : }
[ + - ][ + - ]
3459 : 279 : }
3460 : :
3461 : :
3462 : : void
3463 : 5006 : c_unparser::visit_return_statement (return_statement* s)
3464 : : {
3465 [ - + ]: 5006 : if (current_function == 0)
3466 [ # # ][ # # ]: 0 : throw semantic_error (_("cannot 'return' from probe"), s->tok);
3467 : :
3468 [ - + ]: 5006 : if (s->value->type != current_function->type)
3469 : 0 : throw semantic_error (_("return type mismatch"), current_function->tok,
3470 [ # # ][ # # ]: 0 : s->tok);
3471 : :
3472 [ + - ][ + - ]: 5006 : c_assign ("l->__retvalue", s->value, "return value");
[ + - ][ + - ]
[ + - ]
3473 : 5006 : record_actions(1, s->tok, true);
3474 : 5006 : o->newline() << "goto out;";
3475 : 5006 : }
3476 : :
3477 : :
3478 : : void
3479 : 967 : c_unparser::visit_next_statement (next_statement* s)
3480 : : {
3481 [ - + ]: 967 : if (current_probe == 0)
3482 [ # # ][ # # ]: 0 : throw semantic_error (_("cannot 'next' from function"), s->tok);
3483 : :
3484 : 967 : record_actions(1, s->tok, true);
3485 : 967 : o->newline() << "goto out;";
3486 : 967 : }
3487 : :
3488 : :
3489 [ - + ]: 1809 : struct delete_statement_operand_tmp_visitor:
3490 : : public traversing_visitor
3491 : : {
3492 : : c_tmpcounter *parent;
3493 : 1809 : delete_statement_operand_tmp_visitor (c_tmpcounter *p):
3494 : 1809 : parent (p)
3495 : 1809 : {}
3496 : : //void visit_symbol (symbol* e);
3497 : : void visit_arrayindex (arrayindex* e);
3498 : : };
3499 : :
3500 : :
3501 [ - + ]: 1809 : struct delete_statement_operand_visitor:
3502 : : public throwing_visitor
3503 : : {
3504 : : c_unparser *parent;
3505 : 1809 : delete_statement_operand_visitor (c_unparser *p):
3506 : 1809 : throwing_visitor (_("invalid operand of delete expression")),
3507 [ + - ][ + - ]: 1809 : parent (p)
[ + - ]
3508 : 1809 : {}
3509 : : void visit_symbol (symbol* e);
3510 : : void visit_arrayindex (arrayindex* e);
3511 : : };
3512 : :
3513 : : void
3514 : 144 : delete_statement_operand_visitor::visit_symbol (symbol* e)
3515 : : {
3516 [ - + ]: 144 : assert (e->referent != 0);
3517 [ + + ]: 144 : if (e->referent->arity > 0)
3518 : : {
3519 [ + - ]: 72 : mapvar mvar = parent->getmap(e->referent, e->tok);
3520 : : /* NB: Memory deallocation/allocation operations
3521 : : are not generally safe.
3522 : : parent->o->newline() << mvar.fini ();
3523 : : parent->o->newline() << mvar.init ();
3524 : : */
3525 [ + + ]: 72 : if (mvar.is_parallel())
3526 [ + - ][ + - ]: 37 : parent->o->newline() << "_stp_pmap_clear (" << mvar.value() << ");";
[ + - ][ + - ]
[ + - ][ + - ]
3527 : : else
3528 [ + - ][ + - ]: 72 : parent->o->newline() << "_stp_map_clear (" << mvar.value() << ");";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3529 : : }
3530 : : else
3531 : : {
3532 [ + - ]: 72 : var v = parent->getvar(e->referent, e->tok);
3533 [ + + + - ]: 72 : switch (e->type)
3534 : : {
3535 : : case pe_stats:
3536 [ + - ][ + - ]: 65 : parent->o->newline() << "_stp_stat_clear (" << v.value() << ");";
[ + - ][ + - ]
[ + - ][ + - ]
3537 : 65 : break;
3538 : : case pe_long:
3539 [ + - ][ + - ]: 4 : parent->o->newline() << v.value() << " = 0;";
[ + - ][ + - ]
[ + - ]
3540 : 4 : break;
3541 : : case pe_string:
3542 [ + - ][ + - ]: 3 : parent->o->newline() << v.value() << "[0] = '\\0';";
[ + - ][ + - ]
[ + - ]
3543 : 3 : break;
3544 : : case pe_unknown:
3545 : : default:
3546 [ # # ][ # # ]: 0 : throw semantic_error(_("Cannot delete unknown expression type"), e->tok);
3547 [ + - ]: 72 : }
3548 : : }
3549 : 144 : }
3550 : :
3551 : : void
3552 : 1665 : delete_statement_operand_tmp_visitor::visit_arrayindex (arrayindex* e)
3553 : : {
3554 : : symbol *array;
3555 : : hist_op *hist;
3556 [ + - ]: 1665 : classify_indexable (e->base, array, hist);
3557 : :
3558 [ + - ]: 1665 : if (array)
3559 : : {
3560 [ - + ]: 1665 : assert (array->referent != 0);
3561 : 1665 : vardecl* r = array->referent;
3562 : :
3563 : : // One temporary per index dimension.
3564 [ + + ]: 3998 : for (unsigned i=0; i<r->index_types.size(); i++)
3565 : : {
3566 [ + - ]: 2333 : tmpvar ix = parent->parent->gensym (r->index_types[i]);
3567 [ + - ]: 2333 : ix.declare (*(parent->parent));
3568 [ + - ]: 2333 : e->indexes[i]->visit(parent);
3569 [ + - ]: 2333 : }
3570 : : }
3571 : : else
3572 : : {
3573 [ # # ][ # # ]: 0 : throw semantic_error(_("cannot delete histogram bucket entries\n"), e->tok);
3574 : : }
3575 : 1665 : }
3576 : :
3577 : : void
3578 : 1665 : delete_statement_operand_visitor::visit_arrayindex (arrayindex* e)
3579 : : {
3580 : : symbol *array;
3581 : : hist_op *hist;
3582 [ + - ]: 1665 : classify_indexable (e->base, array, hist);
3583 : :
3584 [ + - ]: 1665 : if (array)
3585 : : {
3586 [ + - ]: 1665 : vector<tmpvar> idx;
3587 [ + - ]: 1665 : parent->load_map_indices (e, idx);
3588 : :
3589 : : {
3590 [ + - ]: 1665 : mapvar mvar = parent->getmap (array->referent, e->tok);
3591 [ + - ][ + - ]: 1665 : parent->o->newline() << mvar.del (idx) << ";";
[ + - ][ + - ]
[ + - ][ + - ]
3592 [ + - ]: 1665 : }
3593 : : }
3594 : : else
3595 : : {
3596 [ # # ][ # # ]: 0 : throw semantic_error(_("cannot delete histogram bucket entries\n"), e->tok);
3597 : : }
3598 : 1665 : }
3599 : :
3600 : :
3601 : : void
3602 : 1809 : c_tmpcounter::visit_delete_statement (delete_statement* s)
3603 : : {
3604 [ + - ]: 1809 : delete_statement_operand_tmp_visitor dv (this);
3605 [ + - ][ + - ]: 1809 : s->value->visit (&dv);
3606 : 1809 : }
3607 : :
3608 : :
3609 : : void
3610 : 1809 : c_unparser::visit_delete_statement (delete_statement* s)
3611 : : {
3612 [ + - ]: 1809 : delete_statement_operand_visitor dv (this);
3613 [ + - ]: 1809 : s->value->visit (&dv);
3614 [ + - ][ + - ]: 1809 : record_actions(1, s->tok);
3615 : 1809 : }
3616 : :
3617 : :
3618 : : void
3619 : 40 : c_unparser::visit_break_statement (break_statement* s)
3620 : : {
3621 [ + + ]: 40 : if (loop_break_labels.empty())
3622 [ + - ][ + - ]: 1 : throw semantic_error (_("cannot 'break' outside loop"), s->tok);
3623 : :
3624 : 39 : record_actions(1, s->tok, true);
3625 : 39 : o->newline() << "goto " << loop_break_labels.back() << ";";
3626 : 39 : }
3627 : :
3628 : :
3629 : : void
3630 : 53 : c_unparser::visit_continue_statement (continue_statement* s)
3631 : : {
3632 [ + + ]: 53 : if (loop_continue_labels.empty())
3633 [ + - ][ + - ]: 1 : throw semantic_error (_("cannot 'continue' outside loop"), s->tok);
3634 : :
3635 : 52 : record_actions(1, s->tok, true);
3636 : 52 : o->newline() << "goto " << loop_continue_labels.back() << ";";
3637 : 52 : }
3638 : :
3639 : :
3640 : :
3641 : : void
3642 : 42528 : c_unparser::visit_literal_string (literal_string* e)
3643 : : {
3644 : 42528 : const string& v = e->value;
3645 : 42528 : o->line() << '"';
3646 [ + + ]: 382129 : for (unsigned i=0; i<v.size(); i++)
3647 : : // NB: The backslash character is specifically passed through as is.
3648 : : // This is because our parser treats "\" as an ordinary character, not
3649 : : // an escape sequence, leaving it to the C compiler (and this function)
3650 : : // to treat it as such. If we were to escape it, there would be no way
3651 : : // of generating C-level escapes from script code.
3652 : : // See also print_format::components_to_string and lex_cast_qstring
3653 [ + + ]: 339601 : if (v[i] == '"') // or other escapeworthy characters?
3654 : 808 : o->line() << '\\' << '"';
3655 : : else
3656 : 338793 : o->line() << v[i];
3657 : 42528 : o->line() << '"';
3658 : 42528 : }
3659 : :
3660 : :
3661 : : void
3662 : 33725 : c_unparser::visit_literal_number (literal_number* e)
3663 : : {
3664 : : // This looks ugly, but tries to be warning-free on 32- and 64-bit
3665 : : // hosts.
3666 : : // NB: this needs to be signed!
3667 [ + + ]: 33725 : if (e->value == -9223372036854775807LL-1) // PR 5023
3668 : 12 : o->line() << "((int64_t)" << (unsigned long long) e->value << "ULL)";
3669 : : else
3670 : 33713 : o->line() << "((int64_t)" << e->value << "LL)";
3671 : 33725 : }
3672 : :
3673 : :
3674 : : void
3675 : 2486 : c_tmpcounter::visit_binary_expression (binary_expression* e)
3676 : : {
3677 [ + + ][ + + ]: 2486 : if (e->op == "/" || e->op == "%")
[ + + ]
3678 : : {
3679 [ + - ]: 176 : tmpvar left = parent->gensym (pe_long);
3680 [ + - ]: 176 : tmpvar right = parent->gensym (pe_long);
3681 [ + + ]: 176 : if (e->left->tok->type != tok_number)
3682 [ + - ]: 165 : left.declare (*parent);
3683 [ + + ]: 176 : if (e->right->tok->type != tok_number)
3684 [ + - ][ + - ]: 176 : right.declare (*parent);
[ + - ]
3685 : : }
3686 : :
3687 : 2486 : e->left->visit (this);
3688 : 2486 : e->right->visit (this);
3689 : 2486 : }
3690 : :
3691 : :
3692 : : void
3693 : 1858 : c_unparser::visit_embedded_expr (embedded_expr* e)
3694 : : {
3695 : 1858 : o->line() << "(";
3696 : :
3697 : : // Automatically add a call to assert_is_myproc to any code tagged with
3698 : : // /* myproc-unprivileged */
3699 [ - + ]: 1858 : if (e->code.find ("/* myproc-unprivileged */") != string::npos)
3700 : 0 : o->line() << "({ assert_is_myproc(); }), ";
3701 : :
3702 [ + + ]: 1858 : if (e->type == pe_long)
3703 : 1450 : o->line() << "((int64_t) (" << e->code << "))";
3704 [ + - ]: 408 : else if (e->type == pe_string)
3705 : 408 : o->line() << "((const char *) (" << e->code << "))";
3706 : : else
3707 [ # # ][ # # ]: 0 : throw semantic_error (_("expected numeric or string type"), e->tok);
3708 : :
3709 : 1858 : o->line() << ")";
3710 : 1858 : }
3711 : :
3712 : :
3713 : : void
3714 : 2486 : c_unparser::visit_binary_expression (binary_expression* e)
3715 : : {
3716 [ + - ][ + - ]: 2486 : if (e->type != pe_long ||
[ - + ]
3717 : : e->left->type != pe_long ||
3718 : : e->right->type != pe_long)
3719 [ # # ][ # # ]: 0 : throw semantic_error (_("expected numeric types"), e->tok);
3720 : :
3721 [ + + + + : 7619 : if (e->op == "+" ||
+ + + + +
+ - + ]
[ + + ]
3722 : 2159 : e->op == "-" ||
3723 : 1330 : e->op == "*" ||
3724 : 1174 : e->op == "&" ||
3725 : 237 : e->op == "|" ||
3726 : 233 : e->op == "^")
3727 : : {
3728 : 2253 : o->line() << "((";
3729 : 2253 : e->left->visit (this);
3730 : 2253 : o->line() << ") " << e->op << " (";
3731 : 2253 : e->right->visit (this);
3732 : 2253 : o->line() << "))";
3733 : : }
3734 [ + + + + ]: 418 : else if (e->op == ">>" ||
[ + + ]
3735 : 185 : e->op == "<<")
3736 : : {
3737 : 57 : o->line() << "((";
3738 : 57 : e->left->visit (this);
3739 : 57 : o->line() << ") " << e->op << "max(min(";
3740 : 57 : e->right->visit (this);
3741 : 57 : o->line() << ", (int64_t)64LL), (int64_t)0LL))"; // between 0 and 64
3742 : : }
3743 [ + + + - ]: 214 : else if (e->op == "/" ||
[ + - ]
3744 : 38 : e->op == "%")
3745 : : {
3746 : : // % and / need a division-by-zero check; and thus two temporaries
3747 : : // for proper evaluation order
3748 [ + - ]: 176 : tmpvar left = gensym (pe_long);
3749 [ + - ]: 176 : tmpvar right = gensym (pe_long);
3750 : :
3751 [ + - ]: 176 : o->line() << "({";
3752 [ + - ]: 176 : o->indent(1);
3753 : :
3754 [ + + ]: 176 : if (e->left->tok->type == tok_number)
3755 [ + - ][ + - ]: 11 : left.override(c_expression(e->left));
[ + - ]
3756 : : else
3757 : : {
3758 [ + - ][ + - ]: 165 : o->newline() << left << " = ";
[ + - ]
3759 [ + - ]: 165 : e->left->visit (this);
3760 [ + - ]: 165 : o->line() << ";";
3761 : : }
3762 : :
3763 [ + + ]: 176 : if (e->right->tok->type == tok_number)
3764 [ + - ][ + - ]: 129 : right.override(c_expression(e->right));
[ + - ]
3765 : : else
3766 : : {
3767 [ + - ][ + - ]: 47 : o->newline() << right << " = ";
[ + - ]
3768 [ + - ]: 47 : e->right->visit (this);
3769 [ + - ]: 47 : o->line() << ";";
3770 : : }
3771 : :
3772 [ + - ][ + - ]: 176 : o->newline() << "if (unlikely(!" << right << ")) {";
[ + - ][ + - ]
3773 [ + - ][ + - ]: 176 : o->newline(1) << "c->last_error = ";
3774 [ + - ]: 176 : o->line() << STAP_T_03;
3775 [ + - ][ + - ]: 176 : o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
[ + - ][ + - ]
[ + - ][ + - ]
3776 [ + - ][ + - ]: 176 : o->newline() << "goto out;";
3777 [ + - ][ + - ]: 176 : o->newline(-1) << "}";
3778 [ + - ][ + - ]: 176 : o->newline() << ((e->op == "/") ? "_stp_div64" : "_stp_mod64")
[ + + ][ + - ]
3779 [ + - ][ + - ]: 176 : << " (NULL, " << left << ", " << right << ");";
[ + - ][ + - ]
[ + - ]
3780 : :
3781 [ + - ][ + - ]: 176 : o->newline(-1) << "})";
[ + - ][ + - ]
3782 : : }
3783 : : else
3784 [ # # ][ # # ]: 0 : throw semantic_error (_("operator not yet implemented"), e->tok);
3785 : 2486 : }
3786 : :
3787 : :
3788 : : void
3789 : 958 : c_unparser::visit_unary_expression (unary_expression* e)
3790 : : {
3791 [ + - ][ - + ]: 958 : if (e->type != pe_long ||
3792 : : e->operand->type != pe_long)
3793 [ # # ][ # # ]: 0 : throw semantic_error (_("expected numeric types"), e->tok);
3794 : :
3795 [ + + ]: 958 : if (e->op == "-")
3796 : : {
3797 : : // NB: Subtraction is special, since negative literals in the
3798 : : // script language show up as unary negations over positive
3799 : : // literals here. This makes it "exciting" for emitting pure
3800 : : // C since: - 0x8000_0000_0000_0000 ==> - (- 9223372036854775808)
3801 : : // This would constitute a signed overflow, which gcc warns on
3802 : : // unless -ftrapv/-J are in CFLAGS - which they're not.
3803 : :
3804 : 22 : o->line() << "(int64_t)(0 " << e->op << " (uint64_t)(";
3805 : 22 : e->operand->visit (this);
3806 : 22 : o->line() << "))";
3807 : : }
3808 : : else
3809 : : {
3810 : 936 : o->line() << "(" << e->op << " (";
3811 : 936 : e->operand->visit (this);
3812 : 936 : o->line() << "))";
3813 : : }
3814 : 958 : }
3815 : :
3816 : : void
3817 : 372 : c_unparser::visit_logical_or_expr (logical_or_expr* e)
3818 : : {
3819 [ + - ][ + - ]: 372 : if (e->type != pe_long ||
[ - + ]
3820 : : e->left->type != pe_long ||
3821 : : e->right->type != pe_long)
3822 [ # # ][ # # ]: 0 : throw semantic_error (_("expected numeric types"), e->tok);
3823 : :
3824 : 372 : o->line() << "((";
3825 : 372 : e->left->visit (this);
3826 : 372 : o->line() << ") " << e->op << " (";
3827 : 372 : e->right->visit (this);
3828 : 372 : o->line() << "))";
3829 : 372 : }
3830 : :
3831 : :
3832 : : void
3833 : 488 : c_unparser::visit_logical_and_expr (logical_and_expr* e)
3834 : : {
3835 [ + - ][ + - ]: 488 : if (e->type != pe_long ||
[ - + ]
3836 : : e->left->type != pe_long ||
3837 : : e->right->type != pe_long)
3838 [ # # ][ # # ]: 0 : throw semantic_error (_("expected numeric types"), e->tok);
3839 : :
3840 : 488 : o->line() << "((";
3841 : 488 : e->left->visit (this);
3842 : 488 : o->line() << ") " << e->op << " (";
3843 : 488 : e->right->visit (this);
3844 : 488 : o->line() << "))";
3845 : 488 : }
3846 : :
3847 : :
3848 : : void
3849 : 359 : c_tmpcounter::visit_array_in (array_in* e)
3850 : : {
3851 : : symbol *array;
3852 : : hist_op *hist;
3853 [ + - ]: 359 : classify_indexable (e->operand->base, array, hist);
3854 : :
3855 [ + + ]: 359 : if (array)
3856 : : {
3857 [ - + ]: 358 : assert (array->referent != 0);
3858 : 358 : vardecl* r = array->referent;
3859 : :
3860 : : // One temporary per index dimension.
3861 [ + + ]: 993 : for (unsigned i=0; i<r->index_types.size(); i++)
3862 : : {
3863 [ + - ]: 635 : tmpvar ix = parent->gensym (r->index_types[i]);
3864 [ + - ]: 635 : ix.declare (*parent);
3865 [ + - ]: 635 : e->operand->indexes[i]->visit(this);
3866 [ + - ]: 635 : }
3867 : :
3868 : : // A boolean result.
3869 [ + - ]: 358 : tmpvar res = parent->gensym (e->type);
3870 [ + - ][ + - ]: 358 : res.declare (*parent);
3871 : : }
3872 : : else
3873 : : {
3874 : : // By definition:
3875 : : //
3876 : : // 'foo in @hist_op(...)' is true iff
3877 : : // '@hist_op(...)[foo]' is nonzero
3878 : : //
3879 : : // so we just delegate to the latter call, since int64_t is also
3880 : : // our boolean type.
3881 [ + - ]: 1 : e->operand->visit(this);
3882 : : }
3883 : 359 : }
3884 : :
3885 : :
3886 : : void
3887 : 359 : c_unparser::visit_array_in (array_in* e)
3888 : : {
3889 : : symbol *array;
3890 : : hist_op *hist;
3891 [ + - ]: 359 : classify_indexable (e->operand->base, array, hist);
3892 : :
3893 [ + + ]: 359 : if (array)
3894 : : {
3895 [ + - ]: 358 : stmt_expr block(*this);
3896 : :
3897 [ + - ]: 358 : vector<tmpvar> idx;
3898 [ + - ]: 358 : load_map_indices (e->operand, idx);
3899 : : // o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
3900 : :
3901 [ + - ]: 358 : tmpvar res = gensym (pe_long);
3902 [ + - ]: 358 : mapvar mvar = getmap (array->referent, e->tok);
3903 [ + - ][ + - ]: 358 : c_assign (res, mvar.exists(idx), e->tok);
[ + - ]
3904 : :
3905 [ + - ][ + - ]: 358 : o->newline() << res << ";";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3906 : : }
3907 : : else
3908 : : {
3909 : : // By definition:
3910 : : //
3911 : : // 'foo in @hist_op(...)' is true iff
3912 : : // '@hist_op(...)[foo]' is nonzero
3913 : : //
3914 : : // so we just delegate to the latter call, since int64_t is also
3915 : : // our boolean type.
3916 [ + - ]: 1 : e->operand->visit(this);
3917 : : }
3918 : 359 : }
3919 : :
3920 : : void
3921 : 44 : c_tmpcounter::visit_regex_query (regex_query* e)
3922 : : {
3923 : : // TODOXXX if e->right is always a literal, do we still need to do
3924 : : // the 'save at least one in a tmpvar' trick as seen in
3925 : : // visit_comparison?
3926 : 44 : e->left->visit(this);
3927 : 44 : e->right->visit(this);
3928 : 44 : }
3929 : :
3930 : : void
3931 : 44 : c_unparser::visit_regex_query (regex_query* e)
3932 : : {
3933 : 44 : o->line() << "(";
3934 : 44 : o->indent(1);
3935 : 44 : o->newline();
3936 [ + + ]: 44 : if (e->op == "!~") o->line() << "!";
3937 : 44 : stapdfa *dfa = session->dfas[e->re->value];
3938 : 44 : dfa->emit_matchop_start (o);
3939 : 44 : e->left->visit(this);
3940 : 44 : dfa->emit_matchop_end (o);
3941 : 44 : o->newline(-1) << ")";
3942 : 44 : }
3943 : :
3944 : : void
3945 : 8280 : c_tmpcounter::visit_comparison (comparison* e)
3946 : : {
3947 : : // When computing string operands, their results may be in overlapping
3948 : : // __retvalue memory, so we need to save at least one in a tmpvar.
3949 [ + + ]: 8280 : if (e->left->type == pe_string)
3950 : : {
3951 [ + - ]: 1070 : tmpvar left = parent->gensym (pe_string);
3952 [ + + ]: 1070 : if (e->left->tok->type != tok_string)
3953 [ + - ][ + - ]: 1070 : left.declare (*parent);
3954 : : }
3955 : :
3956 : 8280 : e->left->visit (this);
3957 : 8280 : e->right->visit (this);
3958 : 8280 : }
3959 : :
3960 : : void
3961 : 8280 : c_unparser::visit_comparison (comparison* e)
3962 : : {
3963 : 8280 : o->line() << "(";
3964 : :
3965 [ + + ]: 8280 : if (e->left->type == pe_string)
3966 : : {
3967 [ - + ]: 1070 : if (e->right->type != pe_string)
3968 [ # # ][ # # ]: 0 : throw semantic_error (_("expected string types"), e->tok);
3969 : :
3970 [ + - ]: 1070 : o->line() << "({";
3971 [ + - ]: 1070 : o->indent(1);
3972 : :
3973 [ + - ]: 1070 : tmpvar left = gensym (pe_string);
3974 [ + + ]: 1070 : if (e->left->tok->type == tok_string)
3975 [ + - ][ + - ]: 6 : left.override(c_expression(e->left));
[ + - ]
3976 : : else
3977 [ + - ][ + - ]: 1064 : c_assign (left.value(), e->left, "assignment");
[ + - ][ + - ]
[ + - ]
3978 : :
3979 [ + - ][ + - ]: 1070 : o->newline() << "strncmp (" << left << ", ";
[ + - ][ + - ]
3980 [ + - ]: 1070 : e->right->visit (this);
3981 [ + - ][ + - ]: 1070 : o->line() << ", MAXSTRINGLEN) " << e->op << " 0;";
[ + - ]
3982 [ + - ][ + - ]: 1070 : o->newline(-1) << "})";
[ + - ]
3983 : : }
3984 [ + - ]: 7210 : else if (e->left->type == pe_long)
3985 : : {
3986 [ - + ]: 7210 : if (e->right->type != pe_long)
3987 [ # # ][ # # ]: 0 : throw semantic_error (_("expected numeric types"), e->tok);
3988 : :
3989 : 7210 : o->line() << "((";
3990 : 7210 : e->left->visit (this);
3991 : 7210 : o->line() << ") " << e->op << " (";
3992 : 7210 : e->right->visit (this);
3993 : 7210 : o->line() << "))";
3994 : : }
3995 : : else
3996 [ # # ][ # # ]: 0 : throw semantic_error (_("unexpected type"), e->left->tok);
3997 : :
3998 : 8280 : o->line() << ")";
3999 : 8280 : }
4000 : :
4001 : :
4002 : : void
4003 : 1646 : c_tmpcounter::visit_concatenation (concatenation* e)
4004 : : {
4005 [ + - ]: 1646 : tmpvar t = parent->gensym (e->type);
4006 [ + - ]: 1646 : t.declare (*parent);
4007 [ + - ]: 1646 : e->left->visit (this);
4008 [ + - ][ + - ]: 1646 : e->right->visit (this);
4009 : 1646 : }
4010 : :
4011 : :
4012 : : void
4013 : 1646 : c_unparser::visit_concatenation (concatenation* e)
4014 : : {
4015 [ + - ][ - + ]: 1646 : if (e->op != ".")
4016 [ # # ][ # # ]: 0 : throw semantic_error (_("unexpected concatenation operator"), e->tok);
4017 : :
4018 [ + - ][ + - ]: 1646 : if (e->type != pe_string ||
[ - + ]
4019 : : e->left->type != pe_string ||
4020 : : e->right->type != pe_string)
4021 [ # # ][ # # ]: 0 : throw semantic_error (_("expected string types"), e->tok);
4022 : :
4023 [ + - ]: 1646 : tmpvar t = gensym (e->type);
4024 : :
4025 [ + - ]: 1646 : o->line() << "({ ";
4026 [ + - ]: 1646 : o->indent(1);
4027 : : // o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
4028 [ + - ][ + - ]: 1646 : c_assign (t.value(), e->left, "assignment");
[ + - ][ + - ]
[ + - ]
4029 [ + - ][ + - ]: 1646 : c_strcat (t.value(), e->right);
[ + - ]
4030 [ + - ][ + - ]: 1646 : o->newline() << t << ";";
[ + - ]
4031 [ + - ][ + - ]: 1646 : o->newline(-1) << "})";
[ + - ]
4032 : 1646 : }
4033 : :
4034 : :
4035 : : void
4036 : 197 : c_unparser::visit_ternary_expression (ternary_expression* e)
4037 : : {
4038 [ - + ]: 197 : if (e->cond->type != pe_long)
4039 [ # # ][ # # ]: 0 : throw semantic_error (_("expected numeric condition"), e->cond->tok);
4040 : :
4041 [ + - ][ + - ]: 197 : if (e->truevalue->type != e->falsevalue->type ||
[ + + ][ - + ]
4042 : : e->type != e->truevalue->type ||
4043 : : (e->truevalue->type != pe_long && e->truevalue->type != pe_string))
4044 [ # # ][ # # ]: 0 : throw semantic_error (_("expected matching types"), e->tok);
4045 : :
4046 : 197 : o->line() << "((";
4047 : 197 : e->cond->visit (this);
4048 : 197 : o->line() << ") ? (";
4049 : 197 : e->truevalue->visit (this);
4050 : 197 : o->line() << ") : (";
4051 : 197 : e->falsevalue->visit (this);
4052 : 197 : o->line() << "))";
4053 : 197 : }
4054 : :
4055 : :
4056 : : void
4057 : 33839 : c_tmpcounter::visit_assignment (assignment *e)
4058 : : {
4059 [ + - ]: 33839 : c_tmpcounter_assignment tav (this, e->op, e->right);
4060 [ + - ][ + - ]: 33839 : e->left->visit (& tav);
4061 : 33839 : }
4062 : :
4063 : :
4064 : : void
4065 : 33839 : c_unparser::visit_assignment (assignment* e)
4066 : : {
4067 [ + - ][ + + ]: 33839 : if (e->op == "<<<")
4068 : : {
4069 [ - + ]: 7621 : if (e->type != pe_long)
4070 [ # # ][ # # ]: 0 : throw semantic_error (_("non-number <<< expression"), e->tok);
4071 : :
4072 [ - + ]: 7621 : if (e->left->type != pe_stats)
4073 [ # # ][ # # ]: 0 : throw semantic_error (_("non-stats left operand to <<< expression"), e->left->tok);
4074 : :
4075 [ - + ]: 7621 : if (e->right->type != pe_long)
4076 [ # # ][ # # ]: 0 : throw semantic_error (_("non-number right operand to <<< expression"), e->right->tok);
4077 : :
4078 : : }
4079 : : else
4080 : : {
4081 [ - + ]: 26218 : if (e->type != e->left->type)
4082 [ # # ][ # # ]: 0 : throw semantic_error (_("type mismatch"), e->tok, e->left->tok);
4083 [ - + ]: 26218 : if (e->right->type != e->left->type)
4084 [ # # ][ # # ]: 0 : throw semantic_error (_("type mismatch"), e->right->tok, e->left->tok);
4085 : : }
4086 : :
4087 [ + - ]: 33839 : c_unparser_assignment tav (this, e->op, e->right);
4088 [ + - ][ + - ]: 33839 : e->left->visit (& tav);
4089 : 33839 : }
4090 : :
4091 : :
4092 : : void
4093 : 910 : c_tmpcounter::visit_pre_crement (pre_crement* e)
4094 : : {
4095 [ + - ]: 910 : c_tmpcounter_assignment tav (this, e->op, 0);
4096 [ + - ][ + - ]: 910 : e->operand->visit (& tav);
4097 : 910 : }
4098 : :
4099 : :
4100 : : void
4101 : 910 : c_unparser::visit_pre_crement (pre_crement* e)
4102 : : {
4103 [ + - ][ - + ]: 910 : if (e->type != pe_long ||
4104 : : e->type != e->operand->type)
4105 [ # # ][ # # ]: 0 : throw semantic_error (_("expected numeric type"), e->tok);
4106 : :
4107 [ + - ]: 910 : c_unparser_assignment tav (this, e->op, false);
4108 [ + - ][ + - ]: 910 : e->operand->visit (& tav);
4109 : 910 : }
4110 : :
4111 : :
4112 : : void
4113 : 1509 : c_tmpcounter::visit_post_crement (post_crement* e)
4114 : : {
4115 [ + - ]: 1509 : c_tmpcounter_assignment tav (this, e->op, 0, true);
4116 [ + - ][ + - ]: 1509 : e->operand->visit (& tav);
4117 : 1509 : }
4118 : :
4119 : :
4120 : : void
4121 : 1509 : c_unparser::visit_post_crement (post_crement* e)
4122 : : {
4123 [ + - ][ - + ]: 1509 : if (e->type != pe_long ||
4124 : : e->type != e->operand->type)
4125 [ # # ][ # # ]: 0 : throw semantic_error (_("expected numeric type"), e->tok);
4126 : :
4127 [ + - ]: 1509 : c_unparser_assignment tav (this, e->op, true);
4128 [ + - ][ + - ]: 1509 : e->operand->visit (& tav);
4129 : 1509 : }
4130 : :
4131 : :
4132 : : void
4133 : 36445 : c_unparser::visit_symbol (symbol* e)
4134 : : {
4135 [ - + ]: 36445 : assert (e->referent != 0);
4136 : 36445 : vardecl* r = e->referent;
4137 : :
4138 [ - + ]: 36445 : if (r->index_types.size() != 0)
4139 [ # # ][ # # ]: 0 : throw semantic_error (_("invalid reference to array"), e->tok);
4140 : :
4141 [ + - ]: 36445 : var v = getvar(r, e->tok);
4142 [ + - ][ + - ]: 36445 : o->line() << v;
4143 : 36445 : }
4144 : :
4145 : :
4146 : : void
4147 : 36258 : c_tmpcounter_assignment::prepare_rvalue (tmpvar & rval)
4148 : : {
4149 [ + + ]: 36258 : if (rvalue)
4150 : : {
4151 : : // literal number and strings don't need any temporaries declared
4152 [ + + ][ + + ]: 33839 : if (rvalue->tok->type != tok_number && rvalue->tok->type != tok_string)
4153 : 13006 : rval.declare (*(parent->parent));
4154 : :
4155 : 33839 : rvalue->visit (parent);
4156 : : }
4157 : 36258 : }
4158 : :
4159 : : void
4160 : 28875 : c_tmpcounter_assignment::c_assignop(tmpvar & res)
4161 : : {
4162 [ + + ]: 28875 : if (res.type() == pe_string)
4163 : : {
4164 : : // string assignment doesn't need any temporaries declared
4165 : : }
4166 [ + + ]: 19082 : else if (op == "<<<")
4167 : 238 : res.declare (*(parent->parent));
4168 [ + - ]: 18844 : else if (res.type() == pe_long)
4169 : : {
4170 : : // Only the 'post' operators ('x++') need a temporary declared.
4171 [ + + ]: 18844 : if (post)
4172 : 1509 : res.declare (*(parent->parent));
4173 : : }
4174 : 28875 : }
4175 : :
4176 : : // Assignment expansion is tricky.
4177 : : //
4178 : : // Because assignments are nestable expressions, we have
4179 : : // to emit C constructs that are nestable expressions too.
4180 : : // We have to evaluate the given expressions the proper number of times,
4181 : : // including array indices.
4182 : : // We have to lock the lvalue (if global) against concurrent modification,
4183 : : // especially with modify-assignment operations (+=, ++).
4184 : : // We have to check the rvalue (for division-by-zero checks).
4185 : :
4186 : : // In the normal "pre=false" case, for (A op B) emit:
4187 : : // ({ tmp = B; check(B); lock(A); res = A op tmp; A = res; unlock(A); res; })
4188 : : // In the "pre=true" case, emit instead:
4189 : : // ({ tmp = B; check(B); lock(A); res = A; A = res op tmp; unlock(A); res; })
4190 : : //
4191 : : // (op is the plain operator portion of a combined calculate/assignment:
4192 : : // "+" for "+=", and so on. It is in the "macop" variable below.)
4193 : : //
4194 : : // For array assignments, additional temporaries are used for each
4195 : : // index, which are expanded before the "tmp=B" expression, in order
4196 : : // to consistently order evaluation of lhs before rhs.
4197 : : //
4198 : :
4199 : : void
4200 : 17786 : c_tmpcounter_assignment::visit_symbol (symbol *e)
4201 : : {
4202 [ + + ]: 17786 : exp_type ty = rvalue ? rvalue->type : e->type;
4203 [ + - ]: 17786 : tmpvar rval = parent->parent->gensym (ty);
4204 [ + - ]: 17786 : tmpvar res = parent->parent->gensym (ty);
4205 : :
4206 [ + - ]: 17786 : prepare_rvalue(rval);
4207 : :
4208 [ + - ][ + - ]: 17786 : c_assignop (res);
[ + - ]
4209 : 17786 : }
4210 : :
4211 : :
4212 : : void
4213 : 36258 : c_unparser_assignment::prepare_rvalue (string const & op,
4214 : : tmpvar & rval,
4215 : : token const * tok)
4216 : : {
4217 [ + + ]: 36258 : if (rvalue)
4218 : : {
4219 [ + + ][ + + ]: 33839 : if (rvalue->tok->type == tok_number || rvalue->tok->type == tok_string)
4220 : : // Instead of assigning the numeric or string constant to a
4221 : : // temporary, then assigning the temporary to the final, let's
4222 : : // just override the temporary with the constant.
4223 [ + - ]: 20833 : rval.override(parent->c_expression(rvalue));
4224 : : else
4225 [ + - ][ + - ]: 33839 : parent->c_assign (rval.value(), rvalue, "assignment");
[ + - ]
4226 : : }
4227 : : else
4228 : : {
4229 [ + + ][ + - ]: 2419 : if (op == "++" || op == "--")
[ + - ]
4230 : : // Here is part of the conversion proccess of turning "x++" to
4231 : : // "x += 1".
4232 [ + - ][ + - ]: 2419 : rval.override("1");
[ + - ]
4233 : : else
4234 [ # # ][ # # ]: 0 : throw semantic_error (_("need rvalue for assignment"), tok);
4235 : : }
4236 : 36258 : }
4237 : :
4238 : : void
4239 : 17786 : c_unparser_assignment::visit_symbol (symbol *e)
4240 : : {
4241 [ + - ]: 17786 : stmt_expr block(*parent);
4242 : :
4243 [ - + ]: 17786 : assert (e->referent != 0);
4244 [ - + ]: 17786 : if (e->referent->index_types.size() != 0)
4245 [ # # ][ # # ]: 0 : throw semantic_error (_("unexpected reference to array"), e->tok);
4246 : :
4247 : : // parent->o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
4248 [ + + ]: 17786 : exp_type ty = rvalue ? rvalue->type : e->type;
4249 [ + - ]: 17786 : tmpvar rval = parent->gensym (ty);
4250 [ + - ]: 17786 : tmpvar res = parent->gensym (ty);
4251 : :
4252 [ + - ]: 17786 : prepare_rvalue (op, rval, e->tok);
4253 : :
4254 [ + - ]: 17786 : var lvar = parent->getvar (e->referent, e->tok);
4255 [ + - ]: 17786 : c_assignop (res, lvar, rval, e->tok);
4256 : :
4257 [ + - ][ + - ]: 17786 : parent->o->newline() << res << ";";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4258 : 17786 : }
4259 : :
4260 : :
4261 : : void
4262 : 0 : c_unparser::visit_target_symbol (target_symbol* e)
4263 : : {
4264 [ # # ][ # # ]: 0 : throw semantic_error(_("cannot translate general target-symbol expression"), e->tok);
4265 : : }
4266 : :
4267 : :
4268 : : void
4269 : 0 : c_unparser::visit_cast_op (cast_op* e)
4270 : : {
4271 [ # # ][ # # ]: 0 : throw semantic_error(_("cannot translate general @cast expression"), e->tok);
4272 : : }
4273 : :
4274 : :
4275 : : void
4276 : 0 : c_unparser::visit_defined_op (defined_op* e)
4277 : : {
4278 [ # # ][ # # ]: 0 : throw semantic_error(_("cannot translate general @defined expression"), e->tok);
4279 : : }
4280 : :
4281 : :
4282 : : void
4283 : 0 : c_unparser::visit_entry_op (entry_op* e)
4284 : : {
4285 [ # # ][ # # ]: 0 : throw semantic_error(_("cannot translate general @entry expression"), e->tok);
4286 : : }
4287 : :
4288 : :
4289 : : void
4290 : 0 : c_unparser::visit_perf_op (perf_op* e)
4291 : : {
4292 [ # # ][ # # ]: 0 : throw semantic_error(_("cannot translate general @perf expression"), e->tok);
4293 : : }
4294 : :
4295 : :
4296 : : void
4297 : 21828 : c_tmpcounter::load_map_indices(arrayindex *e)
4298 : : {
4299 : : symbol *array;
4300 : : hist_op *hist;
4301 [ + - ]: 21828 : classify_indexable (e->base, array, hist);
4302 : :
4303 [ + - ]: 21828 : if (array)
4304 : : {
4305 [ - + ]: 21828 : assert (array->referent != 0);
4306 : 21828 : vardecl* r = array->referent;
4307 : :
4308 : : // One temporary per index dimension, except in the case of
4309 : : // number or string constants.
4310 [ + + ]: 52197 : for (unsigned i=0; i<r->index_types.size(); i++)
4311 : : {
4312 [ + - ]: 30369 : tmpvar ix = parent->gensym (r->index_types[i]);
4313 [ + + + + ]: 54685 : if (e->indexes[i]->tok->type == tok_number
[ + + ]
4314 : 24316 : || e->indexes[i]->tok->type == tok_string)
4315 : : {
4316 : : // Do nothing
4317 : : }
4318 : : else
4319 [ + - ]: 11282 : ix.declare (*parent);
4320 [ + - ]: 30369 : e->indexes[i]->visit(this);
4321 [ + - ]: 30369 : }
4322 : : }
4323 : 21828 : }
4324 : :
4325 : :
4326 : : void
4327 : 23865 : c_unparser::load_map_indices(arrayindex *e,
4328 : : vector<tmpvar> & idx)
4329 : : {
4330 : : symbol *array;
4331 : : hist_op *hist;
4332 [ + - ]: 23865 : classify_indexable (e->base, array, hist);
4333 : :
4334 [ + + ]: 23865 : if (array)
4335 : : {
4336 [ + - ]: 23851 : idx.clear();
4337 : :
4338 [ - + ]: 23851 : assert (array->referent != 0);
4339 : 23851 : vardecl* r = array->referent;
4340 : :
4341 [ + - - + ]: 47702 : if (r->index_types.size() == 0 ||
[ - + ]
4342 : 23851 : r->index_types.size() != e->indexes.size())
4343 [ # # ][ # # ]: 0 : throw semantic_error (_("invalid array reference"), e->tok);
4344 : :
4345 [ + + ]: 57188 : for (unsigned i=0; i<r->index_types.size(); i++)
4346 : : {
4347 [ - + ]: 33337 : if (r->index_types[i] != e->indexes[i]->type)
4348 [ # # ][ # # ]: 0 : throw semantic_error (_("array index type mismatch"), e->indexes[i]->tok);
4349 : :
4350 [ + - ]: 33337 : tmpvar ix = gensym (r->index_types[i]);
4351 [ + + + + ]: 60582 : if (e->indexes[i]->tok->type == tok_number
[ + + ]
4352 : 27245 : || e->indexes[i]->tok->type == tok_string)
4353 : : // Instead of assigning the numeric or string constant to a
4354 : : // temporary, then using the temporary, let's just
4355 : : // override the temporary with the constant.
4356 [ + - ][ + - ]: 19142 : ix.override(c_expression(e->indexes[i]));
[ + - ]
4357 : : else
4358 : : {
4359 : : // o->newline() << "c->last_stmt = "
4360 : : // << lex_cast_qstring(*e->indexes[i]->tok) << ";";
4361 [ + - ][ + - ]: 14195 : c_assign (ix.value(), e->indexes[i], "array index copy");
[ + - ][ + - ]
[ + - ]
4362 : : }
4363 [ + - ]: 33337 : idx.push_back (ix);
4364 [ + - ]: 33337 : }
4365 : : }
4366 : : else
4367 : : {
4368 [ - + ]: 14 : assert (e->indexes.size() == 1);
4369 [ - + ]: 14 : assert (e->indexes[0]->type == pe_long);
4370 [ + - ]: 14 : tmpvar ix = gensym (pe_long);
4371 : : // o->newline() << "c->last_stmt = "
4372 : : // << lex_cast_qstring(*e->indexes[0]->tok) << ";";
4373 [ + - ][ + - ]: 14 : c_assign (ix.value(), e->indexes[0], "array index copy");
[ + - ][ + - ]
[ + - ]
4374 [ + - ][ + - ]: 14 : idx.push_back(ix);
4375 : : }
4376 : 23865 : }
4377 : :
4378 : :
4379 : : void
4380 : 694 : c_tmpcounter::load_aggregate (expression *e)
4381 : : {
4382 [ + - ]: 694 : symbol *sym = get_symbol_within_expression (e);
4383 [ + - ]: 694 : string agg_value;
4384 : 694 : arrayindex* arr = NULL;
4385 [ + - ]: 694 : expression_is_arrayindex (e, arr);
4386 : :
4387 : : // If we have a foreach_loop value, we don't need tmps for indexes
4388 [ + + ][ + + ]: 1139 : if (sym->referent->arity != 0 &&
[ + + ]
4389 [ + - ]: 445 : !parent->get_foreach_loop_value(arr, agg_value))
4390 : : {
4391 [ - + ]: 85 : if (!arr)
4392 [ # # ][ # # ]: 0 : throw semantic_error(_("expected arrayindex expression"), e->tok);
4393 [ + - ]: 85 : load_map_indices (arr);
4394 [ + - ]: 694 : }
4395 : 694 : }
4396 : :
4397 : :
4398 : : var*
4399 : 694 : c_unparser::load_aggregate (expression *e, aggvar & agg)
4400 : : {
4401 : 694 : symbol *sym = get_symbol_within_expression (e);
4402 : :
4403 [ - + ]: 694 : if (sym->referent->type != pe_stats)
4404 [ # # ][ # # ]: 0 : throw semantic_error (_("unexpected aggregate of non-statistic"), sym->tok);
4405 : :
4406 : : var *v;
4407 [ + + ]: 694 : if (sym->referent->arity == 0)
4408 : : {
4409 [ + - ]: 249 : v = new var(getvar(sym->referent, sym->tok));
4410 : : // o->newline() << "c->last_stmt = " << lex_cast_qstring(*sym->tok) << ";";
4411 : 249 : o->newline() << agg << " = _stp_stat_get (" << *v << ", 0);";
4412 : : }
4413 : : else
4414 : : {
4415 [ + - ][ + - ]: 445 : mapvar *mv = new mapvar(getmap(sym->referent, sym->tok));
4416 : 445 : v = mv;
4417 : :
4418 : 445 : arrayindex *arr = NULL;
4419 [ + - ][ - + ]: 445 : if (!expression_is_arrayindex (e, arr))
4420 [ # # ][ # # ]: 0 : throw semantic_error(_("unexpected aggregate of non-arrayindex"), e->tok);
4421 : :
4422 : : // If we have a foreach_loop value, we don't need to index the map
4423 [ + - ]: 445 : string agg_value;
4424 [ + - ][ + + ]: 445 : if (get_foreach_loop_value(arr, agg_value))
4425 [ + - ][ + - ]: 360 : o->newline() << agg << " = " << agg_value << ";";
[ + - ][ + - ]
[ + - ]
4426 : : else
4427 : : {
4428 [ + - ]: 85 : vector<tmpvar> idx;
4429 [ + - ]: 85 : load_map_indices (arr, idx);
4430 : : // o->newline() << "c->last_stmt = " << lex_cast_qstring(*sym->tok) << ";";
4431 [ + - ][ + - ]: 85 : bool pre_agg = (aggregations_active.count(mv->value()) > 0);
[ + - ]
4432 [ + - ][ + - ]: 85 : o->newline() << agg << " = " << mv->get(idx, pre_agg) << ";";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
4433 [ + - ]: 445 : }
4434 : : }
4435 : :
4436 : 694 : return v;
4437 : : }
4438 : :
4439 : :
4440 : : string
4441 : 14 : c_unparser::histogram_index_check(var & base, tmpvar & idx) const
4442 : : {
4443 : : return "((" + idx.value() + " >= 0)"
4444 [ + - ][ + - ]: 14 : + " && (" + idx.value() + " < " + base.buckets() + "))";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4445 : : }
4446 : :
4447 : :
4448 : : void
4449 : 3419 : c_tmpcounter::visit_arrayindex (arrayindex *e)
4450 : : {
4451 : : // If we have a foreach_loop value, no other tmps are needed
4452 [ + - ]: 3419 : string ai_value;
4453 [ + - ][ + + ]: 3419 : if (parent->get_foreach_loop_value(e, ai_value))
4454 : 3419 : return;
4455 : :
4456 : : symbol *array;
4457 : : hist_op *hist;
4458 [ + - ]: 3285 : classify_indexable (e->base, array, hist);
4459 : :
4460 [ + + ]: 3285 : if (array)
4461 : : {
4462 [ + - ]: 3271 : load_map_indices(e);
4463 : :
4464 : : // The index-expression result.
4465 [ + - ]: 3271 : tmpvar res = parent->gensym (e->type);
4466 [ + - ][ + - ]: 3271 : res.declare (*parent);
4467 : : }
4468 : : else
4469 : : {
4470 : :
4471 [ - + ]: 14 : assert(hist);
4472 : :
4473 : : // Note: this is a slightly tricker-than-it-looks allocation of
4474 : : // temporaries. The reason is that we're in the branch handling
4475 : : // histogram-indexing, and the histogram might be build over an
4476 : : // indexable entity itself. For example if we have:
4477 : : //
4478 : : // global foo
4479 : : // ...
4480 : : // foo[getpid(), geteuid()] <<< 1
4481 : : // ...
4482 : : // print @log_hist(foo[pid, euid])[bucket]
4483 : : //
4484 : : // We are looking at the @log_hist(...)[bucket] expression, so
4485 : : // allocating one tmpvar for calculating bucket (the "index" of
4486 : : // this arrayindex expression), and one tmpvar for storing the
4487 : : // result in, just as normal.
4488 : : //
4489 : : // But we are *also* going to call load_aggregate on foo, which
4490 : : // will itself require tmpvars for each of its indices. Since
4491 : : // this is not handled by delving into the subexpression (it
4492 : : // would be if hist were first-class in the type system, but
4493 : : // it's not) we we allocate all the tmpvars used in such a
4494 : : // subexpression up here: first our own aggvar, then our index
4495 : : // (bucket) tmpvar, then all the index tmpvars of our
4496 : : // pe_stat-valued subexpression, then our result.
4497 : :
4498 : :
4499 : : // First all the stuff related to indexing into the histogram
4500 : :
4501 [ - + ]: 14 : if (e->indexes.size() != 1)
4502 [ # # ][ # # ]: 0 : throw semantic_error(_("Invalid indexing of histogram"), e->tok);
4503 [ + - ]: 14 : tmpvar ix = parent->gensym (pe_long);
4504 [ + - ]: 14 : ix.declare (*parent);
4505 [ + - ]: 14 : e->indexes[0]->visit(this);
4506 [ + - ]: 14 : tmpvar res = parent->gensym (pe_long);
4507 [ + - ]: 14 : res.declare (*parent);
4508 : :
4509 : : // Then the aggregate, and all the tmpvars needed by our call to
4510 : : // load_aggregate().
4511 : :
4512 [ + - ]: 14 : aggvar agg = parent->gensym_aggregate ();
4513 [ + - ]: 14 : agg.declare(*(this->parent));
4514 [ + - ][ + - ]: 3285 : load_aggregate (hist->stat);
[ + - ][ + - ]
4515 [ + - ][ + + ]: 3419 : }
4516 : : }
4517 : :
4518 : :
4519 : : void
4520 : 3419 : c_unparser::visit_arrayindex (arrayindex* e)
4521 : : {
4522 : : // If we have a foreach_loop value, use it and call it a day!
4523 [ + - ]: 3419 : string ai_value;
4524 [ + - ][ + + ]: 3419 : if (get_foreach_loop_value(e, ai_value))
4525 : : {
4526 [ + - ]: 134 : o->line() << ai_value;
4527 : 3419 : return;
4528 : : }
4529 : :
4530 : : symbol *array;
4531 : : hist_op *hist;
4532 [ + - ]: 3285 : classify_indexable (e->base, array, hist);
4533 : :
4534 [ + + ]: 3285 : if (array)
4535 : : {
4536 : : // Visiting an statistic-valued array in a non-lvalue context is prohibited.
4537 [ - + ]: 3271 : if (array->referent->type == pe_stats)
4538 [ # # ][ # # ]: 0 : throw semantic_error (_("statistic-valued array in rvalue context"), e->tok);
4539 : :
4540 [ + - ]: 3271 : stmt_expr block(*this);
4541 : :
4542 : : // NB: Do not adjust the order of the next few lines; the tmpvar
4543 : : // allocation order must remain the same between
4544 : : // c_unparser::visit_arrayindex and c_tmpcounter::visit_arrayindex
4545 : :
4546 [ + - ]: 3271 : vector<tmpvar> idx;
4547 [ + - ]: 3271 : load_map_indices (e, idx);
4548 [ + - ]: 3271 : tmpvar res = gensym (e->type);
4549 : :
4550 [ + - ]: 3271 : mapvar mvar = getmap (array->referent, e->tok);
4551 : : // o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
4552 [ + - ][ + - ]: 3271 : c_assign (res, mvar.get(idx), e->tok);
[ + - ]
4553 : :
4554 [ + - ][ + - ]: 3271 : o->newline() << res << ";";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4555 : : }
4556 : : else
4557 : : {
4558 : : // See commentary in c_tmpcounter::visit_arrayindex
4559 : :
4560 [ - + ]: 14 : assert(hist);
4561 [ + - ]: 14 : stmt_expr block(*this);
4562 : :
4563 : : // NB: Do not adjust the order of the next few lines; the tmpvar
4564 : : // allocation order must remain the same between
4565 : : // c_unparser::visit_arrayindex and c_tmpcounter::visit_arrayindex
4566 : :
4567 [ + - ]: 14 : vector<tmpvar> idx;
4568 [ + - ]: 14 : load_map_indices (e, idx);
4569 [ + - ]: 14 : tmpvar res = gensym (e->type);
4570 : :
4571 [ + - ]: 14 : aggvar agg = gensym_aggregate ();
4572 : :
4573 : : // These should have faulted during elaboration if not true.
4574 [ - + ]: 14 : assert(idx.size() == 1);
4575 [ - + ]: 14 : assert(idx[0].type() == pe_long);
4576 : :
4577 [ + - ]: 14 : var *v = load_aggregate(hist->stat, agg);
4578 [ + - ]: 14 : v->assert_hist_compatible(*hist);
4579 : :
4580 [ + - ][ + - ]: 14 : o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
[ + - ][ + - ]
[ + - ][ + - ]
4581 : :
4582 : : // PR 2142+2610: empty aggregates
4583 [ + - ][ + - ]: 28 : o->newline() << "if (unlikely (" << agg.value() << " == NULL)"
[ + - ][ + - ]
[ + - ][ + - ]
4584 [ + - ][ + - ]: 14 : << " || " << agg.value() << "->count == 0) {";
[ + - ][ + - ]
[ + - ]
4585 [ + - ][ + - ]: 14 : o->newline(1) << "c->last_error = ";
4586 [ + - ]: 14 : o->line() << STAP_T_06;
4587 [ + - ][ + - ]: 14 : o->newline() << "goto out;";
4588 [ + - ][ + - ]: 14 : o->newline(-1) << "} else {";
4589 [ + - ][ + - ]: 14 : o->newline(1) << "if (" << histogram_index_check(*v, idx[0]) << ")";
[ + - ][ + - ]
[ + - ][ + - ]
4590 [ + - ][ + - ]: 14 : o->newline(1) << res << " = " << agg << "->histogram[" << idx[0] << "];";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4591 [ + - ][ + - ]: 14 : o->newline(-1) << "else {";
4592 [ + - ][ + - ]: 14 : o->newline(1) << "c->last_error = ";
4593 [ + - ]: 14 : o->line() << STAP_T_07;
4594 [ + - ][ + - ]: 14 : o->newline() << "goto out;";
4595 [ + - ][ + - ]: 14 : o->newline(-1) << "}";
4596 : :
4597 [ + - ][ + - ]: 14 : o->newline(-1) << "}";
4598 [ + - ][ + - ]: 14 : o->newline() << res << ";";
[ + - ]
4599 : :
4600 [ + - ][ + - ]: 3285 : delete v;
[ + - ][ + - ]
[ + - ][ + - ]
4601 [ + - ][ + + ]: 3419 : }
4602 : : }
4603 : :
4604 : :
4605 : : void
4606 : 18472 : c_tmpcounter_assignment::visit_arrayindex (arrayindex *e)
4607 : : {
4608 : : symbol *array;
4609 : : hist_op *hist;
4610 [ + - ]: 18472 : classify_indexable (e->base, array, hist);
4611 : :
4612 [ + - ]: 18472 : if (array)
4613 : : {
4614 [ + - ]: 18472 : parent->load_map_indices(e);
4615 : :
4616 : : // The expression rval, lval, and result.
4617 [ + + ]: 18472 : exp_type ty = rvalue ? rvalue->type : e->type;
4618 [ + - ]: 18472 : tmpvar rval = parent->parent->gensym (ty);
4619 [ + - ]: 18472 : tmpvar lval = parent->parent->gensym (ty);
4620 [ + - ]: 18472 : tmpvar res = parent->parent->gensym (ty);
4621 : :
4622 [ + - ]: 18472 : prepare_rvalue(rval);
4623 [ + - ]: 18472 : lval.declare (*(parent->parent));
4624 : :
4625 [ + - ][ + + ]: 18472 : if (op == "<<<")
4626 [ + - ]: 7383 : res.declare (*(parent->parent));
4627 : : else
4628 [ + - ][ + - ]: 18472 : c_assignop(res);
[ + - ][ + - ]
4629 : : }
4630 : : else
4631 : : {
4632 [ # # ][ # # ]: 0 : throw semantic_error(_("cannot assign to histogram buckets"), e->tok);
4633 : : }
4634 : 18472 : }
4635 : :
4636 : :
4637 : : void
4638 : 18472 : c_unparser_assignment::visit_arrayindex (arrayindex *e)
4639 : : {
4640 : : symbol *array;
4641 : : hist_op *hist;
4642 [ + - ]: 18472 : classify_indexable (e->base, array, hist);
4643 : :
4644 [ + - ]: 18472 : if (array)
4645 : : {
4646 : :
4647 [ + - ]: 18472 : stmt_expr block(*parent);
4648 : :
4649 : 18472 : translator_output *o = parent->o;
4650 : :
4651 [ - + ]: 18472 : if (array->referent->index_types.size() == 0)
4652 [ # # ][ # # ]: 0 : throw semantic_error (_("unexpected reference to scalar"), e->tok);
4653 : :
4654 : : // nb: Do not adjust the order of the next few lines; the tmpvar
4655 : : // allocation order must remain the same between
4656 : : // c_unparser_assignment::visit_arrayindex and
4657 : : // c_tmpcounter_assignment::visit_arrayindex
4658 : :
4659 [ + - ]: 18472 : vector<tmpvar> idx;
4660 [ + - ]: 18472 : parent->load_map_indices (e, idx);
4661 [ + + ]: 18472 : exp_type ty = rvalue ? rvalue->type : e->type;
4662 [ + - ]: 18472 : tmpvar rvar = parent->gensym (ty);
4663 [ + - ]: 18472 : tmpvar lvar = parent->gensym (ty);
4664 [ + - ]: 18472 : tmpvar res = parent->gensym (ty);
4665 : :
4666 : : // NB: because these expressions are nestable, emit this construct
4667 : : // thusly:
4668 : : // ({ tmp0=(idx0); ... tmpN=(idxN); rvar=(rhs); lvar; res;
4669 : : // lock (array);
4670 : : // lvar = get (array,idx0...N); // if necessary
4671 : : // assignop (res, lvar, rvar);
4672 : : // set (array, idx0...N, lvar);
4673 : : // unlock (array);
4674 : : // res; })
4675 : : //
4676 : : // we store all indices in temporary variables to avoid nasty
4677 : : // reentrancy issues that pop up with nested expressions:
4678 : : // e.g. ++a[a[c]=5] could deadlock
4679 : : //
4680 : : //
4681 : : // There is an exception to the above form: if we're doign a <<< assigment to
4682 : : // a statistic-valued map, there's a special form we follow:
4683 : : //
4684 : : // ({ tmp0=(idx0); ... tmpN=(idxN); rvar=(rhs);
4685 : : // *no need to* lock (array);
4686 : : // _stp_map_add_stat (array, idx0...N, rvar);
4687 : : // *no need to* unlock (array);
4688 : : // rvar; })
4689 : : //
4690 : : // To simplify variable-allocation rules, we assign rvar to lvar and
4691 : : // res in this block as well, even though they are technically
4692 : : // superfluous.
4693 : :
4694 [ + - ]: 18472 : prepare_rvalue (op, rvar, e->tok);
4695 : :
4696 [ + - ][ + + ]: 18472 : if (op == "<<<")
4697 : : {
4698 [ - + ]: 7383 : assert (e->type == pe_stats);
4699 [ - + ]: 7383 : assert (rvalue->type == pe_long);
4700 : :
4701 [ + - ]: 7383 : mapvar mvar = parent->getmap (array->referent, e->tok);
4702 [ + - ][ + - ]: 7383 : o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
[ + - ][ + - ]
[ + - ][ + - ]
4703 [ + - ][ + - ]: 7383 : o->newline() << mvar.add (idx, rvar) << ";";
[ + - ][ + - ]
[ + - ]
4704 [ + - ][ + - ]: 7383 : res = rvar;
4705 : : // no need for these dummy assignments
4706 : : // o->newline() << lvar << " = " << rvar << ";";
4707 : : // o->newline() << res << " = " << rvar << ";";
4708 : : }
4709 : : else
4710 : : {
4711 [ + - ]: 11089 : mapvar mvar = parent->getmap (array->referent, e->tok);
4712 [ + - ][ + - ]: 11089 : o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
[ + - ][ + - ]
[ + - ][ + - ]
4713 [ + - ][ + + ]: 11089 : if (op != "=") // don't bother fetch slot if we will just overwrite it
4714 [ + - ][ + - ]: 1271 : parent->c_assign (lvar, mvar.get(idx), e->tok);
[ + - ]
4715 [ + - ]: 11089 : c_assignop (res, lvar, rvar, e->tok);
4716 [ + - ][ + - ]: 11089 : o->newline() << mvar.set (idx, lvar) << ";";
[ + - ][ + - ]
[ + - ][ + - ]
4717 : : }
4718 : :
4719 [ + - ][ + - ]: 18472 : o->newline() << res << ";";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
4720 : : }
4721 : : else
4722 : : {
4723 [ # # ][ # # ]: 0 : throw semantic_error(_("cannot assign to histogram buckets"), e->tok);
4724 : : }
4725 : 18472 : }
4726 : :
4727 : :
4728 : : void
4729 : 31483 : c_tmpcounter::visit_functioncall (functioncall *e)
4730 : : {
4731 [ - + ]: 31483 : assert (e->referent != 0);
4732 : 31483 : functiondecl* r = e->referent;
4733 : : // one temporary per argument, unless literal numbers or strings
4734 [ + + ]: 44855 : for (unsigned i=0; i<r->formal_args.size(); i++)
4735 : : {
4736 [ + - ]: 13372 : tmpvar t = parent->gensym (r->formal_args[i]->type);
4737 [ + + + + ]: 23155 : if (e->args[i]->tok->type != tok_number
[ + + ]
4738 : 9783 : && e->args[i]->tok->type != tok_string)
4739 [ + - ]: 8801 : t.declare (*parent);
4740 [ + - ]: 13372 : e->args[i]->visit (this);
4741 [ + - ]: 13372 : }
4742 : 31483 : }
4743 : :
4744 : :
4745 : : void
4746 : 31483 : c_unparser::visit_functioncall (functioncall* e)
4747 : : {
4748 [ - + ]: 31483 : assert (e->referent != 0);
4749 : 31483 : functiondecl* r = e->referent;
4750 : :
4751 [ - + ]: 31483 : if (r->formal_args.size() != e->args.size())
4752 [ # # ][ # # ]: 0 : throw semantic_error (_("invalid length argument list"), e->tok);
4753 : :
4754 [ + - ]: 31483 : stmt_expr block(*this);
4755 : :
4756 : : // NB: we store all actual arguments in temporary variables,
4757 : : // to avoid colliding sharing of context variables with
4758 : : // nested function calls: f(f(f(1)))
4759 : :
4760 : : // compute actual arguments
4761 [ + - ]: 31483 : vector<tmpvar> tmp;
4762 : :
4763 [ + + ]: 44855 : for (unsigned i=0; i<e->args.size(); i++)
4764 : : {
4765 [ + - ]: 13372 : tmpvar t = gensym(e->args[i]->type);
4766 : :
4767 [ - + ]: 13372 : if (r->formal_args[i]->type != e->args[i]->type)
4768 : 0 : throw semantic_error (_("function argument type mismatch"),
4769 [ # # ][ # # ]: 0 : e->args[i]->tok, r->formal_args[i]->tok);
4770 : :
4771 [ + + + + ]: 23155 : if (e->args[i]->tok->type == tok_number
[ + + ]
4772 : 9783 : || e->args[i]->tok->type == tok_string)
4773 [ + - ][ + - ]: 4571 : t.override(c_expression(e->args[i]));
[ + - ]
4774 : : else
4775 : : {
4776 : : // o->newline() << "c->last_stmt = "
4777 : : // << lex_cast_qstring(*e->args[i]->tok) << ";";
4778 : 8801 : c_assign (t.value(), e->args[i],
4779 [ + - + - ]: 17602 : _("function actual argument evaluation"));
[ + - ][ + - ]
[ + - ]
4780 : : }
4781 [ + - ]: 13372 : tmp.push_back(t);
4782 [ + - ]: 13372 : }
4783 : :
4784 : : // copy in actual arguments
4785 [ + + ]: 44855 : for (unsigned i=0; i<e->args.size(); i++)
4786 : : {
4787 [ - + ]: 13372 : if (r->formal_args[i]->type != e->args[i]->type)
4788 : 0 : throw semantic_error (_("function argument type mismatch"),
4789 [ # # ][ # # ]: 0 : e->args[i]->tok, r->formal_args[i]->tok);
4790 : :
4791 : : c_assign ("c->locals[c->nesting+1]." +
4792 : 13372 : c_funcname (r->name) + "." +
4793 : 13372 : c_localname (r->formal_args[i]->name),
4794 : 13372 : tmp[i].value(),
4795 : 13372 : e->args[i]->type,
4796 : : "function actual argument copy",
4797 [ + - ][ + - ]: 53488 : e->args[i]->tok);
[ + - + - ]
[ + - + -
+ - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4798 : : }
4799 : :
4800 : : // call function
4801 [ + - ][ + - ]: 31483 : o->newline() << c_funcname (r->name) << " (c);";
[ + - ][ + - ]
[ + - ]
4802 [ + - ][ + - ]: 31483 : o->newline() << "if (unlikely(c->last_error)) goto out;";
4803 : :
4804 : : // return result from retvalue slot
4805 [ + + ]: 31483 : if (r->type == pe_unknown)
4806 : : // If we passed typechecking, then nothing will use this return value
4807 [ + - ][ + - ]: 3022 : o->newline() << "(void) 0;";
4808 : : else
4809 [ + - ][ + - ]: 28461 : o->newline() << "c->locals[c->nesting+1]"
4810 [ + - ][ + - ]: 56922 : << "." << c_funcname (r->name)
[ + - ][ + - ]
4811 [ + - ][ + - ]: 59944 : << ".__retvalue;";
[ + - ]
4812 : 31483 : }
4813 : :
4814 : :
4815 : : static int
4816 : 25407 : preprocess_print_format(print_format* e, vector<tmpvar>& tmp,
4817 : : vector<print_format::format_component>& components,
4818 : : string& format_string)
4819 : : {
4820 : 25407 : int use_print = 0;
4821 : :
4822 [ + + ]: 25407 : if (e->print_with_format)
4823 : : {
4824 : 18896 : format_string = e->raw_components;
4825 : 18896 : components = e->components;
4826 : : }
4827 : : else
4828 : : {
4829 [ + - ]: 6511 : string delim;
4830 [ + + ]: 6511 : if (e->print_with_delim)
4831 : : {
4832 [ + - ]: 56 : stringstream escaped_delim;
4833 : 56 : const string& dstr = e->delimiter.literal_string;
4834 [ + - ][ + - ]: 364 : for (string::const_iterator i = dstr.begin();
[ + + ]
4835 [ + - ]: 182 : i != dstr.end(); ++i)
4836 : : {
4837 [ + + ]: 126 : if (*i == '%')
4838 [ + - ]: 6 : escaped_delim << '%';
4839 [ + - ]: 126 : escaped_delim << *i;
4840 : : }
4841 [ + - ][ + - ]: 56 : delim = escaped_delim.str();
[ + - ][ + - ]
4842 : : }
4843 : :
4844 : : // Synthesize a print-format string if the user didn't
4845 : : // provide one; the synthetic string simply contains one
4846 : : // directive for each argument.
4847 [ + - ]: 6511 : stringstream format;
4848 [ + + ]: 13908 : for (unsigned i = 0; i < e->args.size(); ++i)
4849 : : {
4850 [ + + ][ + + ]: 7397 : if (i > 0 && e->print_with_delim)
4851 [ + - ]: 102 : format << delim;
4852 [ - - + + ]: 7397 : switch (e->args[i]->type)
4853 : : {
4854 : : default:
4855 : : case pe_unknown:
4856 [ # # ][ # # ]: 0 : throw semantic_error(_("cannot print unknown expression type"), e->args[i]->tok);
4857 : : case pe_stats:
4858 [ # # ][ # # ]: 0 : throw semantic_error(_("cannot print a raw stats object"), e->args[i]->tok);
4859 : : case pe_long:
4860 [ + - ]: 1379 : format << "%d";
4861 : 1379 : break;
4862 : : case pe_string:
4863 [ + - ]: 6018 : format << "%s";
4864 : 6018 : break;
4865 : : }
4866 : : }
4867 [ + + ]: 6511 : if (e->print_with_newline)
4868 [ + - ]: 4499 : format << "\\n";
4869 : :
4870 [ + - ][ + - ]: 6511 : format_string = format.str();
[ + - ]
4871 [ + - ][ + - ]: 6511 : components = print_format::string_to_components(format_string);
[ + - ][ + - ]
[ + - ]
4872 : : }
4873 : :
4874 : :
4875 [ + + ][ + + : 59924 : if ((tmp.size() == 0 && format_string.find("%%") == string::npos)
+ + + + ]
[ + + ]
4876 : 34517 : || (tmp.size() == 1 && format_string == "%s"))
4877 : 2898 : use_print = 1;
4878 [ + + + + : 33433 : else if (tmp.size() == 1
+ + ][ + + ]
4879 : 9988 : && e->args[0]->tok->type == tok_string
4880 : 936 : && format_string == "%s\\n")
4881 : : {
4882 : 876 : use_print = 1;
4883 [ + - ][ + - ]: 876 : tmp[0].override(tmp[0].value() + "\"\\n\"");
[ + - ]
4884 : : }
4885 : :
4886 : 25407 : return use_print;
4887 : : }
4888 : :
4889 : : void
4890 : 12799 : c_tmpcounter::visit_print_format (print_format* e)
4891 : : {
4892 [ + + ]: 12799 : if (e->hist)
4893 : : {
4894 [ + - ]: 95 : aggvar agg = parent->gensym_aggregate ();
4895 [ + - ]: 95 : agg.declare(*(this->parent));
4896 [ + - ]: 95 : load_aggregate (e->hist->stat);
4897 : :
4898 : : // And the result for sprint[ln](@hist_*)
4899 [ + + ]: 95 : if (!e->print_to_stream)
4900 : : {
4901 : 5 : exp_type ty = pe_string;
4902 [ + - ]: 5 : tmpvar res = parent->gensym(ty);
4903 [ + - ][ + - ]: 5 : res.declare(*parent);
4904 [ + - ]: 95 : }
4905 : : }
4906 : : else
4907 : : {
4908 : : // One temporary per argument
4909 [ + - ]: 12704 : vector<tmpvar> tmp;
4910 [ + + ]: 38922 : for (unsigned i=0; i < e->args.size(); i++)
4911 : : {
4912 [ + - ]: 26218 : tmpvar t = parent->gensym (e->args[i]->type);
4913 [ + - ]: 26218 : tmp.push_back(t);
4914 [ - + ]: 26218 : if (e->args[i]->type == pe_unknown)
4915 : : {
4916 : 0 : throw semantic_error(_("unknown type of arg to print operator"),
4917 [ # # ][ # # ]: 0 : e->args[i]->tok);
4918 : : }
4919 : :
4920 [ + + + + ]: 51991 : if (e->args[i]->tok->type != tok_number
[ + + ]
4921 : 25773 : && e->args[i]->tok->type != tok_string)
4922 [ + - ]: 24747 : t.declare (*parent);
4923 [ + - ]: 26218 : e->args[i]->visit (this);
4924 [ + - ]: 26218 : }
4925 : :
4926 : : // And the result
4927 [ + + ]: 12704 : exp_type ty = e->print_to_stream ? pe_long : pe_string;
4928 [ + - ]: 12704 : tmpvar res = parent->gensym (ty);
4929 [ + + ]: 12704 : if (ty == pe_string)
4930 [ + - ]: 5033 : res.declare (*parent);
4931 : :
4932 : : // Munge so we can find our compiled printf
4933 [ + - ]: 12704 : vector<print_format::format_component> components;
4934 [ + - ]: 12704 : string format_string;
4935 [ + - ]: 12704 : int use_print = preprocess_print_format(e, tmp, components, format_string);
4936 : :
4937 : : // If not in a shortcut case, declare the compiled printf
4938 [ + + ][ + + ]: 12704 : if (!(e->print_to_stream && (e->print_char || use_print)))
[ + + ]
4939 [ + - ][ + - ]: 12704 : parent->declare_compiled_printf(e->print_to_stream, format_string);
[ + - ][ + - ]
[ + - ]
4940 : : }
4941 : 12799 : }
4942 : :
4943 : :
4944 : : void
4945 : 12799 : c_unparser::visit_print_format (print_format* e)
4946 : : {
4947 : : // Print formats can contain a general argument list *or* a special
4948 : : // type of argument which gets its own processing: a single,
4949 : : // non-format-string'ed, histogram-type stat_op expression.
4950 : :
4951 [ + + ]: 12799 : if (e->hist)
4952 : : {
4953 [ + - ]: 95 : stmt_expr block(*this);
4954 [ + - ]: 95 : aggvar agg = gensym_aggregate ();
4955 : :
4956 [ + - ]: 95 : var *v = load_aggregate(e->hist->stat, agg);
4957 [ + - ]: 95 : v->assert_hist_compatible(*e->hist);
4958 : :
4959 : : {
4960 : : // PR 2142+2610: empty aggregates
4961 [ + - ][ + - ]: 190 : o->newline() << "if (unlikely (" << agg.value() << " == NULL)"
[ + - ][ + - ]
[ + - ][ + - ]
4962 [ + - ][ + - ]: 95 : << " || " << agg.value() << "->count == 0) {";
[ + - ][ + - ]
[ + - ]
4963 [ + - ][ + - ]: 95 : o->newline(1) << "c->last_error = ";
4964 [ + - ]: 95 : o->line() << STAP_T_06;
4965 [ + - ][ + - ]: 95 : o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
[ + - ][ + - ]
[ + - ][ + - ]
4966 [ + - ][ + - ]: 95 : o->newline() << "goto out;";
4967 [ + - ][ + - ]: 95 : o->newline(-1) << "} else";
4968 [ + + ]: 95 : if (e->print_to_stream)
4969 : : {
4970 [ + - ][ + - ]: 90 : o->newline(1) << "_stp_stat_print_histogram (" << v->hist() << ", " << agg.value() << ");";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
4971 [ + - ]: 90 : o->indent(-1);
4972 : : }
4973 : : else
4974 : : {
4975 : 5 : exp_type ty = pe_string;
4976 [ + - ]: 5 : tmpvar res = gensym (ty);
4977 [ + - ][ + - ]: 5 : o->newline(1) << "_stp_stat_print_histogram_buf (" << res.value() << ", MAXSTRINGLEN, " << v->hist() << ", " << agg.value() << ");";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
4978 [ + - ][ + - ]: 5 : o->newline(-1) << res.value() << ";";
[ + - ][ + - ]
[ + - ][ + - ]
4979 : : }
4980 : : }
4981 : :
4982 [ + - ][ + - ]: 95 : delete v;
[ + - ][ + - ]
4983 : : }
4984 : : else
4985 : : {
4986 [ + - ]: 12704 : stmt_expr block(*this);
4987 : :
4988 : : // PR10750: Enforce a reasonable limit on # of varargs
4989 : : // 32 varargs leads to max 256 bytes on the stack
4990 [ + + ]: 12704 : if (e->args.size() > 32)
4991 : 1 : throw semantic_error(_F(ngettext("additional argument to print", "too many arguments to print (%zu)",
4992 [ + - ][ + - ]: 2 : e->args.size()), e->args.size()), e->tok);
4993 : :
4994 : : // Compute actual arguments
4995 [ + - ]: 12703 : vector<tmpvar> tmp;
4996 : :
4997 [ + + ]: 38888 : for (unsigned i=0; i<e->args.size(); i++)
4998 : : {
4999 [ + - ]: 26185 : tmpvar t = gensym(e->args[i]->type);
5000 [ + - ]: 26185 : tmp.push_back(t);
5001 : :
5002 : : // o->newline() << "c->last_stmt = "
5003 : : // << lex_cast_qstring(*e->args[i]->tok) << ";";
5004 : :
5005 : : // If we've got a numeric or string constant, instead of
5006 : : // assigning the numeric or string constant to a temporary,
5007 : : // then passing the temporary to _stp_printf/_stp_snprintf,
5008 : : // let's just override the temporary with the constant.
5009 [ + + + + ]: 51958 : if (e->args[i]->tok->type == tok_number
[ + + ]
5010 : 25773 : || e->args[i]->tok->type == tok_string)
5011 [ + - ][ + - ]: 1438 : tmp[i].override(c_expression(e->args[i]));
[ + - ]
5012 : : else
5013 : 24747 : c_assign (t.value(), e->args[i],
5014 [ + - + - ]: 49494 : "print format actual argument evaluation");
[ + - ][ + - ]
[ + - ]
5015 [ + - ]: 26185 : }
5016 : :
5017 : : // Allocate the result
5018 [ + + ]: 12703 : exp_type ty = e->print_to_stream ? pe_long : pe_string;
5019 [ + - ]: 12703 : tmpvar res = gensym (ty);
5020 : :
5021 : : // Munge so we can find our compiled printf
5022 [ + - ]: 12703 : vector<print_format::format_component> components;
5023 [ + - ][ + - ]: 12703 : string format_string, format_string_out;
5024 [ + - ]: 12703 : int use_print = preprocess_print_format(e, tmp, components, format_string);
5025 [ + - ][ + - ]: 12703 : format_string_out = print_format::components_to_string(components);
[ + - ]
5026 : :
5027 : : // Make the [s]printf call...
5028 : :
5029 : : // Generate code to check that any pointer arguments are actually accessible.
5030 : 12703 : size_t arg_ix = 0;
5031 [ + + ]: 64010 : for (unsigned i = 0; i < components.size(); ++i) {
5032 [ + + ]: 51307 : if (components[i].type == print_format::conv_literal)
5033 : 25185 : continue;
5034 : :
5035 : : /* Take note of the width and precision arguments, if any. */
5036 : 26122 : int width_ix = -1, prec_ix= -1;
5037 [ + + ]: 26122 : if (components[i].widthtype == print_format::width_dynamic)
5038 : 33 : width_ix = arg_ix++;
5039 [ + + ]: 26122 : if (components[i].prectype == print_format::prec_dynamic)
5040 : 30 : prec_ix = arg_ix++;
5041 : :
5042 : : (void) width_ix; /* XXX: notused */
5043 : :
5044 : : /* %m and %M need special care for digging into memory. */
5045 [ + + + + ]: 52192 : if (components[i].type == print_format::conv_memory
[ + + ]
5046 : 26070 : || components[i].type == print_format::conv_memory_hex)
5047 : : {
5048 [ + - ]: 78 : string mem_size;
5049 : 78 : const token* prec_tok = e->tok;
5050 [ + + ]: 78 : if (prec_ix != -1)
5051 : : {
5052 [ + - ][ + - ]: 14 : mem_size = tmp[prec_ix].value();
[ + - ]
5053 : 14 : prec_tok = e->args[prec_ix]->tok;
5054 : : }
5055 [ + + + - ]: 74 : else if (components[i].prectype == print_format::prec_static &&
[ + + ]
5056 : 10 : components[i].precision > 0)
5057 [ + - ][ + - ]: 10 : mem_size = lex_cast(components[i].precision) + "LL";
[ + - ][ + - ]
[ + - ]
5058 : : else
5059 [ + - ]: 54 : mem_size = "1LL";
5060 : :
5061 : : /* Limit how much can be printed at a time. (see also PR10490) */
5062 [ + - ][ + - ]: 78 : o->newline() << "c->last_stmt = " << lex_cast_qstring(*prec_tok) << ";";
[ + - ][ + - ]
[ + - ][ + - ]
5063 [ + - ][ + - ]: 78 : o->newline() << "if (" << mem_size << " > 1024) {";
[ + - ][ + - ]
5064 [ + - ][ + - ]: 78 : o->newline(1) << "snprintf(c->error_buffer, sizeof(c->error_buffer), "
5065 [ + - ]: 78 : << "\"%lld is too many bytes for a memory dump\", (long long)"
5066 [ + - ][ + - ]: 78 : << mem_size << ");";
5067 [ + - ][ + - ]: 78 : o->newline() << "c->last_error = c->error_buffer;";
5068 [ + - ][ + - ]: 78 : o->newline() << "goto out;";
5069 [ + - ][ + - ]: 78 : o->newline(-1) << "}";
[ + - ]
5070 : : }
5071 : :
5072 : 26122 : ++arg_ix;
5073 : : }
5074 : :
5075 : : // Shortcuts for cases that aren't formatted at all
5076 [ + + ]: 12703 : if (e->print_to_stream)
5077 : : {
5078 [ + + ]: 7670 : if (e->print_char)
5079 : : {
5080 [ + - ][ + - ]: 20 : o->newline() << "_stp_print_char (";
5081 [ + - ]: 20 : if (tmp.size())
5082 [ + - ][ + - ]: 20 : o->line() << tmp[0].value() << ");";
[ + - ][ + - ]
5083 : : else
5084 [ # # ][ # # ]: 20 : o->line() << '"' << format_string_out << "\");";
[ # # ]
5085 : : return;
5086 : : }
5087 [ + + ]: 7650 : if (use_print)
5088 : : {
5089 [ + - ][ + - ]: 1855 : o->newline() << "_stp_print (";
5090 [ + + ]: 1855 : if (tmp.size())
5091 [ + - ][ + - ]: 936 : o->line() << tmp[0].value() << ");";
[ + - ][ + - ]
5092 : : else
5093 [ + - ][ + - ]: 1855 : o->line() << '"' << format_string_out << "\");";
[ + - ]
5094 : : return;
5095 : : }
5096 : : }
5097 : :
5098 : : // The default it to use the new compiled-printf, but one can fall back
5099 : : // to the old code with -DSTP_LEGACY_PRINT if desired.
5100 [ + - ][ + - ]: 10828 : o->newline() << "#ifndef STP_LEGACY_PRINT";
5101 [ + - ]: 10828 : o->indent(1);
5102 : :
5103 : : // Copy all arguments to the compiled-printf's space, then call it
5104 : : const string& compiled_printf =
5105 [ + - ]: 10828 : get_compiled_printf (e->print_to_stream, format_string);
5106 [ + + ]: 36057 : for (unsigned i = 0; i < tmp.size(); ++i)
5107 [ + - ][ + - ]: 25229 : o->newline() << "c->printf_locals." << compiled_printf
[ + - ]
5108 [ + - ][ + - ]: 25229 : << ".arg" << i << " = " << tmp[i].value() << ";";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
5109 [ + + ]: 10828 : if (e->print_to_stream)
5110 : : // We'll just hardcode the result of 0 instead of using the
5111 : : // temporary.
5112 [ + - ][ + - ]: 5795 : res.override("((int64_t)0LL)");
[ + - ]
5113 : : else
5114 [ + - ][ + - ]: 5033 : o->newline() << "c->printf_locals." << compiled_printf
[ + - ]
5115 [ + - ][ + - ]: 5033 : << ".__retvalue = " << res.value() << ";";
[ + - ][ + - ]
[ + - ]
5116 [ + - ][ + - ]: 10828 : o->newline() << compiled_printf << " (c);";
[ + - ]
5117 : :
5118 [ + - ][ + - ]: 10828 : o->newline(-1) << "#else // STP_LEGACY_PRINT";
5119 [ + - ]: 10828 : o->indent(1);
5120 : :
5121 : : // Generate the legacy call that goes through _stp_vsnprintf.
5122 [ + + ]: 10828 : if (e->print_to_stream)
5123 [ + - ][ + - ]: 5795 : o->newline() << "_stp_printf (";
5124 : : else
5125 [ + - ][ + - ]: 5033 : o->newline() << "_stp_snprintf (" << res.value() << ", MAXSTRINGLEN, ";
[ + - ][ + - ]
[ + - ][ + - ]
5126 [ + - ][ + - ]: 10828 : o->line() << '"' << format_string_out << '"';
[ + - ]
5127 : :
5128 : : // Make sure arguments match the expected type of the format specifier.
5129 : 10828 : arg_ix = 0;
5130 [ + + ]: 59824 : for (unsigned i = 0; i < components.size(); ++i)
5131 : : {
5132 [ + + ]: 48996 : if (components[i].type == print_format::conv_literal)
5133 : 23830 : continue;
5134 : :
5135 : : /* Cast the width and precision arguments, if any, to 'int'. */
5136 [ + + ]: 25166 : if (components[i].widthtype == print_format::width_dynamic)
5137 [ + - ][ + - ]: 33 : o->line() << ", (int)" << tmp[arg_ix++].value();
[ + - ][ + - ]
5138 [ + + ]: 25166 : if (components[i].prectype == print_format::prec_dynamic)
5139 [ + - ][ + - ]: 30 : o->line() << ", (int)" << tmp[arg_ix++].value();
[ + - ][ + - ]
5140 : :
5141 : : /* The type of the %m argument is 'char*'. */
5142 [ + + + + ]: 50280 : if (components[i].type == print_format::conv_memory
[ + + ]
5143 : 25114 : || components[i].type == print_format::conv_memory_hex)
5144 [ + - ][ + - ]: 78 : o->line() << ", (char*)(uintptr_t)" << tmp[arg_ix++].value();
[ + - ][ + - ]
5145 : : /* The type of the %c argument is 'int'. */
5146 [ + + ]: 25088 : else if (components[i].type == print_format::conv_char)
5147 [ + - ][ + - ]: 57 : o->line() << ", (int)" << tmp[arg_ix++].value();
[ + - ][ + - ]
5148 [ + - ]: 25031 : else if (arg_ix < tmp.size())
5149 [ + - ][ + - ]: 25031 : o->line() << ", " << tmp[arg_ix++].value();
[ + - ][ + - ]
5150 : : }
5151 [ + - ]: 10828 : o->line() << ");";
5152 [ + - ][ + - ]: 10828 : o->newline(-1) << "#endif // STP_LEGACY_PRINT";
5153 [ + - ][ + - ]: 10828 : o->newline() << "if (unlikely(c->last_error)) goto out;";
5154 [ + - ][ + - ]: 12799 : o->newline() << res.value() << ";";
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + + ][ + - ]
[ + + ][ + - ]
[ + + ][ + - ]
[ + + ][ + - ]
[ + + ]
5155 : : }
5156 : : }
5157 : :
5158 : :
5159 : : void
5160 : 576 : c_tmpcounter::visit_stat_op (stat_op* e)
5161 : : {
5162 [ + - ]: 576 : aggvar agg = parent->gensym_aggregate ();
5163 [ + - ]: 576 : tmpvar res = parent->gensym (pe_long);
5164 : :
5165 [ + - ]: 576 : agg.declare(*(this->parent));
5166 [ + - ]: 576 : res.declare(*(this->parent));
5167 : :
5168 [ + - ][ + - ]: 576 : load_aggregate (e->stat);
[ + - ]
5169 : 576 : }
5170 : :
5171 : : void
5172 : 576 : c_unparser::visit_stat_op (stat_op* e)
5173 : : {
5174 : : // Stat ops can be *applied* to two types of expression:
5175 : : //
5176 : : // 1. An arrayindex expression on a pe_stats-valued array.
5177 : : //
5178 : : // 2. A symbol of type pe_stats.
5179 : :
5180 : : // FIXME: classify the expression the stat_op is being applied to,
5181 : : // call appropriate stp_get_stat() / stp_pmap_get_stat() helper,
5182 : : // then reach into resultant struct stat_data.
5183 : :
5184 : : // FIXME: also note that summarizing anything is expensive, and we
5185 : : // really ought to pass a timeout handler into the summary routine,
5186 : : // check its response, possibly exit if it ran out of cycles.
5187 : :
5188 : : {
5189 [ + - ]: 576 : stmt_expr block(*this);
5190 [ + - ]: 576 : aggvar agg = gensym_aggregate ();
5191 [ + - ]: 576 : tmpvar res = gensym (pe_long);
5192 [ + - ]: 576 : var *v = load_aggregate(e->stat, agg);
5193 : : {
5194 : : // PR 2142+2610: empty aggregates
5195 [ + + ]: 677 : if ((e->ctype == sc_count) ||
[ + + + + ]
[ + + ]
5196 : : (e->ctype == sc_sum &&
5197 [ + - ]: 101 : strverscmp(session->compatible.c_str(), "1.5") >= 0))
5198 : : {
5199 [ + - ][ + - ]: 304 : o->newline() << "if (unlikely (" << agg.value() << " == NULL))";
[ + - ][ + - ]
[ + - ][ + - ]
5200 [ + - ]: 304 : o->indent(1);
5201 [ + - ][ + - ]: 304 : c_assign(res, "0", e->tok);
[ + - ]
5202 [ + - ]: 304 : o->indent(-1);
5203 : : }
5204 : : else
5205 : : {
5206 [ + - ][ + - ]: 544 : o->newline() << "if (unlikely (" << agg.value() << " == NULL)"
[ + - ][ + - ]
[ + - ][ + - ]
5207 [ + - ][ + - ]: 272 : << " || " << agg.value() << "->count == 0) {";
[ + - ][ + - ]
[ + - ]
5208 [ + - ][ + - ]: 272 : o->newline(1) << "c->last_error = ";
5209 [ + - ]: 272 : o->line() << STAP_T_06;
5210 [ + - ][ + - ]: 272 : o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
[ + - ][ + - ]
[ + - ][ + - ]
5211 [ + - ][ + - ]: 272 : o->newline() << "goto out;";
5212 [ + - ][ + - ]: 272 : o->newline(-1) << "}";
5213 : : }
5214 [ + - ][ + - ]: 576 : o->newline() << "else";
5215 [ + - ]: 576 : o->indent(1);
5216 [ + + + + : 576 : switch (e->ctype)
+ - - ]
5217 : : {
5218 : : case sc_average:
5219 : : c_assign(res, ("_stp_div64(NULL, " + agg.value() + "->sum, "
5220 : : + agg.value() + "->count)"),
5221 [ + - ][ + - ]: 95 : e->tok);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
5222 : 95 : break;
5223 : : case sc_count:
5224 [ + - ][ + - ]: 205 : c_assign(res, agg.value() + "->count", e->tok);
[ + - ][ + - ]
[ + - ]
5225 : 205 : break;
5226 : : case sc_sum:
5227 [ + - ][ + - ]: 101 : c_assign(res, agg.value() + "->sum", e->tok);
[ + - ][ + - ]
[ + - ]
5228 : 101 : break;
5229 : : case sc_min:
5230 [ + - ][ + - ]: 88 : c_assign(res, agg.value() + "->min", e->tok);
[ + - ][ + - ]
[ + - ]
5231 : 88 : break;
5232 : : case sc_max:
5233 [ + - ][ + - ]: 87 : c_assign(res, agg.value() + "->max", e->tok);
[ + - ][ + - ]
[ + - ]
5234 : 87 : break;
5235 : : case sc_none:
5236 : 0 : assert (0); // should not happen, as sc_none is only used in foreach sorts
5237 : : }
5238 [ + - ]: 576 : o->indent(-1);
5239 : : }
5240 [ + - ][ + - ]: 576 : o->newline() << res << ";";
[ + - ]
5241 [ + - ][ + - ]: 576 : delete v;
[ + - ][ + - ]
[ + - ]
5242 : : }
5243 : 576 : }
5244 : :
5245 : :
5246 : : void
5247 : 0 : c_unparser::visit_hist_op (hist_op*)
5248 : : {
5249 : : // Hist ops can only occur in a limited set of circumstances:
5250 : : //
5251 : : // 1. Inside an arrayindex expression, as the base referent. See
5252 : : // c_unparser::visit_arrayindex for handling of this case.
5253 : : //
5254 : : // 2. Inside a foreach statement, as the base referent. See
5255 : : // c_unparser::visit_foreach_loop for handling this case.
5256 : : //
5257 : : // 3. Inside a print_format expression, as the sole argument. See
5258 : : // c_unparser::visit_print_format for handling this case.
5259 : : //
5260 : : // Note that none of these cases involves the c_unparser ever
5261 : : // visiting this node. We should not get here.
5262 : :
5263 : 0 : assert(false);
5264 : : }
5265 : :
5266 : :
5267 : : typedef map<Dwarf_Addr,const char*> addrmap_t; // NB: plain map, sorted by address
5268 : :
5269 [ + - ][ + - ]: 644 : struct unwindsym_dump_context
5270 : : {
5271 : : systemtap_session& session;
5272 : : ostream& output;
5273 : : unsigned stp_module_index;
5274 : :
5275 : : int build_id_len;
5276 : : unsigned char *build_id_bits;
5277 : : GElf_Addr build_id_vaddr;
5278 : :
5279 : : unsigned long stp_kretprobe_trampoline_addr;
5280 : : Dwarf_Addr stext_offset;
5281 : :
5282 : : vector<pair<string,unsigned> > seclist; // encountered relocation bases
5283 : : // (section names and sizes)
5284 : : map<unsigned, addrmap_t> addrmap; // per-relocation-base sorted addrmap
5285 : :
5286 : : void *debug_frame;
5287 : : size_t debug_len;
5288 : : void *debug_frame_hdr;
5289 : : size_t debug_frame_hdr_len;
5290 : : Dwarf_Addr debug_frame_off;
5291 : : void *eh_frame;
5292 : : void *eh_frame_hdr;
5293 : : size_t eh_len;
5294 : : size_t eh_frame_hdr_len;
5295 : : Dwarf_Addr eh_addr;
5296 : : Dwarf_Addr eh_frame_hdr_addr;
5297 : :
5298 : : set<string> undone_unwindsym_modules;
5299 : : };
5300 : :
5301 : 69 : static void create_debug_frame_hdr (const unsigned char e_ident[],
5302 : : Elf_Data *debug_frame,
5303 : : void **debug_frame_hdr,
5304 : : size_t *debug_frame_hdr_len,
5305 : : Dwarf_Addr *debug_frame_off,
5306 : : systemtap_session& session,
5307 : : Dwfl_Module *mod)
5308 : : {
5309 : 69 : *debug_frame_hdr = NULL;
5310 : 69 : *debug_frame_hdr_len = 0;
5311 : :
5312 : 69 : int cies = 0;
5313 [ + - ]: 69 : set< pair<Dwarf_Addr, Dwarf_Off> > fdes;
5314 : 69 : set< pair<Dwarf_Addr, Dwarf_Off> >::iterator it;
5315 : :
5316 : : // In the .debug_frame the FDE encoding is always DW_EH_PE_absptr.
5317 : : // So there is no need to read the CIEs. And the size is either 4
5318 : : // or 8, depending on the elf class from e_ident.
5319 [ + - ]: 69 : int size = (e_ident[EI_CLASS] == ELFCLASS32) ? 4 : 8;
5320 : 69 : int res = 0;
5321 : 69 : Dwarf_Off off = 0;
5322 : : Dwarf_CFI_Entry entry;
5323 : :
5324 [ + + ]: 422115 : while (res != 1)
5325 : : {
5326 : : Dwarf_Off next_off;
5327 : : res = dwarf_next_cfi (e_ident, debug_frame, false, off, &next_off,
5328 [ + - ]: 422046 : &entry);
5329 [ + + ]: 422046 : if (res == 0)
5330 : : {
5331 [ + + ]: 421977 : if (entry.CIE_id == DW_CIE_ID_64)
5332 : 21541 : cies++; // We can just ignore the CIEs.
5333 : : else
5334 : : {
5335 : : Dwarf_Addr addr;
5336 [ + - ]: 400436 : if (size == 4)
5337 : 400436 : addr = (*((uint32_t *) entry.fde.start));
5338 : : else
5339 : 0 : addr = (*((uint64_t *) entry.fde.start));
5340 [ + - ]: 400436 : fdes.insert(pair<Dwarf_Addr, Dwarf_Off>(addr, off));
5341 : : }
5342 : : }
5343 [ - + ]: 69 : else if (res > 0)
5344 : : ; // Great, all done.
5345 : : else
5346 : : {
5347 : : // Warn, but continue, backtracing will be slow...
5348 [ # # ][ # # ]: 0 : if (session.verbose > 2 && ! session.suppress_warnings)
5349 : : {
5350 : : const char *modname = dwfl_module_info (mod, NULL,
5351 : : NULL, NULL, NULL,
5352 [ # # ]: 0 : NULL, NULL, NULL);
5353 : : session.print_warning("Problem creating debug frame hdr for "
5354 : : + lex_cast_qstring(modname)
5355 [ # # ][ # # ]: 0 : + ", " + dwarf_errmsg (-1));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
5356 : : }
5357 : 69 : return;
5358 : : }
5359 : 422046 : off = next_off;
5360 : : }
5361 : :
5362 [ + - ][ + - ]: 69 : if (fdes.size() > 0)
5363 : : {
5364 [ + - ]: 69 : it = fdes.begin();
5365 : 69 : Dwarf_Addr first_addr = (*it).first;
5366 [ + - ]: 69 : int res = dwfl_module_relocate_address (mod, &first_addr);
5367 : : dwfl_assert ("create_debug_frame_hdr, dwfl_module_relocate_address",
5368 [ + - ][ + - ]: 69 : res >= 0);
[ + - ]
5369 : 69 : *debug_frame_off = (*it).first - first_addr;
5370 : : }
5371 : :
5372 [ + - ]: 69 : size_t total_size = 4 + (2 * size) + (2 * size * fdes.size());
5373 : 69 : uint8_t *hdr = (uint8_t *) malloc(total_size);
5374 : 69 : *debug_frame_hdr = hdr;
5375 : 69 : *debug_frame_hdr_len = total_size;
5376 : :
5377 : 69 : hdr[0] = 1; // version
5378 : 69 : hdr[1] = DW_EH_PE_absptr; // ptr encoding
5379 [ + - ]: 69 : hdr[2] = (size == 4) ? DW_EH_PE_udata4 : DW_EH_PE_udata8; // count encoding
5380 : 69 : hdr[3] = DW_EH_PE_absptr; // table encoding
5381 [ + - ]: 69 : if (size == 4)
5382 : : {
5383 : 69 : uint32_t *table = (uint32_t *)(hdr + 4);
5384 : 69 : *table++ = (uint32_t) 0; // eh_frame_ptr, unused
5385 [ + - ]: 69 : *table++ = (uint32_t) fdes.size();
5386 [ + - ][ + - ]: 400505 : for (it = fdes.begin(); it != fdes.end(); it++)
[ + + ]
5387 : : {
5388 : 400436 : *table++ = (*it).first;
5389 : 400436 : *table++ = (*it).second;
5390 : : }
5391 : : }
5392 : : else
5393 : : {
5394 : 0 : uint64_t *table = (uint64_t *)(hdr + 4);
5395 : 0 : *table++ = (uint64_t) 0; // eh_frame_ptr, unused
5396 [ # # ]: 0 : *table++ = (uint64_t) fdes.size();
5397 [ # # ][ # # ]: 69 : for (it = fdes.begin(); it != fdes.end(); it++)
[ # # ]
5398 : : {
5399 : 0 : *table++ = (*it).first;
5400 : 0 : *table++ = (*it).second;
5401 : : }
5402 [ + - ][ + - ]: 69 : }
5403 : : }
5404 : :
5405 : 2414 : static set<string> vdso_paths;
5406 : :
5407 : : // Get the .debug_frame end .eh_frame sections for the given module.
5408 : : // Also returns the lenght of both sections when found, plus the section
5409 : : // address (offset) of the eh_frame data. If a debug_frame is found, a
5410 : : // synthesized debug_frame_hdr is also returned.
5411 : 69 : static void get_unwind_data (Dwfl_Module *m,
5412 : : void **debug_frame, void **eh_frame,
5413 : : size_t *debug_len, size_t *eh_len,
5414 : : Dwarf_Addr *eh_addr,
5415 : : void **eh_frame_hdr, size_t *eh_frame_hdr_len,
5416 : : void **debug_frame_hdr,
5417 : : size_t *debug_frame_hdr_len,
5418 : : Dwarf_Addr *debug_frame_off,
5419 : : Dwarf_Addr *eh_frame_hdr_addr,
5420 : : systemtap_session& session)
5421 : : {
5422 : 69 : Dwarf_Addr start, bias = 0;
5423 : : GElf_Ehdr *ehdr, ehdr_mem;
5424 : : GElf_Shdr *shdr, shdr_mem;
5425 : : Elf_Scn *scn;
5426 : 69 : Elf_Data *data = NULL;
5427 : : Elf *elf;
5428 : :
5429 : : // fetch .eh_frame info preferably from main elf file.
5430 : : const char *modname = dwfl_module_info (m, NULL, &start,
5431 [ + - ]: 69 : NULL, NULL, NULL, NULL, NULL);
5432 [ + - ]: 69 : elf = dwfl_module_getelf(m, &bias);
5433 [ + - ]: 69 : ehdr = gelf_getehdr(elf, &ehdr_mem);
5434 : :
5435 : : // This is a little unelegant, since at this point we only have the
5436 : : // kernel normalized machine architecture as string, but we can deduce
5437 : : // the ELF class from that and warn if it is different from the module
5438 : : // ELF class. See PR10272.
5439 [ + - ]: 69 : int kelf_class = elf_class_from_normalized_machine (session.architecture);
5440 : 69 : int melf_class = (int) ehdr->e_ident[EI_CLASS];
5441 [ - + ]: 69 : if (kelf_class != melf_class)
5442 : : {
5443 : : // Don't warn about 32bit VDSO, the user didn't explicitly add those.
5444 [ # # ][ # # ]: 0 : if (vdso_paths.find (string(modname)) == vdso_paths.end ())
[ # # ][ # # ]
[ # # ]
5445 : : session.print_warning ("Kernel ELF class (" + lex_cast (kelf_class)
5446 : : + ") doesn't match module '" + modname
5447 : : + "' ELF class (" + lex_cast (melf_class)
5448 : : + "), backtraces for 32bit programs on 64bit"
5449 [ # # ][ # # ]: 0 : + " kernels don't work.");
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
5450 : 69 : return;
5451 : : }
5452 : :
5453 : 69 : scn = NULL;
5454 : 69 : bool eh_frame_seen = false;
5455 : 69 : bool eh_frame_hdr_seen = false;
5456 [ + - ][ + + ]: 3298 : while ((scn = elf_nextscn(elf, scn)))
5457 : : {
5458 [ + - ]: 3229 : shdr = gelf_getshdr(scn, &shdr_mem);
5459 [ + - ]: 3229 : const char* scn_name = elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name);
5460 [ + + ][ + + ]: 3229 : if (!eh_frame_seen
[ + - ]
5461 : 3211 : && strcmp(scn_name, ".eh_frame") == 0
5462 : : && shdr->sh_type == SHT_PROGBITS)
5463 : : {
5464 [ + - ]: 1 : data = elf_rawdata(scn, NULL);
5465 : 1 : *eh_frame = data->d_buf;
5466 : 1 : *eh_len = data->d_size;
5467 : : // For ".dynamic" sections we want the offset, not absolute addr.
5468 : : // Note we don't trust dwfl_module_relocations() for ET_EXEC.
5469 [ - + ][ # # ]: 1 : if (ehdr->e_type != ET_EXEC && dwfl_module_relocations (m) > 0)
[ # # ][ - + ]
5470 : 0 : *eh_addr = shdr->sh_addr - start + bias;
5471 : : else
5472 : 1 : *eh_addr = shdr->sh_addr;
5473 : 1 : eh_frame_seen = true;
5474 : : }
5475 [ + - ][ - + ]: 3228 : else if (!eh_frame_hdr_seen
[ # # ]
5476 : 3228 : && strcmp(scn_name, ".eh_frame_hdr") == 0
5477 : : && shdr->sh_type == SHT_PROGBITS)
5478 : : {
5479 [ # # ]: 0 : data = elf_rawdata(scn, NULL);
5480 : 0 : *eh_frame_hdr = data->d_buf;
5481 : 0 : *eh_frame_hdr_len = data->d_size;
5482 [ # # ][ # # ]: 0 : if (ehdr->e_type != ET_EXEC && dwfl_module_relocations (m) > 0)
[ # # ][ # # ]
5483 : 0 : *eh_frame_hdr_addr = shdr->sh_addr - start + bias;
5484 : : else
5485 : 0 : *eh_frame_hdr_addr = shdr->sh_addr;
5486 : 0 : eh_frame_hdr_seen = true;
5487 : : }
5488 [ + + ][ - + ]: 3229 : if (eh_frame_seen && eh_frame_hdr_seen)
5489 : 0 : break;
5490 : : }
5491 : :
5492 : : // fetch .debug_frame info preferably from dwarf debuginfo file.
5493 [ + - ][ + - ]: 69 : elf = (dwarf_getelf (dwfl_module_getdwarf (m, &bias))
5494 [ + - ][ # # ]: 69 : ?: dwfl_module_getelf (m, &bias));
5495 [ + - ]: 69 : ehdr = gelf_getehdr(elf, &ehdr_mem);
5496 : 69 : scn = NULL;
5497 [ + - ][ + - ]: 2431 : while ((scn = elf_nextscn(elf, scn)))
5498 : : {
5499 [ + - ]: 2431 : shdr = gelf_getshdr(scn, &shdr_mem);
5500 [ + - ][ + + ]: 2431 : if (strcmp(elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name),
5501 : 2431 : ".debug_frame") == 0)
5502 : : {
5503 [ + - ]: 69 : data = elf_rawdata(scn, NULL);
5504 : 69 : *debug_frame = data->d_buf;
5505 : 69 : *debug_len = data->d_size;
5506 : 69 : break;
5507 : : }
5508 : : }
5509 : :
5510 [ + - ][ + - ]: 69 : if (*debug_frame != NULL && *debug_len > 0)
5511 : : create_debug_frame_hdr (ehdr->e_ident, data,
5512 : : debug_frame_hdr, debug_frame_hdr_len,
5513 [ + - ]: 69 : debug_frame_off, session, m);
5514 : : }
5515 : :
5516 : : static int
5517 : 357 : dump_build_id (Dwfl_Module *m,
5518 : : unwindsym_dump_context *c,
5519 : : const char *name, Dwarf_Addr base)
5520 : : {
5521 [ + - ]: 357 : string modname = name;
5522 : :
5523 : : //extract build-id from debuginfo file
5524 : 357 : int build_id_len = 0;
5525 : : unsigned char *build_id_bits;
5526 : : GElf_Addr build_id_vaddr;
5527 : :
5528 [ + - ][ + - ]: 357 : if ((build_id_len=dwfl_module_build_id(m,
5529 : : (const unsigned char **)&build_id_bits,
5530 : : &build_id_vaddr)) > 0)
5531 : : {
5532 [ + - ][ + + ]: 357 : if (modname != "kernel")
5533 : : {
5534 : 143 : Dwarf_Addr reloc_vaddr = build_id_vaddr;
5535 : : const char *secname;
5536 : : int i;
5537 : :
5538 [ + - ]: 143 : i = dwfl_module_relocate_address (m, &reloc_vaddr);
5539 [ + - ][ + - ]: 143 : dwfl_assert ("dwfl_module_relocate_address reloc_vaddr", i >= 0);
[ + - ]
5540 : :
5541 [ + - ]: 143 : secname = dwfl_module_relocation_info (m, i, NULL);
5542 : :
5543 : : // assert same section name as in runtime/transport/symbols.c
5544 : : // NB: this is applicable only to module("...") probes.
5545 : : // process("...") ones may have relocation bases like '.dynamic',
5546 : : // and so we'll have to store not just a generic offset but
5547 : : // the relocation section/symbol name too: just like we do
5548 : : // for probe PC addresses themselves. We want to set build_id_vaddr for
5549 : : // user modules even though they will not have a secname.
5550 : :
5551 [ + - ][ + + ]: 143 : if (modname[0] != '/')
5552 [ + - ][ - + ]: 125 : if (!secname || strcmp(secname, ".note.gnu.build-id"))
5553 : 0 : throw semantic_error (_("unexpected build-id reloc section ") +
5554 [ # # ][ # # ]: 0 : string(secname ?: "null"));
[ # # ][ # # ]
5555 : :
5556 : 143 : build_id_vaddr = reloc_vaddr;
5557 : : }
5558 : :
5559 [ + + ]: 357 : if (c->session.verbose > 1)
5560 : : {
5561 [ + - ][ + - ]: 32 : clog << _F("Found build-id in %s, length %d, start at %#" PRIx64,
[ + - ]
5562 [ + - ]: 16 : name, build_id_len, build_id_vaddr) << endl;
5563 : : }
5564 : :
5565 : 357 : c->build_id_len = build_id_len;
5566 : 357 : c->build_id_vaddr = build_id_vaddr;
5567 : 357 : c->build_id_bits = build_id_bits;
5568 : : }
5569 : :
5570 [ + - ]: 357 : return DWARF_CB_OK;
5571 : : }
5572 : :
5573 : : static int
5574 : 357 : dump_section_list (Dwfl_Module *m,
5575 : : unwindsym_dump_context *c,
5576 : : const char *name, Dwarf_Addr base)
5577 : : {
5578 : : // Depending on ELF section names normally means you are doing it WRONG.
5579 : : // Sadly it seems we do need it for the kernel modules. Which are ET_REL
5580 : : // files, which are "dynamically loaded" by the kernel. We keep a section
5581 : : // list for them to know which symbol corresponds to which section.
5582 : : //
5583 : : // Luckily for the kernel, normal executables (ET_EXEC) or shared
5584 : : // libraries (ET_DYN) we don't need it. We just have one "section",
5585 : : // which we will just give the arbitrary names "_stext", ".absolute"
5586 : : // or ".dynamic"
5587 : :
5588 [ + - ]: 357 : string modname = name;
5589 : :
5590 : : // Use start and end as to calculate size for _stext, .dynamic and
5591 : : // .absolute sections.
5592 : : Dwarf_Addr start, end;
5593 [ + - ]: 357 : dwfl_module_info (m, NULL, &start, &end, NULL, NULL, NULL, NULL);
5594 : :
5595 : : // Look up the relocation basis for symbols
5596 [ + - ]: 357 : int n = dwfl_module_relocations (m);
5597 [ + - ][ + - ]: 357 : dwfl_assert ("dwfl_module_relocations", n >= 0);
[ + - ]
5598 : :
5599 [ + + ]: 357 : if (n == 0)
5600 : : {
5601 : : // ET_EXEC, no relocations.
5602 [ + - ]: 7 : string secname = ".absolute";
5603 : 7 : unsigned size = end - start;
5604 [ + - ][ + - ]: 7 : c->seclist.push_back (make_pair (secname, size));
[ + - ][ + - ]
[ + - ]
5605 [ + - ]: 7 : return DWARF_CB_OK;
5606 : : }
5607 [ + + ]: 350 : else if (n == 1)
5608 : : {
5609 : : // kernel or shared library (ET_DYN).
5610 [ + - ]: 225 : string secname;
5611 [ + - ][ + + ]: 225 : secname = (modname == "kernel") ? "_stext" : ".dynamic";
[ + - ]
5612 : 225 : unsigned size = end - start;
5613 [ + - ][ + - ]: 225 : c->seclist.push_back (make_pair (secname, size));
[ + - ][ + - ]
[ + - ]
5614 [ + - ]: 225 : return DWARF_CB_OK;
5615 : : }
5616 [ + - ]: 125 : else if (n > 1)
5617 : : {
5618 : : // ET_REL, kernel module.
5619 [ + - ]: 125 : string secname;
5620 : : unsigned size;
5621 : : Dwarf_Addr bias;
5622 : : GElf_Ehdr *ehdr, ehdr_mem;
5623 : : GElf_Shdr *shdr, shdr_mem;
5624 [ + - ]: 125 : Elf *elf = dwfl_module_getelf(m, &bias);
5625 [ + - ]: 125 : ehdr = gelf_getehdr(elf, &ehdr_mem);
5626 : 125 : Elf_Scn *scn = NULL;
5627 [ + - ][ + + ]: 6426 : while ((scn = elf_nextscn(elf, scn)))
5628 : : {
5629 : : // Just the "normal" sections with program bits please.
5630 [ + - ]: 6301 : shdr = gelf_getshdr(scn, &shdr_mem);
5631 [ + + ][ + + ]: 6301 : if ((shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_NOBITS)
[ + + ]
5632 : : && (shdr->sh_flags & SHF_ALLOC))
5633 : : {
5634 : 1947 : size = shdr->sh_size;
5635 : : const char* scn_name = elf_strptr(elf, ehdr->e_shstrndx,
5636 [ + - ]: 1947 : shdr->sh_name);
5637 [ + - ]: 1947 : secname = scn_name;
5638 [ + - ][ + - ]: 1947 : c->seclist.push_back (make_pair (secname, size));
[ + - ][ + - ]
[ + - ]
5639 : : }
5640 : : }
5641 : :
5642 [ + - ]: 125 : return DWARF_CB_OK;
5643 : : }
5644 : :
5645 : : // Impossible... dflw_assert above will have triggered.
5646 [ + - ]: 357 : return DWARF_CB_ABORT;
5647 : : }
5648 : :
5649 : : /* Some architectures create special local symbols that are not
5650 : : interesting. */
5651 : : static int
5652 : 2914600 : skippable_arch_symbol (GElf_Half e_machine, const char *name, GElf_Sym *sym)
5653 : : {
5654 : : /* Filter out ARM mapping symbols */
5655 [ + - ][ + + ]: 2914600 : if (e_machine == EM_ARM
[ + + ][ + - ]
[ + - ][ + + ]
[ + - ][ - + ]
5656 : : && GELF_ST_TYPE (sym->st_info) == STT_NOTYPE
5657 : 2438695 : && (! strcmp(name, "$a") || ! strcmp(name, "$t")
5658 : 1960110 : || ! strcmp(name, "$t.x") || ! strcmp(name, "$d")
5659 : 27638 : || ! strcmp(name, "$v") || ! strcmp(name, "$d.realdata")))
5660 : 1444821 : return 1;
5661 : :
5662 : 2914600 : return 0;
5663 : : }
5664 : :
5665 : : static int
5666 : 318 : dump_symbol_tables (Dwfl_Module *m,
5667 : : unwindsym_dump_context *c,
5668 : : const char *modname, Dwarf_Addr base)
5669 : : {
5670 : : // Use end as sanity check when resolving symbol addresses.
5671 : : Dwarf_Addr end;
5672 [ + - ]: 318 : dwfl_module_info (m, NULL, NULL, &end, NULL, NULL, NULL, NULL);
5673 : :
5674 [ + - ]: 318 : int syments = dwfl_module_getsymtab(m);
5675 [ + - ][ + - ]: 318 : dwfl_assert (_F("Getting symbol table for %s", modname), syments >= 0);
[ + - ]
5676 : :
5677 : : // Look up the relocation basis for symbols
5678 [ + - ]: 318 : int n = dwfl_module_relocations (m);
5679 [ + - ][ + - ]: 318 : dwfl_assert ("dwfl_module_relocations", n >= 0);
[ + - ]
5680 : :
5681 : : /* Needed on ppc64, for function descriptors. */
5682 : : Dwarf_Addr elf_bias;
5683 : : GElf_Ehdr *ehdr, ehdr_mem;
5684 : : Elf *elf;
5685 [ + - ]: 318 : elf = dwfl_module_getelf(m, &elf_bias);
5686 [ + - ]: 318 : ehdr = gelf_getehdr(elf, &ehdr_mem);
5687 : :
5688 : : // XXX: unfortunate duplication with tapsets.cxx:emit_address()
5689 : :
5690 : : // extra_offset is for the special kernel case.
5691 : 318 : Dwarf_Addr extra_offset = 0;
5692 : 318 : Dwarf_Addr kretprobe_trampoline_addr = (unsigned long) -1;
5693 : 318 : int is_kernel = !strcmp(modname, "kernel");
5694 : :
5695 : : /* Set to bail early if we are just examining the kernel
5696 : : and don't need anything more. */
5697 : 318 : int done = 0;
5698 [ + + ][ + + ]: 21417505 : for (int i = 0; i < syments && !done; ++i)
[ + + ]
5699 : : {
5700 [ - + ]: 21417187 : if (pending_interrupts)
5701 : 0 : return DWARF_CB_ABORT;
5702 : :
5703 : : GElf_Sym sym;
5704 : : GElf_Word shndxp;
5705 : :
5706 [ + - ]: 21417187 : const char *name = dwfl_module_getsym(m, i, &sym, &shndxp);
5707 [ + - ]: 21417187 : if (name)
5708 : : {
5709 : 21417187 : Dwarf_Addr sym_addr = sym.st_value;
5710 : :
5711 : : // We always need two special values from the kernel.
5712 : : // _stext for extra_offset and kretprobe_trampoline_holder
5713 : : // for the unwinder.
5714 [ + + ]: 21417187 : if (is_kernel)
5715 : : {
5716 : : // NB: Yey, we found the kernel's _stext value.
5717 : : // Sess.sym_stext may be unset (0) at this point, since
5718 : : // there may have been no kernel probes set. We could
5719 : : // use tapsets.cxx:lookup_symbol_address(), but then
5720 : : // we're already iterating over the same data here...
5721 [ + + ]: 21365937 : if (! strcmp(name, KERNEL_RELOC_SYMBOL))
5722 : : {
5723 : : int ki;
5724 : 214 : extra_offset = sym_addr;
5725 [ + - ]: 214 : ki = dwfl_module_relocate_address (m, &extra_offset);
5726 : : dwfl_assert ("dwfl_module_relocate_address extra_offset",
5727 [ + - ][ + - ]: 214 : ki >= 0);
[ + - ]
5728 : :
5729 [ - + ]: 214 : if (c->session.verbose > 2)
5730 [ # # ][ # # ]: 0 : clog << _F("Found kernel _stext extra offset %#" PRIx64,
[ # # ]
5731 [ # # ]: 0 : extra_offset) << endl;
5732 : :
5733 [ + + ][ + - ]: 214 : if (! c->session.need_symbols
[ + + ]
5734 : : && (kretprobe_trampoline_addr != (unsigned long) -1
5735 : 187 : || ! c->session.need_unwind))
5736 : 183 : done = 1;
5737 : : }
5738 [ + - ][ + + ]: 21365723 : else if (kretprobe_trampoline_addr == (unsigned long) -1
[ - + ]
5739 : : && c->session.need_unwind
5740 : 1696784 : && ! strcmp(name, "kretprobe_trampoline_holder"))
5741 : : {
5742 : : int ki;
5743 : 0 : kretprobe_trampoline_addr = sym_addr;
5744 : : ki = dwfl_module_relocate_address(m,
5745 [ # # ]: 0 : &kretprobe_trampoline_addr);
5746 [ # # ][ # # ]: 0 : dwfl_assert ("dwfl_module_relocate_address, kretprobe_trampoline_addr", ki >= 0);
[ # # ]
5747 : :
5748 [ # # ][ # # ]: 0 : if (! c->session.need_symbols
5749 : : && extra_offset != 0)
5750 : 0 : done = 1;
5751 : : }
5752 : : }
5753 : :
5754 : : // We are only interested in "real" symbols.
5755 : : // We omit symbols that have suspicious addresses
5756 : : // (before base, or after end).
5757 [ + + ]: 25744039 : if (!done && c->session.need_symbols
[ + + + + ]
[ + + ][ + + ]
[ + + ][ + + ]
[ + + ][ + + ]
[ + + ]
5758 : 2914600 : && ! skippable_arch_symbol(ehdr->e_machine, name, &sym)
5759 : : && (GELF_ST_TYPE (sym.st_info) == STT_FUNC
5760 : : || (GELF_ST_TYPE (sym.st_info) == STT_NOTYPE
5761 : : && (ehdr->e_type == ET_REL // PR10206 ppc fn-desc in .opd
5762 : : || is_kernel)) // kernel entry functions are NOTYPE
5763 : : || GELF_ST_TYPE (sym.st_info) == STT_OBJECT) // PR10000: .data
5764 : : && !(sym.st_shndx == SHN_UNDEF // Value undefined,
5765 : : || shndxp == (GElf_Word) -1 // in a non-allocated section,
5766 : : || sym_addr >= end // beyond current module,
5767 [ + - ][ + + ]: 1412252 : || sym_addr < base)) // before first section.
[ + + ]
5768 : : {
5769 : 1410443 : const char *secname = NULL;
5770 : 1410443 : unsigned secidx = 0; /* Most things have just one section. */
5771 : 1410443 : Dwarf_Addr func_desc_addr = 0; /* Function descriptor */
5772 : :
5773 : : /* PPC64 uses function descriptors.
5774 : : Note: for kernel ET_REL modules we rely on finding the
5775 : : .function symbols instead of going through the opd function
5776 : : descriptors. */
5777 [ - + ][ # # ]: 1410443 : if (ehdr->e_machine == EM_PPC64
[ # # ]
5778 : : && GELF_ST_TYPE (sym.st_info) == STT_FUNC
5779 : : && ehdr->e_type != ET_REL)
5780 : : {
5781 : : Elf64_Addr opd_addr;
5782 : : Dwarf_Addr opd_bias;
5783 : : Elf_Scn *opd;
5784 : :
5785 : 0 : func_desc_addr = sym_addr;
5786 : :
5787 [ # # ]: 0 : opd = dwfl_module_address_section (m, &sym_addr, &opd_bias);
5788 [ # # ][ # # ]: 0 : dwfl_assert ("dwfl_module_address_section opd", opd != NULL);
[ # # ]
5789 : :
5790 [ # # ]: 0 : Elf_Data *opd_data = elf_rawdata (opd, NULL);
5791 [ # # ]: 0 : assert(opd_data != NULL);
5792 : :
5793 : : Elf_Data opd_in, opd_out;
5794 : 0 : opd_out.d_buf = &opd_addr;
5795 : 0 : opd_in.d_buf = (char *) opd_data->d_buf + sym_addr;
5796 : 0 : opd_out.d_size = opd_in.d_size = sizeof (Elf64_Addr);
5797 : 0 : opd_out.d_type = opd_in.d_type = ELF_T_ADDR;
5798 [ # # ]: 0 : if (elf64_xlatetom (&opd_out, &opd_in,
5799 [ # # ]: 0 : ehdr->e_ident[EI_DATA]) == NULL)
5800 [ # # ][ # # ]: 0 : throw runtime_error ("elf64_xlatetom failed");
5801 : :
5802 : : // So the real address of the function is...
5803 : 0 : sym_addr = opd_addr + opd_bias;
5804 : : }
5805 : :
5806 [ + + ]: 1410443 : if (n > 0) // only try to relocate if there exist relocation bases
5807 : : {
5808 [ + - ]: 1410419 : int ki = dwfl_module_relocate_address (m, &sym_addr);
5809 [ + - ][ + - ]: 1410419 : dwfl_assert ("dwfl_module_relocate_address sym_addr", ki >= 0);
[ + - ]
5810 [ + - ]: 1410419 : secname = dwfl_module_relocation_info (m, ki, NULL);
5811 : :
5812 [ - + ]: 1410419 : if (func_desc_addr != 0)
5813 [ # # ]: 0 : dwfl_module_relocate_address (m, &func_desc_addr);
5814 : : }
5815 : :
5816 [ + + ][ + - ]: 1410443 : if (n == 1 && is_kernel)
5817 : : {
5818 : : // This is a symbol within a (possibly relocatable)
5819 : : // kernel image.
5820 : :
5821 : : // We only need the function symbols to identify kernel-mode
5822 : : // PC's, so we omit undefined or "fake" absolute addresses.
5823 : : // These fake absolute addresses occur in some older i386
5824 : : // kernels to indicate they are vDSO symbols, not real
5825 : : // functions in the kernel. We also omit symbols that have
5826 [ + + ][ - + ]: 1393389 : if (GELF_ST_TYPE (sym.st_info) == STT_FUNC
5827 : : && sym.st_shndx == SHN_ABS)
5828 : 0 : continue;
5829 : :
5830 : 1393389 : secname = "_stext";
5831 : : // NB: don't subtract session.sym_stext, which could be
5832 : : // inconveniently NULL. Instead, sym_addr will get
5833 : : // compensated later via extra_offset.
5834 : : }
5835 [ + + ]: 17054 : else if (n > 0)
5836 : : {
5837 [ - + ]: 17030 : assert (secname != NULL);
5838 : : // secname adequately set
5839 : :
5840 : : // NB: it may be an empty string for ET_DYN objects
5841 : : // like shared libraries, as their relocation base
5842 : : // is implicit.
5843 [ - + ]: 17030 : if (secname[0] == '\0')
5844 : 0 : secname = ".dynamic";
5845 : : else
5846 : : {
5847 : : // Compute our section number
5848 [ + - ]: 82586 : for (secidx = 0; secidx < c->seclist.size(); secidx++)
5849 [ + - ][ + + ]: 82586 : if (c->seclist[secidx].first==secname)
5850 : 17030 : break;
5851 : :
5852 [ - + ]: 17030 : if (secidx == c->seclist.size()) // whoa! We messed up...
5853 : : {
5854 [ # # ]: 0 : string m = _F("%s has unknown section %s for sym %s",
5855 : : modname, secname, name);
5856 [ # # ]: 0 : throw runtime_error(m);
5857 : : }
5858 : : }
5859 : : }
5860 : : else
5861 : : {
5862 [ - + ]: 24 : assert (n == 0);
5863 : : // sym_addr is absolute, as it must be since there are
5864 : : // no relocation bases
5865 : 24 : secname = ".absolute"; // sentinel
5866 : : }
5867 : :
5868 [ + - ][ + - ]: 1410443 : (c->addrmap[secidx])[sym_addr] = name;
5869 : : /* If we have a function descriptor, register that address
5870 : : under the same name */
5871 [ - + ]: 1410443 : if (func_desc_addr != 0)
5872 [ # # ][ # # ]: 21417187 : (c->addrmap[secidx])[func_desc_addr] = name;
5873 : : }
5874 : : }
5875 : : }
5876 : :
5877 [ + + ]: 318 : if (is_kernel)
5878 : : {
5879 : 214 : c->stext_offset = extra_offset;
5880 : : // Must be relative to actual kernel load address.
5881 [ - + ]: 214 : if (kretprobe_trampoline_addr != (unsigned long) -1)
5882 : : c->stp_kretprobe_trampoline_addr = (kretprobe_trampoline_addr
5883 : 0 : - extra_offset);
5884 : : }
5885 : :
5886 : 318 : return DWARF_CB_OK;
5887 : : }
5888 : :
5889 : : static int
5890 : 69 : dump_unwind_tables (Dwfl_Module *m,
5891 : : unwindsym_dump_context *c,
5892 : : const char *name, Dwarf_Addr base)
5893 : : {
5894 : : // Add unwind data to be included if it exists for this module.
5895 : : get_unwind_data (m, &c->debug_frame, &c->eh_frame,
5896 : : &c->debug_len, &c->eh_len,
5897 : : &c->eh_addr, &c->eh_frame_hdr, &c->eh_frame_hdr_len,
5898 : : &c->debug_frame_hdr, &c->debug_frame_hdr_len,
5899 : : &c->debug_frame_off, &c->eh_frame_hdr_addr,
5900 : 69 : c->session);
5901 : 69 : return DWARF_CB_OK;
5902 : : }
5903 : :
5904 : : static void
5905 : 1428 : dump_unwindsym_cxt_table(systemtap_session& session, ostream& output,
5906 : : const string& modname, unsigned modindex,
5907 : : const string& secname, unsigned secindex,
5908 : : const string& table, void*& data, size_t& len)
5909 : : {
5910 [ + + ][ - + ]: 1428 : if (data == NULL || len == 0)
5911 : 1289 : return;
5912 : :
5913 [ - + ]: 139 : if (len > MAX_UNWIND_TABLE_SIZE)
5914 : : {
5915 [ # # ]: 0 : if (secname.empty())
5916 : 0 : session.print_warning (_F("skipping module %s %s table (too big: %zi > %zi)",
5917 : : modname.c_str(), table.c_str(),
5918 [ # # ]: 0 : len, (size_t)MAX_UNWIND_TABLE_SIZE));
5919 : : else
5920 : 0 : session.print_warning (_F("skipping module %s, section %s %s table (too big: %zi > %zi)",
5921 : : modname.c_str(), secname.c_str(), table.c_str(),
5922 [ # # ]: 0 : len, (size_t)MAX_UNWIND_TABLE_SIZE));
5923 : 0 : data = NULL;
5924 : 0 : len = 0;
5925 : 0 : return;
5926 : : }
5927 : :
5928 : 139 : output << "#if defined(STP_USE_DWARF_UNWINDER) && defined(STP_NEED_UNWIND_DATA)\n";
5929 : 139 : output << "static uint8_t _stp_module_" << modindex << "_" << table;
5930 [ + + ]: 139 : if (!secname.empty())
5931 : 69 : output << "_" << secindex;
5932 : 139 : output << "[] = \n";
5933 : 139 : output << " {";
5934 [ + + ]: 23282539 : for (size_t i = 0; i < len; i++)
5935 : : {
5936 : 23282400 : int h = ((uint8_t *)data)[i];
5937 : 23282400 : output << h << ","; // decimal is less wordy than hex
5938 [ + + ]: 23282400 : if ((i + 1) % 16 == 0)
5939 : 1455098 : output << "\n" << " ";
5940 : : }
5941 : 139 : output << "};\n";
5942 : 1428 : output << "#endif /* STP_USE_DWARF_UNWINDER && STP_NEED_UNWIND_DATA */\n";
5943 : : }
5944 : :
5945 : : static int
5946 : 357 : dump_unwindsym_cxt (Dwfl_Module *m,
5947 : : unwindsym_dump_context *c,
5948 : : const char *name, Dwarf_Addr base)
5949 : : {
5950 [ + - ]: 357 : string modname = name;
5951 : 357 : unsigned stpmod_idx = c->stp_module_index;
5952 : 357 : void *debug_frame = c->debug_frame;
5953 : 357 : size_t debug_len = c->debug_len;
5954 : 357 : void *debug_frame_hdr = c->debug_frame_hdr;
5955 : 357 : size_t debug_frame_hdr_len = c->debug_frame_hdr_len;
5956 : 357 : Dwarf_Addr debug_frame_off = c->debug_frame_off;
5957 : 357 : void *eh_frame = c->eh_frame;
5958 : 357 : void *eh_frame_hdr = c->eh_frame_hdr;
5959 : 357 : size_t eh_len = c->eh_len;
5960 : 357 : size_t eh_frame_hdr_len = c->eh_frame_hdr_len;
5961 : 357 : Dwarf_Addr eh_addr = c->eh_addr;
5962 : 357 : Dwarf_Addr eh_frame_hdr_addr = c->eh_frame_hdr_addr;
5963 : :
5964 : : dump_unwindsym_cxt_table(c->session, c->output, modname, stpmod_idx, "", 0,
5965 [ + - ][ + - ]: 357 : "debug_frame", debug_frame, debug_len);
[ + - ][ + - ]
[ + - ]
5966 : :
5967 : : dump_unwindsym_cxt_table(c->session, c->output, modname, stpmod_idx, "", 0,
5968 [ + - ][ + - ]: 357 : "eh_frame", eh_frame, eh_len);
[ + - ][ + - ]
[ + - ]
5969 : :
5970 : : dump_unwindsym_cxt_table(c->session, c->output, modname, stpmod_idx, "", 0,
5971 [ + - ][ + - ]: 357 : "eh_frame_hdr", eh_frame_hdr, eh_frame_hdr_len);
[ + - ][ + - ]
[ + - ]
5972 : :
5973 [ + + ][ - + ]: 357 : if (c->session.need_unwind && debug_frame == NULL && eh_frame == NULL)
[ # # ]
5974 : : {
5975 : : // There would be only a small benefit to warning. A user
5976 : : // likely can't do anything about this; backtraces for the
5977 : : // affected module would just get all icky heuristicy.
5978 : : // So only report in verbose mode.
5979 [ # # ]: 0 : if (c->session.verbose > 2)
5980 : : c->session.print_warning ("No unwind data for " + modname
5981 [ # # ][ # # ]: 0 : + ", " + dwfl_errmsg (-1));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
5982 : : }
5983 : :
5984 [ + + ]: 2536 : for (unsigned secidx = 0; secidx < c->seclist.size(); secidx++)
5985 : : {
5986 [ + - ]: 2179 : c->output << "static struct _stp_symbol "
5987 [ + - ][ + - ]: 2179 : << "_stp_module_" << stpmod_idx<< "_symbols_" << secidx << "[] = {\n";
[ + - ][ + - ]
[ + - ]
5988 : :
5989 [ + - ]: 2179 : string secname = c->seclist[secidx].first;
5990 : : Dwarf_Addr extra_offset;
5991 [ + - ][ + + ]: 2179 : extra_offset = (secname == "_stext") ? c->stext_offset : 0;
5992 : :
5993 : : // Only include symbols if they will be used
5994 [ + + ]: 2179 : if (c->session.need_symbols)
5995 : : {
5996 : : // We write out a *sorted* symbol table, so the runtime doesn't
5997 : : // have to sort them later.
5998 [ + - ][ + - ]: 2774366 : for (addrmap_t::iterator it = c->addrmap[secidx].begin();
[ + + ]
5999 [ + - ][ + - ]: 1387183 : it != c->addrmap[secidx].end(); it++)
6000 : : {
6001 : : // skip symbols that occur before our chosen base address
6002 [ + - ][ + + ]: 1385551 : if (it->first < extra_offset)
6003 : 135 : continue;
6004 : :
6005 [ + - ][ + - ]: 1385416 : c->output << " { 0x" << hex << it->first-extra_offset << dec
[ + - ][ + - ]
[ + - ]
6006 [ + - ][ + - ]: 1385416 : << ", " << lex_cast_qstring (it->second) << " },\n";
[ + - ][ + - ]
[ + - ][ + - ]
6007 : : // XXX: these literal strings all suffer ELF relocation bloat too.
6008 : : // See if the tapsets.cxx:dwarf_derived_probe_group::emit_module_decls
6009 : : // CALCIT hack could work here.
6010 : : }
6011 : : }
6012 : :
6013 [ + - ]: 2179 : c->output << "};\n";
6014 : :
6015 : : /* For now output debug_frame index only in "magic" sections. */
6016 [ + - ][ + + ]: 6376 : if (secname == ".dynamic" || secname == ".absolute"
[ + - ][ + + ]
[ + + ][ + + ]
[ + + ]
6017 [ + - ][ + - ]: 4197 : || secname == ".text" || secname == "_stext")
6018 : : {
6019 : : dump_unwindsym_cxt_table(c->session, c->output, modname, stpmod_idx, secname, secidx,
6020 [ + - ][ + - ]: 357 : "debug_frame_hdr", debug_frame_hdr, debug_frame_hdr_len);
[ + - ]
6021 : : }
6022 [ + - ]: 2179 : }
6023 : :
6024 [ + - ][ + - ]: 357 : c->output << "static struct _stp_section _stp_module_" << stpmod_idx<< "_sections[] = {\n";
[ + - ]
6025 : : // For the kernel, executables (ET_EXEC) or shared libraries (ET_DYN)
6026 : : // there is just one section that covers the whole address space of
6027 : : // the module. For kernel modules (ET_REL) there can be multiple
6028 : : // sections that get relocated separately.
6029 [ + + ]: 2536 : for (unsigned secidx = 0; secidx < c->seclist.size(); secidx++)
6030 : : {
6031 [ + - ]: 2179 : c->output << "{\n"
6032 [ + - ][ + - ]: 4358 : << ".name = " << lex_cast_qstring(c->seclist[secidx].first) << ",\n"
[ + - ][ + - ]
[ + - ]
6033 [ + - ][ + - ]: 2179 : << ".size = 0x" << hex << c->seclist[secidx].second << dec << ",\n"
[ + - ][ + - ]
[ + - ]
6034 [ + - ][ + - ]: 2179 : << ".symbols = _stp_module_" << stpmod_idx << "_symbols_" << secidx << ",\n"
[ + - ][ + - ]
[ + - ]
6035 [ + - ][ + - ]: 2179 : << ".num_symbols = " << c->addrmap[secidx].size() << ",\n";
[ + - ][ + - ]
[ + - ]
6036 : :
6037 : : /* For now output debug_frame index only in "magic" sections. */
6038 [ + - ]: 2179 : string secname = c->seclist[secidx].first;
6039 [ + + ][ + - ]: 3767 : if (debug_frame_hdr && (secname == ".dynamic" || secname == ".absolute"
[ + - ][ + - ]
[ + + ][ + + ]
[ + + ][ + + ]
6040 [ + - ][ + - ]: 1588 : || secname == ".text" || secname == "_stext"))
6041 : : {
6042 [ + - ]: 69 : c->output << "#if defined(STP_USE_DWARF_UNWINDER)"
6043 [ + - ]: 69 : << " && defined(STP_NEED_UNWIND_DATA)\n";
6044 : :
6045 [ + - ]: 69 : c->output << ".debug_hdr = "
6046 [ + - ][ + - ]: 69 : << "_stp_module_" << stpmod_idx
6047 [ + - ][ + - ]: 69 : << "_debug_frame_hdr_" << secidx << ",\n";
[ + - ]
6048 [ + - ][ + - ]: 69 : c->output << ".debug_hdr_len = " << debug_frame_hdr_len << ", \n";
[ + - ]
6049 : :
6050 : 69 : Dwarf_Addr dwbias = 0;
6051 [ + - ]: 69 : dwfl_module_getdwarf (m, &dwbias);
6052 [ + - ]: 69 : c->output << ".sec_load_offset = 0x"
6053 [ + - ][ + - ]: 69 : << hex << debug_frame_off - dwbias << dec << "\n";
[ + - ][ + - ]
6054 : :
6055 [ + - ]: 69 : c->output << "#else\n";
6056 [ + - ]: 69 : c->output << ".debug_hdr = NULL,\n";
6057 [ + - ]: 69 : c->output << ".debug_hdr_len = 0,\n";
6058 [ + - ]: 69 : c->output << ".sec_load_offset = 0\n";
6059 [ + - ]: 69 : c->output << "#endif /* STP_USE_DWARF_UNWINDER"
6060 [ + - ]: 69 : << " && STP_NEED_UNWIND_DATA */\n";
6061 : :
6062 : : }
6063 : : else
6064 : : {
6065 [ + - ]: 2110 : c->output << ".debug_hdr = NULL,\n";
6066 [ + - ]: 2110 : c->output << ".debug_hdr_len = 0,\n";
6067 [ + - ]: 2110 : c->output << ".sec_load_offset = 0\n";
6068 : : }
6069 : :
6070 [ + - ]: 2179 : c->output << "},\n";
6071 [ + - ]: 2179 : }
6072 [ + - ]: 357 : c->output << "};\n";
6073 : :
6074 : : // Get the canonical path of the main file for comparison at runtime.
6075 : : // When given directly by the user through -d or in case of the kernel
6076 : : // name and path might differ. path should be used for matching.
6077 : : const char *mainfile;
6078 [ + - ]: 357 : dwfl_module_info (m, NULL, NULL, NULL, NULL, NULL, &mainfile, NULL);
6079 : :
6080 : : // For user space modules store canonical path and base name.
6081 : : // For kernel modules just the name itself.
6082 : 357 : const char *mainpath = canonicalize_file_name(mainfile);
6083 : 357 : const char *mainname = strrchr(mainpath, '/');
6084 [ + - ][ + + ]: 357 : if (modname[0] == '/')
6085 : 18 : mainname++;
6086 : : else
6087 [ + - ]: 339 : mainname = modname.c_str();
6088 : :
6089 [ + - ][ + - ]: 357 : c->output << "static struct _stp_module _stp_module_" << stpmod_idx << " = {\n";
[ + - ]
6090 [ + - ][ + - ]: 357 : c->output << ".name = " << lex_cast_qstring (mainname) << ", \n";
[ + - ][ + - ]
[ + - ]
6091 [ + - ][ + - ]: 357 : c->output << ".path = " << lex_cast_qstring (path_remove_sysroot(c->session,mainpath)) << ",\n";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
6092 [ + - ][ + - ]: 357 : c->output << ".eh_frame_addr = 0x" << hex << eh_addr << dec << ", \n";
[ + - ][ + - ]
[ + - ]
6093 [ + - ][ + - ]: 357 : c->output << ".unwind_hdr_addr = 0x" << hex << eh_frame_hdr_addr
[ + - ]
6094 [ + - ][ + - ]: 357 : << dec << ", \n";
6095 : :
6096 [ + + ]: 357 : if (debug_frame != NULL)
6097 : : {
6098 [ + - ]: 69 : c->output << "#if defined(STP_USE_DWARF_UNWINDER) && defined(STP_NEED_UNWIND_DATA)\n";
6099 [ + - ]: 69 : c->output << ".debug_frame = "
6100 [ + - ][ + - ]: 69 : << "_stp_module_" << stpmod_idx << "_debug_frame, \n";
[ + - ]
6101 [ + - ][ + - ]: 69 : c->output << ".debug_frame_len = " << debug_len << ", \n";
[ + - ]
6102 [ + - ]: 69 : c->output << "#else\n";
6103 : : }
6104 : :
6105 [ + - ]: 357 : c->output << ".debug_frame = NULL,\n";
6106 [ + - ]: 357 : c->output << ".debug_frame_len = 0,\n";
6107 : :
6108 [ + + ]: 357 : if (debug_frame != NULL)
6109 [ + - ]: 69 : c->output << "#endif /* STP_USE_DWARF_UNWINDER && STP_NEED_UNWIND_DATA*/\n";
6110 : :
6111 [ + + ]: 357 : if (eh_frame != NULL)
6112 : : {
6113 [ + - ]: 1 : c->output << "#if defined(STP_USE_DWARF_UNWINDER) && defined(STP_NEED_UNWIND_DATA)\n";
6114 [ + - ]: 1 : c->output << ".eh_frame = "
6115 [ + - ][ + - ]: 1 : << "_stp_module_" << stpmod_idx << "_eh_frame, \n";
[ + - ]
6116 [ + - ][ + - ]: 1 : c->output << ".eh_frame_len = " << eh_len << ", \n";
[ + - ]
6117 [ - + ]: 1 : if (eh_frame_hdr)
6118 : : {
6119 [ # # ]: 0 : c->output << ".unwind_hdr = "
6120 [ # # ][ # # ]: 0 : << "_stp_module_" << stpmod_idx << "_eh_frame_hdr, \n";
[ # # ]
6121 [ # # ][ # # ]: 0 : c->output << ".unwind_hdr_len = " << eh_frame_hdr_len << ", \n";
[ # # ]
6122 : : }
6123 : : else
6124 : : {
6125 [ + - ]: 1 : c->output << ".unwind_hdr = NULL,\n";
6126 [ + - ]: 1 : c->output << ".unwind_hdr_len = 0,\n";
6127 : : }
6128 [ + - ]: 1 : c->output << "#else\n";
6129 : : }
6130 : :
6131 [ + - ]: 357 : c->output << ".eh_frame = NULL,\n";
6132 [ + - ]: 357 : c->output << ".eh_frame_len = 0,\n";
6133 [ + - ]: 357 : c->output << ".unwind_hdr = NULL,\n";
6134 [ + - ]: 357 : c->output << ".unwind_hdr_len = 0,\n";
6135 [ + + ]: 357 : if (eh_frame != NULL)
6136 [ + - ]: 1 : c->output << "#endif /* STP_USE_DWARF_UNWINDER && STP_NEED_UNWIND_DATA*/\n";
6137 [ + - ][ + - ]: 357 : c->output << ".sections = _stp_module_" << stpmod_idx << "_sections" << ",\n";
[ + - ][ + - ]
6138 [ + - ][ + - ]: 357 : c->output << ".num_sections = sizeof(_stp_module_" << stpmod_idx << "_sections)/"
[ + - ]
6139 [ + - ]: 357 : << "sizeof(struct _stp_section),\n";
6140 : :
6141 : : /* Don't save build-id if it is located before _stext.
6142 : : * This probably means that build-id will not be loaded at all and
6143 : : * happens for example with ARM kernel. Allow user space modules since the
6144 : : * check fails for a shared object.
6145 : : *
6146 : : * See also:
6147 : : * http://sourceware.org/ml/systemtap/2009-q4/msg00574.html
6148 : : */
6149 [ + - ][ + + ]: 714 : if (c->build_id_len > 0
[ + - ][ + - ]
6150 [ + - ]: 357 : && (modname != "kernel" || (c->build_id_vaddr > base + c->stext_offset))) {
6151 [ + - ]: 357 : c->output << ".build_id_bits = (unsigned char *)\"" ;
6152 [ + + ]: 7497 : for (int j=0; j<c->build_id_len;j++)
6153 [ + - ][ + - ]: 7140 : c->output << "\\x" << hex
6154 [ + - ][ + - ]: 7140 : << (unsigned short) *(c->build_id_bits+j) << dec;
6155 : :
6156 [ + - ]: 357 : c->output << "\",\n";
6157 [ + - ][ + - ]: 357 : c->output << ".build_id_len = " << c->build_id_len << ",\n";
[ + - ]
6158 : :
6159 : : /* XXX: kernel data boot-time relocation works differently from text.
6160 : : This hack assumes that offset between _stext and build id
6161 : : stays constant after relocation, but that's not necessarily
6162 : : correct either. We may instead need a relocation basis different
6163 : : from _stext, such as __start_notes. */
6164 [ + - ][ + + ]: 357 : if (modname == "kernel")
6165 [ + - ][ + - ]: 214 : c->output << ".build_id_offset = 0x" << hex << c->build_id_vaddr - (base + c->stext_offset)
[ + - ]
6166 [ + - ][ + - ]: 214 : << dec << ",\n";
6167 : : // ET_DYN: task finder gives the load address. ET_EXEC: this is absolute address
6168 : : else
6169 [ + - ][ + - ]: 143 : c->output << ".build_id_offset = 0x" << hex
6170 [ + - ]: 143 : << c->build_id_vaddr /* - base */
6171 [ + - ][ + - ]: 143 : << dec << ",\n";
6172 : : } else
6173 [ # # ]: 0 : c->output << ".build_id_len = 0,\n";
6174 : :
6175 : : //initialize the note section representing unloaded
6176 [ + - ]: 357 : c->output << ".notes_sect = 0,\n";
6177 : :
6178 [ + - ]: 357 : c->output << "};\n\n";
6179 : :
6180 [ + - ]: 357 : c->undone_unwindsym_modules.erase (modname);
6181 : :
6182 : : // release various malloc'd tables
6183 : : // if (eh_frame_hdr) free (eh_frame_hdr); -- nope, this one comes from the elf image in memory
6184 [ + + ]: 357 : if (debug_frame_hdr) free (debug_frame_hdr);
6185 : :
6186 [ + - ]: 357 : return DWARF_CB_OK;
6187 : : }
6188 : :
6189 : : static int
6190 : 398 : dump_unwindsyms (Dwfl_Module *m,
6191 : : void **userdata __attribute__ ((unused)),
6192 : : const char *name,
6193 : : Dwarf_Addr base,
6194 : : void *arg)
6195 : : {
6196 [ - + ]: 398 : if (pending_interrupts)
6197 : 0 : return DWARF_CB_ABORT;
6198 : :
6199 : 398 : unwindsym_dump_context *c = (unwindsym_dump_context*) arg;
6200 [ - + ]: 398 : assert (c);
6201 : :
6202 : : // skip modules/files we're not actually interested in
6203 [ + - ]: 398 : string modname = name;
6204 [ + + ]: 398 : if (c->session.unwindsym_modules.find(modname)
6205 [ + - ][ + - ]: 398 : == c->session.unwindsym_modules.end())
6206 : 41 : return DWARF_CB_OK;
6207 : :
6208 [ + + ]: 357 : if (c->session.verbose > 1)
6209 [ + - ][ + - ]: 16 : clog << "dump_unwindsyms " << name
6210 [ + - ][ + - ]: 16 : << " index=" << c->stp_module_index
6211 [ + - ][ + - ]: 16 : << " base=0x" << hex << base << dec << endl;
[ + - ][ + - ]
[ + - ]
6212 : :
6213 : : // We want to extract several bits of information:
6214 : : //
6215 : : // - parts of the program-header that map the file's physical offsets to the text section
6216 : : // - section table: just a list of section (relocation) base addresses
6217 : : // - symbol table of the text-like sections, with all addresses relativized to each base
6218 : : // - the contents of .debug_frame and/or .eh_frame section, for unwinding purposes
6219 : :
6220 : 357 : int res = DWARF_CB_OK;
6221 : :
6222 : 357 : c->build_id_len = 0;
6223 : 357 : c->build_id_vaddr = 0;
6224 : 357 : c->build_id_bits = NULL;
6225 [ + - ]: 357 : res = dump_build_id (m, c, name, base);
6226 : :
6227 [ + - ]: 357 : c->seclist.clear();
6228 [ + - ]: 357 : if (res == DWARF_CB_OK)
6229 [ + - ]: 357 : res = dump_section_list(m, c, name, base);
6230 : :
6231 : : // We always need to check the symbols of the kernel if we use it,
6232 : : // for the extra_offset (also used for build_ids) and possibly
6233 : : // stp_kretprobe_trampoline_addr for the dwarf unwinder.
6234 [ + - ]: 357 : c->addrmap.clear();
6235 [ + - ][ + + ]: 357 : if (res == DWARF_CB_OK
[ + + ]
6236 : 226 : && (c->session.need_symbols || ! strcmp(name, "kernel")))
6237 [ + - ]: 318 : res = dump_symbol_tables (m, c, name, base);
6238 : :
6239 : 357 : c->debug_frame = NULL;
6240 : 357 : c->debug_len = 0;
6241 : 357 : c->debug_frame_hdr = NULL;
6242 : 357 : c->debug_frame_hdr_len = 0;
6243 : 357 : c->debug_frame_off = 0;
6244 : 357 : c->eh_frame = NULL;
6245 : 357 : c->eh_frame_hdr = NULL;
6246 : 357 : c->eh_len = 0;
6247 : 357 : c->eh_frame_hdr_len = 0;
6248 : 357 : c->eh_addr = 0;
6249 : 357 : c->eh_frame_hdr_addr = 0;
6250 [ + - ][ + + ]: 357 : if (res == DWARF_CB_OK && c->session.need_unwind)
6251 [ + - ]: 69 : res = dump_unwind_tables (m, c, name, base);
6252 : :
6253 : : /* And finally dump everything collected in the output. */
6254 [ + - ]: 357 : if (res == DWARF_CB_OK)
6255 [ + - ]: 357 : res = dump_unwindsym_cxt (m, c, name, base);
6256 : :
6257 [ + - ]: 357 : if (res == DWARF_CB_OK)
6258 : 357 : c->stp_module_index++;
6259 : :
6260 [ + - ]: 398 : return res;
6261 : : }
6262 : :
6263 : :
6264 : : // Emit symbol table & unwind data, plus any calls needed to register
6265 : : // them with the runtime.
6266 : : void emit_symbol_data_done (unwindsym_dump_context*, systemtap_session&);
6267 : :
6268 : :
6269 : : void
6270 : 11 : add_unwindsym_iol_callback (void *q, const char *data)
6271 : : {
6272 : 11 : std::set<std::string> *added = (std::set<std::string>*)q;
6273 [ + - ][ + - ]: 11 : added->insert (string (data));
[ + - ]
6274 : 11 : }
6275 : :
6276 : :
6277 : : static int
6278 : 1 : query_module (Dwfl_Module *mod,
6279 : : void **,
6280 : : const char *,
6281 : : Dwarf_Addr,
6282 : : void *arg)
6283 : : {
6284 : 1 : ((struct dwflpp*)arg)->focus_on_module(mod, NULL);
6285 : 1 : return DWARF_CB_OK;
6286 : : }
6287 : :
6288 : :
6289 : : void
6290 : 3 : add_unwindsym_ldd (systemtap_session &s)
6291 : : {
6292 [ + - ]: 3 : std::set<std::string> added;
6293 : :
6294 [ + - ][ + + ]: 62 : for (std::set<std::string>::iterator it = s.unwindsym_modules.begin();
6295 [ + - ]: 31 : it != s.unwindsym_modules.end();
6296 : : it++)
6297 : : {
6298 [ + - ]: 28 : string modname = *it;
6299 [ + - ][ - + ]: 28 : assert (modname.length() != 0);
6300 [ + - ][ + + ]: 28 : if (! is_user_module (modname)) continue;
6301 : :
6302 [ + - ][ + - ]: 2 : struct dwflpp *mod_dwflpp = new dwflpp(s, modname, false);
6303 [ + - ]: 2 : mod_dwflpp->iterate_over_modules (&query_module, mod_dwflpp);
6304 [ + + ]: 2 : if (mod_dwflpp->module) // existing binary
6305 : : {
6306 [ + - ][ - + ]: 1 : assert (mod_dwflpp->module_name != "");
6307 [ + - ]: 1 : mod_dwflpp->iterate_over_libraries (&add_unwindsym_iol_callback, &added);
6308 : : }
6309 [ + - ][ + - ]: 2 : delete mod_dwflpp;
6310 [ + - ][ + + ]: 28 : }
6311 : :
6312 [ + - ][ + - ]: 3 : s.unwindsym_modules.insert (added.begin(), added.end());
[ + - ][ + - ]
6313 : 3 : }
6314 : :
6315 : 0 : static int find_vdso(const char *path, const struct stat *, int type)
6316 : : {
6317 [ # # ]: 0 : if (type == FTW_F)
6318 : : {
6319 : 0 : const char *name = strrchr(path, '/');
6320 [ # # ]: 0 : if (name)
6321 : : {
6322 : 0 : name++;
6323 : 0 : const char *ext = strrchr(name, '.');
6324 [ # # ][ # # ]: 0 : if (ext
[ # # ]
6325 : 0 : && strncmp("vdso", name, 4) == 0
6326 : 0 : && strcmp(".so", ext) == 0)
6327 [ # # ][ # # ]: 0 : vdso_paths.insert(path);
[ # # ]
6328 : : }
6329 : : }
6330 : 0 : return 0;
6331 : : }
6332 : :
6333 : : void
6334 : 26 : add_unwindsym_vdso (systemtap_session &s)
6335 : : {
6336 : : // This is to disambiguate between -r REVISION vs -r BUILDDIR.
6337 : : // See also dwflsetup.c (setup_dwfl_kernel). In case of only
6338 : : // having the BUILDDIR we need to do a deep search (the specific
6339 : : // arch name dir in the kernel build tree is unknown).
6340 [ + - ]: 26 : string vdso_dir;
6341 [ + - ][ + - ]: 52 : if (s.kernel_build_tree == string(s.sysroot + "/lib/modules/"
6342 : : + s.kernel_release
6343 [ + - ][ + - ]: 52 : + "/build"))
[ + - ][ + - ]
[ + - ][ + - ]
6344 [ + - ][ + - ]: 26 : vdso_dir = s.sysroot + "/lib/modules/" + s.kernel_release + "/vdso";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
6345 : : else
6346 [ # # ][ # # ]: 0 : vdso_dir = s.kernel_build_tree + "/arch/";
[ # # ]
6347 : :
6348 [ + + ]: 26 : if (s.verbose > 1)
6349 [ + - ][ + - ]: 1 : clog << _("Searching for vdso candidates: ") << vdso_dir << endl;
[ + - ]
6350 : :
6351 [ + - ][ + - ]: 26 : ftw(vdso_dir.c_str(), find_vdso, 1);
6352 : :
6353 [ + - ][ - + ]: 52 : for (set<string>::iterator it = vdso_paths.begin();
6354 [ + - ]: 26 : it != vdso_paths.end();
6355 : : it++)
6356 : : {
6357 [ # # ]: 0 : s.unwindsym_modules.insert(*it);
6358 [ # # ]: 0 : if (s.verbose > 1)
6359 [ # # ][ # # ]: 0 : clog << _("vdso candidate: ") << *it << endl;
[ # # ]
6360 [ + - ]: 26 : }
6361 : 26 : }
6362 : :
6363 : : static void
6364 : 831 : prepare_symbol_data (systemtap_session& s)
6365 : : {
6366 : : // step 0: run ldd on any user modules if requested
6367 [ + + ]: 831 : if (s.unwindsym_ldd)
6368 : 3 : add_unwindsym_ldd (s);
6369 : : // step 0.5: add vdso(s) when vma tracker was requested
6370 [ + + ]: 831 : if (vma_tracker_enabled (s))
6371 : 26 : add_unwindsym_vdso (s);
6372 : : // NB: do this before the ctx.unwindsym_modules copy is taken
6373 : 831 : }
6374 : :
6375 : : void
6376 : 644 : emit_symbol_data (systemtap_session& s)
6377 : : {
6378 [ + - ]: 644 : string symfile = "stap-symbols.h";
6379 : :
6380 [ + - ][ + - ]: 644 : s.op->newline() << "#include " << lex_cast_qstring (symfile);
[ + - ][ + - ]
[ + - ]
6381 : :
6382 [ + - ][ + - ]: 644 : ofstream kallsyms_out ((s.tmpdir + "/" + symfile).c_str());
[ + - ][ + - ]
[ + - ][ + - ]
6383 : :
6384 [ + - ]: 644 : vector<pair<string,unsigned> > seclist;
6385 [ + - ]: 644 : map<unsigned, addrmap_t> addrmap;
6386 : : unwindsym_dump_context ctx = { s, kallsyms_out,
6387 : : 0, /* module index */
6388 : : 0, NULL, 0, /* build_id len, bits, vaddr */
6389 : : ~0UL, /* stp_kretprobe_trampoline_addr */
6390 : : 0, /* stext_offset */
6391 : : seclist, addrmap,
6392 : : NULL, /* debug_frame */
6393 : : 0, /* debug_len */
6394 : : NULL, /* debug_frame_hdr */
6395 : : 0, /* debug_frame_hdr_len */
6396 : : 0, /* debug_frame_off */
6397 : : NULL, /* eh_frame */
6398 : : NULL, /* eh_frame_hdr */
6399 : : 0, /* eh_len */
6400 : : 0, /* eh_frame_hdr_len */
6401 : : 0, /* eh_addr */
6402 : : 0, /* eh_frame_hdr_addr */
6403 [ + - ][ + - ]: 644 : s.unwindsym_modules };
[ + - ]
6404 : :
6405 : : // Micro optimization, mainly to speed up tiny regression tests
6406 : : // using just begin probe.
6407 [ + - ][ + + ]: 644 : if (s.unwindsym_modules.size () == 0)
6408 : : {
6409 [ + - ]: 414 : emit_symbol_data_done(&ctx, s);
6410 : 644 : return;
6411 : : }
6412 : :
6413 : : // ---- step 1: process any kernel modules listed
6414 [ + - ]: 230 : set<string> offline_search_modules;
6415 : : unsigned count;
6416 [ + - ][ + + ]: 1176 : for (set<string>::iterator it = s.unwindsym_modules.begin();
6417 [ + - ]: 588 : it != s.unwindsym_modules.end();
6418 : : it++)
6419 : : {
6420 [ + - ]: 358 : string foo = *it;
6421 [ + - ][ + + ]: 358 : if (! is_user_module (foo)) /* Omit user-space, since we're only
6422 : : using this for kernel space
6423 : : offline searches. */
6424 [ + - ]: 339 : offline_search_modules.insert (foo);
6425 [ + - ]: 358 : }
6426 [ + - ]: 230 : DwflPtr dwfl_ptr = setup_dwfl_kernel (offline_search_modules, &count, s);
6427 : 230 : Dwfl *dwfl = dwfl_ptr.get()->dwfl;
6428 : : /* NB: It's not an error to find a few fewer modules than requested.
6429 : : There might be third-party modules loaded (e.g. uprobes). */
6430 : : /* dwfl_assert("all kernel modules found",
6431 : : count >= offline_search_modules.size()); */
6432 : :
6433 : 230 : ptrdiff_t off = 0;
6434 [ - + ]: 230 : do
6435 : : {
6436 [ + - ]: 230 : assert_no_interrupts();
6437 [ + - ][ - + ]: 230 : if (ctx.undone_unwindsym_modules.empty()) break;
6438 [ + - ]: 230 : off = dwfl_getmodules (dwfl, &dump_unwindsyms, (void *) &ctx, off);
6439 : : }
6440 : : while (off > 0);
6441 [ + - ][ + - ]: 230 : dwfl_assert("dwfl_getmodules", off == 0);
[ + - ]
6442 [ + - ]: 230 : dwfl_ptr.reset();
6443 : :
6444 : : // ---- step 2: process any user modules (files) listed
6445 [ + - ][ + + ]: 1176 : for (std::set<std::string>::iterator it = s.unwindsym_modules.begin();
6446 [ + - ]: 588 : it != s.unwindsym_modules.end();
6447 : : it++)
6448 : : {
6449 [ + - ]: 358 : string modname = *it;
6450 [ + - ][ - + ]: 358 : assert (modname.length() != 0);
6451 [ + - ][ + + ]: 358 : if (! is_user_module (modname)) continue;
6452 [ + - ]: 19 : DwflPtr dwfl_ptr = setup_dwfl_user (modname);
6453 : 19 : Dwfl *dwfl = dwfl_ptr.get()->dwfl;
6454 [ + + ]: 19 : if (dwfl != NULL) // tolerate missing data; will warn below
6455 : : {
6456 : 18 : ptrdiff_t off = 0;
6457 [ - + ]: 18 : do
6458 : : {
6459 [ + - ]: 18 : assert_no_interrupts();
6460 [ + - ][ - + ]: 18 : if (ctx.undone_unwindsym_modules.empty()) break;
6461 [ + - ]: 18 : off = dwfl_getmodules (dwfl, &dump_unwindsyms, (void *) &ctx, off);
6462 : : }
6463 : : while (off > 0);
6464 [ + - ][ + - ]: 18 : dwfl_assert("dwfl_getmodules", off == 0);
[ + - ]
6465 : : }
6466 [ + - ]: 19 : dwfl_ptr.reset();
6467 [ + - ][ + - ]: 358 : }
[ + + ]
6468 : :
6469 [ + - ][ + - ]: 644 : emit_symbol_data_done (&ctx, s);
[ + - ][ + - ]
[ + + ][ + - ]
[ + + ][ + - ]
[ + + ][ + - ]
[ + + ][ + - ]
[ + + ]
6470 : : }
6471 : :
6472 : : void
6473 : 644 : emit_symbol_data_done (unwindsym_dump_context *ctx, systemtap_session& s)
6474 : : {
6475 : : // Print out a definition of the runtime's _stp_modules[] globals.
6476 : 644 : ctx->output << "\n";
6477 : 644 : ctx->output << "static struct _stp_module *_stp_modules [] = {\n";
6478 [ + + ]: 1001 : for (unsigned i=0; i<ctx->stp_module_index; i++)
6479 : : {
6480 : 357 : ctx->output << "& _stp_module_" << i << ",\n";
6481 : : }
6482 : 644 : ctx->output << "};\n";
6483 : 644 : ctx->output << "static unsigned _stp_num_modules = " << ctx->stp_module_index << ";\n";
6484 : :
6485 : 644 : ctx->output << "static unsigned long _stp_kretprobe_trampoline = ";
6486 : : // Special case for -1, which is invalid in hex if host width > target width.
6487 [ + - ]: 644 : if (ctx->stp_kretprobe_trampoline_addr == (unsigned long) -1)
6488 : 644 : ctx->output << "-1;\n";
6489 : : else
6490 : 0 : ctx->output << "0x" << hex << ctx->stp_kretprobe_trampoline_addr << dec
6491 : 0 : << ";\n";
6492 : :
6493 : : // Some nonexistent modules may have been identified with "-d". Note them.
6494 [ + + ]: 644 : if (! s.suppress_warnings)
6495 [ + - ][ + + ]: 1256 : for (set<string>::iterator it = ctx->undone_unwindsym_modules.begin();
6496 [ + - ]: 628 : it != ctx->undone_unwindsym_modules.end();
6497 : : it ++)
6498 : 25 : s.print_warning (_("missing unwind/symbol data for module '")
6499 [ + - ][ + - ]: 25 : + (*it) + "'");
[ + - ][ + - ]
[ + - ]
6500 : 644 : }
6501 : :
6502 : :
6503 : :
6504 : :
6505 [ + - ][ - + ]: 645 : struct recursion_info: public traversing_visitor
6506 : : {
6507 [ + - ]: 645 : recursion_info (systemtap_session& s): sess(s), nesting_max(0), recursive(false) {}
6508 : : systemtap_session& sess;
6509 : : unsigned nesting_max;
6510 : : bool recursive;
6511 : : std::vector <functiondecl *> current_nesting;
6512 : :
6513 : 6383 : void visit_functioncall (functioncall* e) {
6514 : 6383 : traversing_visitor::visit_functioncall (e); // for arguments
6515 : :
6516 : : // check for nesting level
6517 : 6383 : unsigned nesting_depth = current_nesting.size() + 1;
6518 [ + + ]: 6383 : if (nesting_max < nesting_depth)
6519 : : {
6520 [ - + ]: 347 : if (sess.verbose > 3)
6521 [ # # ]: 0 : clog << _F("identified max-nested function: %s (%d)",
6522 [ # # ]: 0 : e->referent->name.c_str(), nesting_depth) << endl;
6523 : 347 : nesting_max = nesting_depth;
6524 : : }
6525 : :
6526 : : // check for (direct or mutual) recursion
6527 [ + + ]: 11055 : for (unsigned j=0; j<current_nesting.size(); j++)
6528 [ + + ]: 4676 : if (current_nesting[j] == e->referent)
6529 : : {
6530 : 4 : recursive = true;
6531 [ - + ]: 4 : if (sess.verbose > 3)
6532 [ # # ][ # # ]: 0 : clog << _F("identified recursive function: %s", e->referent->name.c_str()) << endl;
6533 : 6383 : return;
6534 : : }
6535 : :
6536 : : // non-recursive traversal
6537 : 6379 : current_nesting.push_back (e->referent);
6538 : 6379 : e->referent->body->visit (this);
6539 : 6379 : current_nesting.pop_back ();
6540 : : }
6541 : : };
6542 : :
6543 : :
6544 : 645 : void translate_runtime(systemtap_session& s)
6545 : : {
6546 : 645 : s.op->newline() << "#define STAP_MSG_RUNTIME_H_01 "
6547 : 645 : << lex_cast_qstring(_("myproc-unprivileged tapset function called "
6548 [ + - ][ + - ]: 645 : "without is_myproc checking for pid %d (euid %d)"));
[ + - ]
6549 : :
6550 : 645 : s.op->newline() << "#define STAP_MSG_LOC2C_01 "
6551 [ + - ][ + - ]: 645 : << lex_cast_qstring(_("read fault [man error::fault] at 0x%p (%s)"));
[ + - ]
6552 : 645 : s.op->newline() << "#define STAP_MSG_LOC2C_02 "
6553 [ + - ][ + - ]: 645 : << lex_cast_qstring(_("write fault [man error::fault] at 0x%p (%s)"));
[ + - ]
6554 : 645 : s.op->newline() << "#define STAP_MSG_LOC2C_03 "
6555 [ + - ][ + - ]: 645 : << lex_cast_qstring(_("divide by zero in DWARF operand (%s)"));
[ + - ]
6556 : 645 : }
6557 : :
6558 : :
6559 : : int
6560 : 831 : prepare_translate_pass (systemtap_session& s)
6561 : : {
6562 : 831 : int rc = 0;
6563 : : try
6564 : : {
6565 [ + - ]: 831 : prepare_symbol_data (s);
6566 : : }
6567 [ # # ]: : catch (const semantic_error& e)
6568 : : {
6569 [ # # ]: : s.print_error (e);
6570 : : rc = 1;
6571 : : }
6572 : :
6573 : 831 : return rc;
6574 : : }
6575 : :
6576 : :
6577 : : int
6578 : 645 : translate_pass (systemtap_session& s)
6579 : : {
6580 : 645 : int rc = 0;
6581 : :
6582 [ + - ][ + - ]: 645 : s.op = new translator_output (s.translated_source);
6583 : : // additional outputs might be found in s.auxiliary_outputs
6584 [ + - ]: 645 : c_unparser cup (& s);
6585 : 645 : s.up = & cup;
6586 [ + - ]: 645 : translate_runtime(s);
6587 : :
6588 : : try
6589 : : {
6590 : 645 : int64_t major=0, minor=0;
6591 : : try
6592 : : {
6593 [ + - ]: 645 : vector<string> versions;
6594 [ + - ][ + - ]: 645 : tokenize (s.compatible, versions, ".");
[ + - ]
6595 [ + - ]: 645 : if (versions.size() >= 1)
6596 [ + - ]: 645 : major = lex_cast<int64_t> (versions[0]);
6597 [ + - ]: 645 : if (versions.size() >= 2)
6598 [ + - ]: 645 : minor = lex_cast<int64_t> (versions[1]);
6599 [ + + ][ - + ]: 645 : if (versions.size() >= 3 && s.verbose > 1)
[ - + ]
6600 [ # # ][ # # ]: 645 : clog << _F("ignoring extra parts of compat version: %s", s.compatible.c_str()) << endl;
[ # # ][ # # ]
[ # # ][ + - ]
6601 : : }
6602 [ # # ]: : catch (const runtime_error)
6603 : : {
6604 [ # # # # : : throw semantic_error(_F("parse error in compatibility version: %s", s.compatible.c_str()));
# # ]
6605 : : }
6606 [ + - ][ + - ]: 645 : if (major < 0 || major > 255 || minor < 0 || minor > 255)
[ + - ][ - + ]
6607 [ # # ][ # # ]: 0 : throw semantic_error(_F("compatibility version out of range: %s", s.compatible.c_str()));
[ # # ]
6608 [ + - ][ + - ]: 645 : s.op->newline() << "#define STAP_VERSION(a, b) ( ((a) << 8) + (b) )";
6609 [ + - ][ + - ]: 645 : s.op->newline() << "#ifndef STAP_COMPAT_VERSION";
6610 [ + - ][ + - ]: 645 : s.op->newline() << "#define STAP_COMPAT_VERSION STAP_VERSION("
6611 [ + - ][ + - ]: 645 : << major << ", " << minor << ")";
[ + - ][ + - ]
6612 [ + - ][ + - ]: 645 : s.op->newline() << "#endif";
6613 : :
6614 [ + - ]: 645 : recursion_info ri (s);
6615 : :
6616 : : // NB: we start our traversal from the s.functions[] rather than the probes.
6617 : : // We assume that each function is called at least once, or else it would have
6618 : : // been elided already.
6619 [ + - ][ + - ]: 7022 : for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
[ + + ]
6620 : : {
6621 [ + - ]: 6377 : functiondecl *fd = it->second;
6622 [ + - ]: 6377 : fd->body->visit (& ri);
6623 : : }
6624 : :
6625 [ + + ]: 645 : if (s.verbose > 1)
6626 [ - + ][ + - ]: 32 : clog << _F("function recursion-analysis: max-nesting %d %s", ri.nesting_max,
[ + - ][ + - ]
6627 [ + - ]: 16 : (ri.recursive ? _(" recursive") : _(" non-recursive"))) << endl;
6628 : 645 : unsigned nesting = ri.nesting_max + 1; /* to account for initial probe->function call */
6629 [ + + ]: 645 : if (ri.recursive) nesting += 10;
6630 : :
6631 : : // This is at the very top of the file.
6632 : : // All "static" defines (not dependend on session state).
6633 [ + - ][ + - ]: 645 : s.op->newline() << "#include \"runtime_defines.h\"";
6634 [ + + ]: 645 : if (s.perf_derived_probes)
6635 [ + - ][ + - ]: 8 : s.op->newline() << "#define _HAVE_PERF_ 1";
6636 [ + - ][ + - ]: 645 : s.op->newline() << "#include \"linux/perf_read.h\"";
6637 : :
6638 : : // Generated macros describing the privilege level required to load/run this module.
6639 [ + - ][ + - ]: 645 : s.op->newline() << "#define STP_PR_STAPUSR 0x" << hex << pr_stapusr << dec;
[ + - ][ + - ]
[ + - ]
6640 [ + - ][ + - ]: 645 : s.op->newline() << "#define STP_PR_STAPSYS 0x" << hex << pr_stapsys << dec;
[ + - ][ + - ]
[ + - ]
6641 [ + - ][ + - ]: 645 : s.op->newline() << "#define STP_PR_STAPDEV 0x" << hex << pr_stapdev << dec;
[ + - ][ + - ]
[ + - ]
6642 [ + - ][ + - ]: 645 : s.op->newline() << "#define STP_PRIVILEGE 0x" << hex << s.privilege << dec;
[ + - ][ + - ]
[ + - ]
6643 : :
6644 : : // Generate a section containing a mask of the privilege levels required to load/run this
6645 : : // module.
6646 [ + - ][ + - ]: 645 : s.op->newline() << "int stp_required_privilege "
6647 [ + - ][ + - ]: 645 : << "__attribute__ ((section (\"" << STAP_PRIVILEGE_SECTION <<"\")))"
[ + - ]
6648 [ + - ]: 645 : << " = STP_PRIVILEGE;";
6649 : :
6650 [ + - ][ + - ]: 645 : s.op->newline() << "#ifndef MAXNESTING";
6651 [ + - ][ + - ]: 645 : s.op->newline() << "#define MAXNESTING " << nesting;
[ + - ]
6652 [ + - ][ + - ]: 645 : s.op->newline() << "#endif";
6653 : :
6654 [ + - ][ + - ]: 645 : s.op->newline() << "#define STP_SKIP_BADVARS " << (s.skip_badvars ? 1 : 0);
[ + + ][ + - ]
6655 : :
6656 [ + + ]: 645 : if (s.bulk_mode)
6657 [ + - ][ + - ]: 8 : s.op->newline() << "#define STP_BULKMODE";
6658 : :
6659 [ + + ]: 645 : if (s.timing)
6660 [ + - ][ + - ]: 8 : s.op->newline() << "#define STP_TIMING";
6661 : :
6662 [ + + ]: 645 : if (s.need_unwind)
6663 [ + - ][ + - ]: 20 : s.op->newline() << "#define STP_NEED_UNWIND_DATA 1";
6664 : :
6665 : : // Emit the total number of probes (not regarding merged probe handlers)
6666 [ + - ][ + - ]: 645 : s.op->newline() << "#define STP_PROBE_COUNT " << s.probes.size();
[ + - ]
6667 : :
6668 [ + - ][ + - ]: 645 : s.op->newline() << "#include \"runtime.h\"";
6669 : :
6670 : : // Emit embeds ahead of time, in case they affect context layout
6671 [ + + ]: 2419 : for (unsigned i=0; i<s.embeds.size(); i++)
6672 : : {
6673 [ + - ][ + - ]: 1774 : s.op->newline() << s.embeds[i]->code << "\n";
[ + - ]
6674 : : }
6675 : :
6676 [ + - ]: 645 : s.up->emit_common_header (); // context etc.
6677 : :
6678 [ + + ]: 645 : if (s.need_unwind)
6679 [ + - ][ + - ]: 20 : s.op->newline() << "#include \"stack.c\"";
6680 : :
6681 [ + + ]: 645 : if (s.globals.size()>0)
6682 : : {
6683 [ + - ][ + - ]: 279 : s.op->newline() << "struct stp_globals {";
6684 [ + - ]: 279 : s.op->indent(1);
6685 [ + + ]: 2013 : for (unsigned i=0; i<s.globals.size(); i++)
6686 : : {
6687 [ + - ]: 1734 : s.up->emit_global (s.globals[i]);
6688 : : }
6689 [ + - ][ + - ]: 279 : s.op->newline(-1) << "};";
6690 : :
6691 : : // We only need to statically initialize globals in kernel modules,
6692 : : // where module parameters may want to override the script's value. In
6693 : : // stapdyn, the globals are actually part of the dynamic shared memory.
6694 [ + - ]: 279 : if (!s.runtime_usermode_p())
6695 : : {
6696 [ + - ]: 279 : s.op->newline();
6697 [ + - ][ + - ]: 279 : s.op->newline() << "static struct stp_globals stp_global = {";
6698 [ + - ]: 279 : s.op->newline(1);
6699 [ + + ]: 2013 : for (unsigned i=0; i<s.globals.size(); i++)
6700 : : {
6701 [ + - ]: 1734 : assert_no_interrupts();
6702 [ + - ]: 1734 : s.up->emit_global_init (s.globals[i]);
6703 : : }
6704 [ + - ][ + - ]: 279 : s.op->newline(-1) << "};";
6705 : : }
6706 : :
6707 [ + - ]: 279 : s.op->assert_0_indent();
6708 : : }
6709 : : else
6710 : : // stp_runtime_session wants to incorporate globals, but it
6711 : : // can be empty
6712 [ + - ][ + - ]: 366 : s.op->newline() << "struct stp_globals {};";
6713 : :
6714 : : // Common (static atomic) state of the stap session.
6715 [ + - ][ + - ]: 645 : s.op->newline() << "#include \"common_session_state.h\"";
6716 : :
6717 [ + - ][ + - ]: 645 : s.op->newline() << "#include \"probe_lock.h\" ";
6718 : :
6719 [ + - ][ + - ]: 645 : s.op->newline() << "#ifdef STAP_NEED_GETTIMEOFDAY";
6720 [ + - ][ + - ]: 645 : s.op->newline() << "#include \"time.c\""; // Don't we all need more?
6721 [ + - ][ + - ]: 645 : s.op->newline() << "#endif";
6722 : :
6723 [ + - ][ + - ]: 668 : for (map<string,stapdfa*>::iterator it = s.dfas.begin(); it != s.dfas.end(); it++)
[ + + ]
6724 : : {
6725 [ + - ]: 23 : assert_no_interrupts();
6726 [ + - ]: 23 : s.op->newline();
6727 : : try
6728 : : {
6729 [ + - ][ + - ]: 23 : it->second->emit_declaration (s.op);
6730 : : }
6731 [ # # ]: : catch (const semantic_error &e)
6732 : : {
6733 [ # # ]: : s.print_error(e); // TODOXXX want to report the token
6734 : : }
6735 : : }
6736 [ + - ]: 645 : s.op->assert_0_indent();
6737 : :
6738 [ + - ][ + - ]: 7022 : for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
[ + + ]
6739 : : {
6740 [ + - ]: 6377 : assert_no_interrupts();
6741 [ + - ]: 6377 : s.op->newline();
6742 [ + - ][ + - ]: 6377 : s.up->emit_functionsig (it->second);
6743 : : }
6744 [ + - ]: 645 : s.op->assert_0_indent();
6745 : :
6746 [ + - ][ + - ]: 7022 : for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
[ + + ]
6747 : : {
6748 [ + - ]: 6377 : assert_no_interrupts();
6749 [ + - ]: 6377 : s.op->newline();
6750 [ + - ][ + - ]: 6377 : s.up->emit_function (it->second);
6751 : : }
6752 [ + - ]: 645 : s.op->assert_0_indent();
6753 : :
6754 : : // Run a varuse_collecting_visitor over probes that need global
6755 : : // variable locks. We'll use this information later in
6756 : : // emit_locks()/emit_unlocks().
6757 [ + + ]: 17506 : for (unsigned i=0; i<s.probes.size(); i++)
6758 : : {
6759 [ + - ]: 16861 : assert_no_interrupts();
6760 [ + - ][ + + ]: 16861 : if (s.probes[i]->needs_global_locks())
6761 [ + - ]: 15396 : s.probes[i]->body->visit (&cup.vcv_needs_global_locks);
6762 : : }
6763 [ + - ]: 645 : s.op->assert_0_indent();
6764 : :
6765 [ + + ]: 17505 : for (unsigned i=0; i<s.probes.size(); i++)
6766 : : {
6767 [ + - ]: 16861 : assert_no_interrupts();
6768 [ + + ]: 16861 : s.up->emit_probe (s.probes[i]);
6769 : : }
6770 [ + - ]: 644 : s.op->assert_0_indent();
6771 : :
6772 : : // Let's find some stats for the embedded pp strings. Maybe they
6773 : : // are small and uniform enough to justify putting char[MAX]'s into
6774 : : // the array instead of relocated char*'s.
6775 : 644 : size_t pp_max = 0, pn_max = 0, location_max = 0, derivation_max = 0;
6776 : 644 : size_t pp_tot = 0, pn_tot = 0, location_tot = 0, derivation_tot = 0;
6777 [ + + ]: 17504 : for (unsigned i=0; i<s.probes.size(); i++)
6778 : : {
6779 : 16860 : derived_probe* p = s.probes[i];
6780 : : #define DOIT(var,expr) do { \
6781 : : size_t var##_size = (expr) + 1; \
6782 : : var##_max = max (var##_max, var##_size); \
6783 : : var##_tot += var##_size; } while (0)
6784 [ + - ][ + - ]: 16860 : DOIT(pp, lex_cast_qstring(*p->sole_location()).size());
[ + - ][ + - ]
6785 [ + - ][ + - ]: 16860 : DOIT(pn, lex_cast_qstring(*p->script_location()).size());
[ + - ][ + - ]
6786 [ + - ][ + - ]: 16860 : DOIT(location, lex_cast_qstring(p->tok->location).size());
[ + - ]
6787 [ + - ][ + - ]: 16860 : DOIT(derivation, lex_cast_qstring(p->derived_locations()).size());
[ + - ][ + - ]
[ + - ]
6788 : : #undef DOIT
6789 : : }
6790 : :
6791 : : // Decide whether it's worthwhile to use char[] or char* by comparing
6792 : : // the amount of average waste (max - avg) to the relocation data size
6793 : : // (3 native long words).
6794 : : #define CALCIT(var) \
6795 : : if (s.verbose > 2) \
6796 : : clog << "adapt " << #var << ":" << var##_max << "max - " << var##_tot << "/" << s.probes.size() << "tot =>"; \
6797 : : if ((var##_max-(var##_tot/s.probes.size())) < (3 * sizeof(void*))) \
6798 : : { \
6799 : : s.op->newline() << "const char " << #var << "[" << var##_max << "];"; \
6800 : : if (s.verbose > 2) \
6801 : : clog << "[]" << endl; \
6802 : : } \
6803 : : else \
6804 : : { \
6805 : : s.op->newline() << "const char * const " << #var << ";"; \
6806 : : if (s.verbose > 2) \
6807 : : clog << "*" << endl; \
6808 : : }
6809 : :
6810 [ + - ][ + - ]: 644 : s.op->newline() << "struct stap_probe {";
6811 [ + - ][ + - ]: 644 : s.op->newline(1) << "size_t index;";
6812 [ + - ][ + - ]: 644 : s.op->newline() << "void (* const ph) (struct context*);";
6813 [ + - ][ + - ]: 644 : s.op->newline() << "#if defined(STP_TIMING) || defined(STP_ALIBI)";
6814 [ + + ][ + - ]: 644 : CALCIT(location);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + + ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ # # ]
[ # # ]
6815 [ + + ][ + - ]: 644 : CALCIT(derivation);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + + ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ # # ]
[ # # ]
6816 [ + - ][ + - ]: 644 : s.op->newline() << "#define STAP_PROBE_INIT_TIMING(L, D) "
6817 [ + - ]: 644 : << ".location=(L), .derivation=(D),";
6818 [ + - ][ + - ]: 644 : s.op->newline() << "#else";
6819 [ + - ][ + - ]: 644 : s.op->newline() << "#define STAP_PROBE_INIT_TIMING(L, D)";
6820 [ + - ][ + - ]: 644 : s.op->newline() << "#endif";
6821 [ + + ][ + - ]: 644 : CALCIT(pp);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + + ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ # # ]
[ # # ]
6822 [ + - ][ + - ]: 644 : s.op->newline() << "#ifdef STP_NEED_PROBE_NAME";
6823 [ + + ][ + - ]: 644 : CALCIT(pn);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + + ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ # # ]
[ # # ]
6824 [ + - ][ + - ]: 644 : s.op->newline() << "#define STAP_PROBE_INIT_NAME(PN) .pn=(PN),";
6825 [ + - ][ + - ]: 644 : s.op->newline() << "#else";
6826 [ + - ][ + - ]: 644 : s.op->newline() << "#define STAP_PROBE_INIT_NAME(PN)";
6827 [ + - ][ + - ]: 644 : s.op->newline() << "#endif";
6828 [ + - ][ + - ]: 644 : s.op->newline() << "#define STAP_PROBE_INIT(I, PH, PP, PN, L, D) "
6829 [ + - ]: 644 : << "{ .index=(I), .ph=(PH), .pp=(PP), "
6830 [ + - ]: 644 : << "STAP_PROBE_INIT_NAME(PN) "
6831 [ + - ]: 644 : << "STAP_PROBE_INIT_TIMING(L, D) "
6832 [ + - ]: 644 : << "}";
6833 [ + - ][ + - ]: 644 : s.op->newline(-1) << "} static const stap_probes[] = {";
6834 [ + - ]: 644 : s.op->indent(1);
6835 [ + + ]: 17504 : for (unsigned i=0; i<s.probes.size(); ++i)
6836 : : {
6837 : 16860 : derived_probe* p = s.probes[i];
6838 : 16860 : p->session_index = i;
6839 [ + - ][ + - ]: 16860 : s.op->newline() << "STAP_PROBE_INIT(" << i << ", &" << p->name << ", "
[ + - ][ + - ]
[ + - ][ + - ]
6840 [ + - ][ + - ]: 33720 : << lex_cast_qstring (*p->sole_location()) << ", "
[ + - ][ + - ]
[ + - ]
6841 [ + - ][ + - ]: 33720 : << lex_cast_qstring (*p->script_location()) << ", "
[ + - ][ + - ]
[ + - ]
6842 [ + - ][ + - ]: 33720 : << lex_cast_qstring (p->tok->location) << ", "
[ + - ][ + - ]
6843 [ + - ][ + - ]: 16860 : << lex_cast_qstring (p->derived_locations()) << "),";
[ + - ][ + - ]
[ + - ][ + - ]
6844 : : }
6845 [ + - ][ + - ]: 644 : s.op->newline(-1) << "};";
6846 [ + - ]: 644 : s.op->assert_0_indent();
6847 : : #undef CALCIT
6848 : :
6849 [ - + ]: 644 : if (s.runtime_usermode_p())
6850 : : {
6851 [ # # ][ # # ]: 0 : s.op->newline() << "static const char* stp_probe_point(size_t index) {";
6852 [ # # ][ # # ]: 0 : s.op->newline(1) << "if (index < ARRAY_SIZE(stap_probes))";
6853 [ # # ][ # # ]: 0 : s.op->newline(1) << "return stap_probes[index].pp;";
6854 [ # # ][ # # ]: 0 : s.op->newline(-1) << "return NULL;";
6855 [ # # ][ # # ]: 0 : s.op->newline(-1) << "}";
6856 [ # # ]: 0 : s.op->assert_0_indent();
6857 : : }
6858 : :
6859 [ + - ]: 644 : s.op->newline();
6860 [ + - ]: 644 : s.up->emit_module_init ();
6861 [ + - ]: 644 : s.op->assert_0_indent();
6862 [ + - ]: 644 : s.op->newline();
6863 [ + - ]: 644 : s.up->emit_module_refresh ();
6864 [ + - ]: 644 : s.op->assert_0_indent();
6865 [ + - ]: 644 : s.op->newline();
6866 [ + - ]: 644 : s.up->emit_module_exit ();
6867 [ + - ]: 644 : s.op->assert_0_indent();
6868 [ + - ]: 644 : s.op->newline();
6869 : :
6870 [ + - ]: 644 : emit_symbol_data (s);
6871 : :
6872 [ + - ][ + - ]: 644 : s.op->newline() << "MODULE_DESCRIPTION(\"systemtap-generated probe\");";
6873 [ + - ][ + - ]: 644 : s.op->newline() << "MODULE_LICENSE(\"GPL\");";
6874 : :
6875 [ + + ]: 1277 : for (unsigned i = 0; i < s.modinfos.size(); i++)
6876 : : {
6877 : 633 : const string& mi = s.modinfos[i];
6878 [ + - ]: 633 : size_t loc = mi.find('=');
6879 [ + - ]: 633 : string tag = mi.substr (0, loc);
6880 [ + - ]: 633 : string value = mi.substr (loc+1);
6881 [ + - ][ + - ]: 633 : s.op->newline() << "MODULE_INFO(" << tag << "," << lex_cast_qstring(value) << ");";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
6882 [ + - ][ + - ]: 633 : }
6883 : :
6884 [ + - ]: 644 : s.op->assert_0_indent();
6885 : :
6886 : : // PR10298: attempt to avoid collisions with symbols
6887 [ + + ]: 2378 : for (unsigned i=0; i<s.globals.size(); i++)
6888 : : {
6889 [ + - ]: 1734 : s.op->newline();
6890 [ + - ]: 1734 : s.up->emit_global_param (s.globals[i]);
6891 : : }
6892 [ + - ][ + - ]: 645 : s.op->assert_0_indent();
6893 : : }
6894 [ - + ]: 2 : catch (const semantic_error& e)
6895 : : {
6896 [ - + ]: 1 : s.print_error (e);
6897 : : }
6898 : :
6899 [ + - ]: 645 : s.op->line() << "\n";
6900 : :
6901 [ + - ][ + - ]: 645 : delete s.op;
6902 : 645 : s.op = 0;
6903 : 645 : s.up = 0;
6904 : :
6905 [ + - ][ + - ]: 645 : return rc + s.num_errors();
6906 [ + - ][ + - ]: 7242 : }
6907 : :
6908 : : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
|