// -*- C++ -*- // Copyright (C) 2005-2010 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef ELABORATE_H #define ELABORATE_H #include "staptree.h" #include "parse.h" #include #include //#include #include #include #include #include extern "C" { #include } // ------------------------------------------------------------------------ struct derived_probe; struct match_node; struct symresolution_info: public traversing_visitor { protected: systemtap_session& session; public: functiondecl* current_function; derived_probe* current_probe; symresolution_info (systemtap_session& s); vardecl* find_var (const std::string& name, int arity, const token *tok); functiondecl* find_function (const std::string& name, unsigned arity); void visit_block (block *s); void visit_symbol (symbol* e); void visit_foreach_loop (foreach_loop* e); void visit_arrayindex (arrayindex* e); void visit_functioncall (functioncall* e); void visit_delete_statement (delete_statement* s); }; struct typeresolution_info: public visitor { typeresolution_info (systemtap_session& s); systemtap_session& session; unsigned num_newly_resolved; unsigned num_still_unresolved; bool assert_resolvability; functiondecl* current_function; derived_probe* current_probe; std::vector resolved_toks; // account for type mis- std::vector printed_toks; // matches (BZ 9719) void check_arg_type (exp_type wanted, expression* arg); void mismatch (const token* tok, exp_type t1, exp_type t2); void unresolved (const token* tok); void resolved (const token* tok, exp_type t); void invalid (const token* tok, exp_type t); exp_type t; // implicit parameter for nested visit call; may clobber void visit_block (block* s); void visit_try_block (try_block* s); void visit_embeddedcode (embeddedcode* s); void visit_null_statement (null_statement* s); void visit_expr_statement (expr_statement* s); void visit_if_statement (if_statement* s); void visit_for_loop (for_loop* s); void visit_foreach_loop (foreach_loop* s); void visit_return_statement (return_statement* s); void visit_delete_statement (delete_statement* s); void visit_next_statement (next_statement* s); void visit_break_statement (break_statement* s); void visit_continue_statement (continue_statement* s); void visit_literal_string (literal_string* e); void visit_literal_number (literal_number* e); void visit_binary_expression (binary_expression* e); void visit_unary_expression (unary_expression* e); void visit_pre_crement (pre_crement* e); void visit_post_crement (post_crement* e); void visit_logical_or_expr (logical_or_expr* e); void visit_logical_and_expr (logical_and_expr* e); void visit_array_in (array_in* e); void visit_comparison (comparison* e); void visit_concatenation (concatenation* e); void visit_ternary_expression (ternary_expression* e); void visit_assignment (assignment* e); void visit_symbol (symbol* e); void visit_target_symbol (target_symbol* e); void visit_arrayindex (arrayindex* e); void visit_functioncall (functioncall* e); void visit_print_format (print_format* e); void visit_stat_op (stat_op* e); void visit_hist_op (hist_op* e); void visit_cast_op (cast_op* e); void visit_defined_op (defined_op* e); }; // ------------------------------------------------------------------------ // A derived_probe is a probe that has been elaborated by // binding to a matching provider. The locations std::vector // may be smaller or larger than the base probe, since a // provider may transform it. class translator_output; class derived_probe_group; struct derived_probe: public probe { derived_probe (probe* b); derived_probe (probe* b, probe_point* l); probe* base; // the original parsed probe virtual probe* basest () { return base->basest(); } // XXX: might be helpful for listing and stepwise expansion, but aliases/wildcards don't show up right // virtual probe* almost_basest () { probe* bb = base->basest(); return (bb == base) ? this : bb; } virtual ~derived_probe () {} virtual void join_group (systemtap_session& s) = 0; virtual probe_point* sole_location () const; virtual void printsig (std::ostream &o) const; // return arguments of probe if there virtual void getargs (std::list &arg_set) const {} void printsig_nested (std::ostream &o) const; virtual void collect_derivation_chain (std::vector &probes_list); virtual void print_dupe_stamp(std::ostream&) {} // To aid duplication elimination, print a stamp which uniquely identifies // the code that will be added to the probe body. (Doesn't need to be the // actual code...) virtual void emit_probe_context_vars (translator_output*) {} // From within unparser::emit_common_header, add any extra variables // to this probe's context locals. virtual void initialize_probe_context_vars (translator_output*) {} // From within unparser::emit_probe, initialized any extra variables // in this probe's context locals. virtual void emit_probe_local_init (translator_output*) {} // From within unparser::emit_probe, emit any extra processing block // for this probe. virtual void emit_unprivileged_assertion (translator_output*); // From within unparser::emit_probe, emit any unprivileged mode // checking for this probe. public: static void emit_common_header (translator_output* o); // from c_unparser::emit_common_header // XXX: probably can move this stuff to a probe_group::emit_module_decls static void emit_process_owner_assertion (translator_output*); // From within unparser::emit_probe, emit a check that the current // process belongs to the user. static void print_dupe_stamp_unprivileged(std::ostream& o); static void print_dupe_stamp_unprivileged_process_owner(std::ostream& o); virtual bool needs_global_locks () { return true; } // by default, probes need locks around global variables // Location of semaphores to activate sdt probes Dwarf_Addr sdt_semaphore_addr; }; // ------------------------------------------------------------------------ struct unparser; // Various derived classes derived_probe_group manage the // registration/invocation/unregistration of sibling probes. struct derived_probe_group { virtual ~derived_probe_group () {} virtual void emit_module_decls (systemtap_session& s) = 0; // The _decls-generated code may assume that declarations such as // the context, embedded-C code, function and probe handler bodies // are all already generated. That is, _decls is called near the // end of the code generation process. It should minimize the // number of separate variables (and to a lesser extent, their // size). virtual void emit_module_init (systemtap_session& s) = 0; // The _init-generated code may assume that it is called only once. // If that code fails at run time, it must set rc=1 and roll back // any partial initializations, for its _exit friend will NOT be // invoked. The generated code may use pre-declared "int i, j;". virtual void emit_module_exit (systemtap_session& s) = 0; // The _exit-generated code may assume that it is executed exactly // zero times (if the _init-generated code failed) or once. (_exit // itself may be called a few times, to generate the code in a few // different places in the probe module.) // The generated code may use pre-declared "int i, j;". }; // ------------------------------------------------------------------------ typedef std::map literal_map_t; struct derived_probe_builder { virtual void build(systemtap_session & sess, probe* base, probe_point* location, literal_map_t const & parameters, std::vector & finished_results) = 0; virtual ~derived_probe_builder() {} virtual void build_no_more (systemtap_session &) {} static bool has_null_param (literal_map_t const & parameters, const std::string& key); static bool get_param (literal_map_t const & parameters, const std::string& key, std::string& value); static bool get_param (literal_map_t const & parameters, const std::string& key, int64_t& value); }; struct match_key { std::string name; bool have_parameter; exp_type parameter_type; match_key(std::string const & n); match_key(probe_point::component const & c); match_key & with_number(); match_key & with_string(); std::string str() const; bool operator<(match_key const & other) const; bool globmatch(match_key const & other) const; }; class match_node { typedef std::map sub_map_t; typedef std::map::iterator sub_map_iterator_t; sub_map_t sub; std::vector ends; public: match_node(); void find_and_build (systemtap_session& s, probe* p, probe_point *loc, unsigned pos, std::vector& results); void build_no_more (systemtap_session &s); match_node* bind(match_key const & k); match_node* bind(std::string const & k); match_node* bind_str(std::string const & k); match_node* bind_num(std::string const & k); match_node* bind_unprivileged(bool b = true); void bind(derived_probe_builder* e); private: bool unprivileged_ok; }; // ------------------------------------------------------------------------ /* struct systemtap_session moved to session.h */ int semantic_pass (systemtap_session& s); void derive_probes (systemtap_session& s, probe *p, std::vector& dps, bool optional = false); // A helper we use here and in translate, for pulling symbols out of lvalue // expressions. symbol * get_symbol_within_expression (expression *e); struct unparser; #endif // ELABORATE_H /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */