LCOV - code coverage report
Current view: top level - mnt/wasteland/wcohen/systemtap_write/systemtap - translate.cxx (source / functions) Hit Total Coverage
Test: stap.info Lines: 3026 3248 93.2 %
Date: 2013-03-08 Functions: 220 238 92.4 %
Branches: 5109 10074 50.7 %

           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 : */

Generated by: LCOV version 1.9