diff options
-rw-r--r-- | buildrun.cxx | 10 | ||||
-rw-r--r-- | dwflpp.cxx | 130 | ||||
-rw-r--r-- | dwflpp.h | 43 | ||||
-rw-r--r-- | elaborate.cxx | 6 | ||||
-rw-r--r-- | hash.cxx | 1 | ||||
-rw-r--r-- | main.cxx | 4 | ||||
-rw-r--r-- | parse.cxx | 5 | ||||
-rw-r--r-- | staptree.cxx | 2 | ||||
-rw-r--r-- | tapset-mark.cxx | 12 | ||||
-rw-r--r-- | tapset-perfmon.cxx | 6 | ||||
-rw-r--r-- | tapset-procfs.cxx | 2 | ||||
-rw-r--r-- | tapset-timers.cxx | 4 | ||||
-rw-r--r-- | tapset-utrace.cxx | 6 | ||||
-rw-r--r-- | tapsets.cxx | 65 | ||||
-rw-r--r-- | translate.cxx | 36 | ||||
-rw-r--r-- | unordered.h | 56 | ||||
-rw-r--r-- | util.h | 68 |
17 files changed, 271 insertions, 185 deletions
diff --git a/buildrun.cxx b/buildrun.cxx index a40dab15..6bef4095 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -363,10 +363,10 @@ run_pass (systemtap_session& s) staprun_cmd += "-c " + cmdstr_quoted(s.cmd) + " "; if (s.target_pid) - staprun_cmd += "-t " + stringify(s.target_pid) + " "; + staprun_cmd += "-t " + lex_cast(s.target_pid) + " "; if (s.buffer_size) - staprun_cmd += "-b " + stringify(s.buffer_size) + " "; + staprun_cmd += "-b " + lex_cast(s.buffer_size) + " "; if (s.need_uprobes) staprun_cmd += "-u "; @@ -390,7 +390,7 @@ make_tracequery(systemtap_session& s, string& name, const vector<string>& extra_headers) { static unsigned tick = 0; - string basename("tracequery_kmod_" + lex_cast<string>(++tick)); + string basename("tracequery_kmod_" + lex_cast(++tick)); // create a subdirectory for the module string dir(s.tmpdir + "/" + basename); @@ -461,7 +461,7 @@ static int make_typequery_kmod(systemtap_session& s, const string& header, string& name) { static unsigned tick = 0; - string basename("typequery_kmod_" + lex_cast<string>(++tick)); + string basename("typequery_kmod_" + lex_cast(++tick)); // create a subdirectory for the module string dir(s.tmpdir + "/" + basename); @@ -519,7 +519,7 @@ make_typequery_umod(systemtap_session& s, const string& header, string& name) { static unsigned tick = 0; - name = s.tmpdir + "/typequery_umod_" + lex_cast<string>(++tick) + ".so"; + name = s.tmpdir + "/typequery_umod_" + lex_cast(++tick) + ".so"; // make the module // @@ -93,6 +93,23 @@ dwflpp::dwflpp(systemtap_session & session, const vector<string>& names): dwflpp::~dwflpp() { free(cached_scopes); + + for (module_cu_cache_t::iterator it = module_cu_cache.begin(); + it != module_cu_cache.end(); ++it) + delete it->second; + + for (mod_cu_function_cache_t::iterator it = cu_function_cache.begin(); + it != cu_function_cache.end(); ++it) + delete it->second; + + for (cu_inl_function_cache_t::iterator it = cu_inl_function_cache.begin(); + it != cu_inl_function_cache.end(); ++it) + delete it->second; + + for (mod_cu_type_cache_t::iterator it = global_alias_cache.begin(); + it != global_alias_cache.end(); ++it) + delete it->second; + if (dwfl) dwfl_end(dwfl); } @@ -577,7 +594,7 @@ dwflpp::iterate_over_inline_instances (int (* callback)(Dwarf_Die * die, void * int dwflpp::global_alias_caching_callback(Dwarf_Die *die, void *arg) { - cu_function_cache_t *cache = static_cast<cu_function_cache_t*>(arg); + cu_type_cache_t *cache = static_cast<cu_type_cache_t*>(arg); const char *name = dwarf_diename(die); if (!name) @@ -599,10 +616,10 @@ dwflpp::declaration_resolve(const char *name) if (!name) return NULL; - cu_function_cache_t *v = global_alias_cache[cu->addr]; + cu_type_cache_t *v = global_alias_cache[cu->addr]; if (v == 0) // need to build the cache, just once per encountered module/cu { - v = new cu_function_cache_t; + v = new cu_type_cache_t; global_alias_cache[cu->addr] = v; iterate_over_globals(global_alias_caching_callback, v); if (sess.verbose > 4) @@ -633,8 +650,7 @@ dwflpp::cu_function_caching_callback (Dwarf_Die* func, void *arg) if (!name) return DWARF_CB_OK; - string function_name = name; - (*v)[function_name] = * func; + v->insert(make_pair(string(name), *func)); return DWARF_CB_OK; } @@ -660,14 +676,19 @@ dwflpp::iterate_over_functions (int (* callback)(Dwarf_Die * func, base_query * mod_info->update_symtab(v); } - cu_function_cache_t::iterator it = v->find(function); - if (it != v->end()) + cu_function_cache_t::iterator it; + cu_function_cache_range_t range = v->equal_range(function); + if (range.first != range.second) { - Dwarf_Die& die = it->second; - if (sess.verbose > 4) - clog << "function cache " << module_name << ":" << cu_name() - << " hit " << function << endl; - return (*callback)(& die, q); + for (it = range.first; it != range.second; ++it) + { + Dwarf_Die& die = it->second; + if (sess.verbose > 4) + clog << "function cache " << module_name << ":" << cu_name() + << " hit " << function << endl; + rc = (*callback)(& die, q); + if (rc != DWARF_CB_OK) break; + } } else if (name_has_wildcard (function)) { @@ -1243,7 +1264,7 @@ dwflpp::die_entrypc (Dwarf_Die * die, Dwarf_Addr * addr) while ((offset = dwarf_ranges (die, offset, &base, &begin, &end)) > 0) extra ++; if (extra) - lookup_method += ", ignored " + lex_cast<string>(extra) + " more"; + lookup_method += ", ignored " + lex_cast(extra) + " more"; } } @@ -1437,7 +1458,7 @@ dwflpp::find_variable_and_frame_base (Dwarf_Die *scope_die, if (nscopes <= 0) { throw semantic_error ("unable to find any scopes containing " - + lex_cast_hex<string>(pc) + + lex_cast_hex(pc) + ((scope_die == NULL) ? "" : (string (" in ") + (dwarf_diename(scope_die) ?: "<unknown>") @@ -1456,7 +1477,7 @@ dwflpp::find_variable_and_frame_base (Dwarf_Die *scope_die, stringstream alternatives; print_locals (scopes, alternatives); throw semantic_error ("unable to find local '" + local + "'" - + " near pc " + lex_cast_hex<string>(pc) + + " near pc " + lex_cast_hex(pc) + ((scope_die == NULL) ? "" : (string (" in ") + (dwarf_diename(scope_die) ?: "<unknown>") @@ -1727,7 +1748,7 @@ dwflpp::translate_components(struct obstack *pool, #if 0 // Emit a marker to note which field is being access-attempted, to give // better error messages if deref() fails. - string piece = string(...target_symbol token...) + string ("#") + stringify(components[i].second); + string piece = string(...target_symbol token...) + string ("#") + lex_cast(components[i].second); obstack_printf (pool, "c->last_stmt = %s;", lex_cast_qstring(piece).c_str()); #endif @@ -1749,7 +1770,7 @@ dwflpp::translate_components(struct obstack *pool, case DW_TAG_pointer_type: /* A pointer with no type is a void* -- can't dereference it. */ if (!dwarf_hasattr_integrate (die, DW_AT_type)) - throw semantic_error ("invalid access '" + lex_cast<string>(c) + throw semantic_error ("invalid access '" + lex_cast(c) + "' vs. " + dwarf_type_name(die), c.tok); @@ -1768,14 +1789,14 @@ dwflpp::translate_components(struct obstack *pool, } else if (c.type == target_symbol::comp_expression_array_index) { - string index = "THIS->index" + lex_cast<string>(i); + string index = "THIS->index" + lex_cast(i); c_translate_array (pool, 1, 0 /* PR9768 */, die, tail, index.c_str(), 0); ++i; } else throw semantic_error ("invalid access '" - + lex_cast<string>(c) + + lex_cast(c) + "' for array type", c.tok); break; @@ -1785,7 +1806,7 @@ dwflpp::translate_components(struct obstack *pool, case DW_TAG_class_type: if (c.type != target_symbol::comp_struct_member) throw semantic_error ("invalid access '" - + lex_cast<string>(c) + + lex_cast(c) + "' for " + dwarf_type_name(die), c.tok); @@ -1811,7 +1832,7 @@ dwflpp::translate_components(struct obstack *pool, const char *file = dwarf_decl_file(&parentdie); if (file && dwarf_decl_line(&parentdie, &line) == 0) source = " (" + string(file) + ":" - + lex_cast<string>(line) + ")"; + + lex_cast(line) + ")"; } string alternatives; @@ -1836,7 +1857,7 @@ dwflpp::translate_components(struct obstack *pool, case DW_TAG_enumeration_type: case DW_TAG_base_type: throw semantic_error ("invalid access '" - + lex_cast<string>(c) + + lex_cast(c) + "' vs. " + dwarf_type_name(die), c.tok); break; @@ -1848,7 +1869,7 @@ dwflpp::translate_components(struct obstack *pool, default: throw semantic_error (dwarf_type_name(die) + ": unexpected type tag " - + lex_cast<string>(dwarf_tag (die)), + + lex_cast(dwarf_tag (die)), c.tok); break; } @@ -1936,7 +1957,7 @@ dwflpp::translate_final_fetch_or_store (struct obstack *pool, { default: throw semantic_error ("unsupported type tag " - + lex_cast<string>(typetag) + + lex_cast(typetag) + " for " + dwarf_type_name(typedie), e->tok); break; @@ -1959,7 +1980,7 @@ dwflpp::translate_final_fetch_or_store (struct obstack *pool, if (encoding < 0) { // clog << "bad type1 " << encoding << " diestr" << endl; - throw semantic_error ("unsupported type (mystery encoding " + lex_cast<string>(encoding) + ")" + + throw semantic_error ("unsupported type (mystery encoding " + lex_cast(encoding) + ")" + " for " + dwarf_type_name(typedie), e->tok); } @@ -1968,7 +1989,7 @@ dwflpp::translate_final_fetch_or_store (struct obstack *pool, /* XXX || many others? */) { // clog << "bad type " << encoding << " diestr" << endl; - throw semantic_error ("unsupported type (encoding " + lex_cast<string>(encoding) + ")" + + throw semantic_error ("unsupported type (encoding " + lex_cast(encoding) + ")" + " for " + dwarf_type_name(typedie), e->tok); } } @@ -2097,7 +2118,7 @@ dwflpp::literal_stmt_for_local (Dwarf_Die *scope_die, throw semantic_error("failed to retrieve location " "attribute for local '" + local + "' (dieoffset: " - + lex_cast_hex<string>(dwarf_dieoffset (&vardie)) + + lex_cast_hex(dwarf_dieoffset (&vardie)) + ")", e->tok); } @@ -2281,21 +2302,14 @@ dwflpp::blacklisted_p(const string& funcname, const string& filename, int, const string& module, - const string& section, Dwarf_Addr addr, bool has_return) { if (!blacklist_enabled) return false; // no blacklist for userspace - if (section.substr(0, 6) == string(".init.") || - section.substr(0, 6) == string(".exit.") || - section.substr(0, 9) == string(".devinit.") || - section.substr(0, 9) == string(".devexit.") || - section.substr(0, 9) == string(".cpuinit.") || - section.substr(0, 9) == string(".cpuexit.") || - section.substr(0, 9) == string(".meminit.") || - section.substr(0, 9) == string(".memexit.")) + string section = get_blacklist_section(addr); + if (!regexec (&blacklist_section, section.c_str(), 0, NULL, 0)) { // NB: module .exit. routines could be probed in theory: // if the exit handler in "struct module" is diverted, @@ -2351,16 +2365,26 @@ dwflpp::build_blacklist() string blfn = "^("; string blfn_ret = "^("; string blfile = "^("; - - blfile += "kernel/kprobes.c"; // first alternative, no "|" - blfile += "|arch/.*/kernel/kprobes.c"; + string blsection = "^("; + + blsection += "\\.init\\."; // first alternative, no "|" + blsection += "|\\.exit\\."; + blsection += "|\\.devinit\\."; + blsection += "|\\.devexit\\."; + blsection += "|\\.cpuinit\\."; + blsection += "|\\.cpuexit\\."; + blsection += "|\\.meminit\\."; + blsection += "|\\.memexit\\."; + + blfile += "kernel/kprobes\\.c"; // first alternative, no "|" + blfile += "|arch/.*/kernel/kprobes\\.c"; // Older kernels need ... - blfile += "|include/asm/io.h"; - blfile += "|include/asm/bitops.h"; + blfile += "|include/asm/io\\.h"; + blfile += "|include/asm/bitops\\.h"; // While newer ones need ... - blfile += "|arch/.*/include/asm/io.h"; - blfile += "|arch/.*/include/asm/bitops.h"; - blfile += "|drivers/ide/ide-iops.c"; + blfile += "|arch/.*/include/asm/io\\.h"; + blfile += "|arch/.*/include/asm/bitops\\.h"; + blfile += "|drivers/ide/ide-iops\\.c"; // XXX: it would be nice if these blacklisted functions were pulled // in dynamically, instead of being statically defined here. @@ -2451,6 +2475,7 @@ dwflpp::build_blacklist() blfn += ")$"; blfn_ret += ")$"; blfile += ")$"; + blsection += ")"; // NB: no $, sections match just the beginning if (sess.verbose > 2) { @@ -2458,6 +2483,7 @@ dwflpp::build_blacklist() clog << "blfn: " << blfn << endl; clog << "blfn_ret: " << blfn_ret << endl; clog << "blfile: " << blfile << endl; + clog << "blsection: " << blsection << endl; } int rc = regcomp (& blacklist_func, blfn.c_str(), REG_NOSUB|REG_EXTENDED); @@ -2466,6 +2492,8 @@ dwflpp::build_blacklist() if (rc) throw semantic_error ("blacklist_func_ret regcomp failed"); rc = regcomp (& blacklist_file, blfile.c_str(), REG_NOSUB|REG_EXTENDED); if (rc) throw semantic_error ("blacklist_file regcomp failed"); + rc = regcomp (& blacklist_section, blsection.c_str(), REG_NOSUB|REG_EXTENDED); + if (rc) throw semantic_error ("blacklist_section regcomp failed"); blacklist_enabled = true; } @@ -2512,9 +2540,7 @@ dwflpp::get_blacklist_section(Dwarf_Addr addr) Dwarf_Addr -dwflpp::relocate_address(Dwarf_Addr dw_addr, - string& reloc_section, - string& blacklist_section) +dwflpp::relocate_address(Dwarf_Addr dw_addr, string& reloc_section) { // PR10273 // libdw address, so adjust for bias gotten from dwfl_module_getdwarf @@ -2523,7 +2549,6 @@ dwflpp::relocate_address(Dwarf_Addr dw_addr, { assert(module_name == TOK_KERNEL); reloc_section = ""; - blacklist_section = ""; } else if (dwfl_module_relocations (module) > 0) { @@ -2533,19 +2558,12 @@ dwflpp::relocate_address(Dwarf_Addr dw_addr, const char* r_s = dwfl_module_relocation_info (module, idx, NULL); if (r_s) reloc_section = r_s; - blacklist_section = reloc_section; if (reloc_section == "" && dwfl_module_relocations (module) == 1) - { - blacklist_section = get_blacklist_section(dw_addr); reloc_section = ".dynamic"; - } } else - { - blacklist_section = get_blacklist_section(dw_addr); - reloc_section = ".absolute"; - } + reloc_section = ".absolute"; return reloc_addr; } @@ -15,6 +15,7 @@ #include "dwarf_wrappers.h" #include "elaborate.h" #include "session.h" +#include "unordered.h" #include <cstring> #include <iostream> @@ -43,33 +44,26 @@ struct dwarf_query; enum line_t { ABSOLUTE, RELATIVE, RANGE, WILDCARD }; enum info_status { info_unknown, info_present, info_absent }; -#ifdef HAVE_TR1_UNORDERED_MAP -#include <tr1/unordered_map> -template<class K, class V> struct stap_map { - typedef std::tr1::unordered_map<K, V> type; -}; -#else -#include <ext/hash_map> -template<class K, class V> struct stap_map { - typedef __gnu_cxx::hash_map<K, V, stap_map> type; - size_t operator() (std::string const& s) const - { __gnu_cxx::hash<const char*> h; return h(s.c_str()); } - size_t operator() (void* const& p) const - { __gnu_cxx::hash<long> h; return h(reinterpret_cast<long>(p)); } -}; -#endif - // module -> cu die[] -typedef stap_map<Dwarf*, std::vector<Dwarf_Die>*>::type module_cu_cache_t; +typedef unordered_map<Dwarf*, std::vector<Dwarf_Die>*> module_cu_cache_t; + +// typename -> die +typedef unordered_map<std::string, Dwarf_Die> cu_type_cache_t; + +// cu die -> (typename -> die) +typedef unordered_map<void*, cu_type_cache_t*> mod_cu_type_cache_t; // function -> die -typedef stap_map<std::string, Dwarf_Die>::type cu_function_cache_t; +typedef unordered_multimap<std::string, Dwarf_Die> cu_function_cache_t; +typedef std::pair<cu_function_cache_t::iterator, + cu_function_cache_t::iterator> + cu_function_cache_range_t; // cu die -> (function -> die) -typedef stap_map<void*, cu_function_cache_t*>::type mod_cu_function_cache_t; +typedef unordered_map<void*, cu_function_cache_t*> mod_cu_function_cache_t; // inline function die -> instance die[] -typedef stap_map<void*, std::vector<Dwarf_Die>*>::type cu_inl_function_cache_t; +typedef unordered_map<void*, std::vector<Dwarf_Die>*> cu_inl_function_cache_t; typedef std::vector<func_info> func_info_map_t; typedef std::vector<inline_instance_info> inline_instance_map_t; @@ -145,6 +139,7 @@ struct inline_instance_info { std::memset(&die, 0, sizeof(die)); } + bool operator<(const inline_instance_info& other) const; std::string name; char const * decl_file; int decl_line; @@ -273,13 +268,10 @@ struct dwflpp const std::string& filename, int line, const std::string& module, - const std::string& section, Dwarf_Addr addr, bool has_return); - Dwarf_Addr relocate_address(Dwarf_Addr addr, - std::string& reloc_section, - std::string& blacklist_section); + Dwarf_Addr relocate_address(Dwarf_Addr addr, std::string& reloc_section); Dwarf_Addr literal_addr_to_sym_addr(Dwarf_Addr lit_addr); @@ -308,7 +300,7 @@ private: * cache is indexed by name. If other declaration lookups were * added to it, it would have to be indexed by name and tag */ - mod_cu_function_cache_t global_alias_cache; + mod_cu_type_cache_t global_alias_cache; static int global_alias_caching_callback(Dwarf_Die *die, void *arg); int iterate_over_globals (int (* callback)(Dwarf_Die *, void *), void * data); @@ -377,6 +369,7 @@ private: regex_t blacklist_func; // function/statement probes regex_t blacklist_func_ret; // only for .return probes regex_t blacklist_file; // file name + regex_t blacklist_section; // init/exit sections bool blacklist_enabled; void build_blacklist(); std::string get_blacklist_section(Dwarf_Addr addr); diff --git a/elaborate.cxx b/elaborate.cxx index 17f335d0..c1a2e898 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -331,7 +331,7 @@ match_node::find_and_build (systemtap_session& s, alternatives += string(" ") + i->first.str(); throw semantic_error (string("probe point truncated at position ") + - lex_cast<string> (pos) + + lex_cast (pos) + " (follow:" + alternatives + ")", loc->tok); } @@ -416,7 +416,7 @@ match_node::find_and_build (systemtap_session& s, alternatives += string(" ") + i->first.str(); throw semantic_error(string("probe point mismatch at position ") + - lex_cast<string> (pos) + + lex_cast (pos) + " (alternatives:" + alternatives + ")" + " didn't find any wildcard matches", loc->tok); @@ -433,7 +433,7 @@ match_node::find_and_build (systemtap_session& s, alternatives += string(" ") + i->first.str(); throw semantic_error (string("probe point mismatch at position ") + - lex_cast<string> (pos) + + lex_cast (pos) + " (alternatives:" + alternatives + ")", loc->tok); } @@ -174,6 +174,7 @@ find_script_hash (systemtap_session& s, const string& script, const hash &base) h.add(s.ignore_dwarf); // --ignore-dwarf h.add(s.consult_symtab); // --kelf, --kmap h.add(s.skip_badvars); // --skip-badvars + h.add(s.unprivileged); // --unprivileged if (!s.kernel_symtab_path.empty()) // --kmap { h.add(s.kernel_symtab_path); @@ -486,8 +486,8 @@ main (int argc, char * const argv []) s.buffer_size = 0; s.last_pass = 5; - s.module_name = "stap_" + stringify(getpid()); - s.stapconf_name = "stapconf_" + stringify(getpid()) + ".h"; + s.module_name = "stap_" + lex_cast(getpid()); + s.stapconf_name = "stapconf_" + lex_cast(getpid()) + ".h"; s.output_file = ""; // -o FILE s.keep_tmpdir = false; s.cmd = ""; @@ -754,9 +754,8 @@ lexer::scan (bool wildcard) idx <= session.args.size()); // prevent overflow if (idx == 0 || idx-1 >= session.args.size()) - throw parse_error ("command line argument index " + lex_cast<string>(idx) - + " out of range [1-" + lex_cast<string>(session.args.size()) + "]", n); - + throw parse_error ("command line argument index " + lex_cast(idx) + + " out of range [1-" + lex_cast(session.args.size()) + "]", n); string arg = session.args[idx-1]; if (c == '$') input_put (arg); else input_put (lex_cast_qstring (arg)); diff --git a/staptree.cxx b/staptree.cxx index b4975017..090f0bd3 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -101,7 +101,7 @@ probe::probe (): body (0), tok (0) { static unsigned last_probeidx = 0; - this->name = string ("probe_") + lex_cast<string>(last_probeidx ++); + this->name = string ("probe_") + lex_cast(last_probeidx ++); } diff --git a/tapset-mark.cxx b/tapset-mark.cxx index 6b4f47c5..b70098e3 100644 --- a/tapset-mark.cxx +++ b/tapset-mark.cxx @@ -108,7 +108,7 @@ mark_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) // Remember that we've seen a target variable. target_symbol_seen = true; - e->probe_context_var = "__mark_arg" + lex_cast<string>(argnum); + e->probe_context_var = "__mark_arg" + lex_cast(argnum); e->type = mark_args[argnum-1]->stp_type; provide (e); } @@ -156,10 +156,10 @@ mark_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) { if (i > 0) pf->raw_components += " "; - pf->raw_components += "$arg" + lex_cast<string>(i+1); + pf->raw_components += "$arg" + lex_cast(i+1); target_symbol *tsym = new target_symbol; tsym->tok = e->tok; - tsym->base_name = "$arg" + lex_cast<string>(i+1); + tsym->base_name = "$arg" + lex_cast(i+1); tsym->saved_conversion_error = 0; expression *texp = require (tsym); //same treatment as tracepoint @@ -414,7 +414,7 @@ mark_derived_probe::emit_probe_context_vars (translator_output* o) for (unsigned i = 0; i < mark_args.size(); i++) { - string localname = "__mark_arg" + lex_cast<string>(i+1); + string localname = "__mark_arg" + lex_cast(i+1); switch (mark_args[i]->stp_type) { case pe_long: @@ -441,7 +441,7 @@ mark_derived_probe::initialize_probe_context_vars (translator_output* o) bool deref_fault_needed = false; for (unsigned i = 0; i < mark_args.size(); i++) { - string localname = "l->__mark_arg" + lex_cast<string>(i+1); + string localname = "l->__mark_arg" + lex_cast(i+1); switch (mark_args[i]->stp_type) { case pe_long: @@ -475,7 +475,7 @@ mark_derived_probe::printargs(std::ostream &o) const { for (unsigned i = 0; i < mark_args.size(); i++) { - string localname = "$arg" + lex_cast<string>(i+1); + string localname = "$arg" + lex_cast(i+1); switch (mark_args[i]->stp_type) { case pe_long: diff --git a/tapset-perfmon.cxx b/tapset-perfmon.cxx index 827e88ca..56abb997 100644 --- a/tapset-perfmon.cxx +++ b/tapset-perfmon.cxx @@ -59,7 +59,7 @@ perfmon_var_expanding_visitor::visit_target_symbol (target_symbol *e) string fname = string("_perfmon_tvar_get") + "_" + e->base_name.substr(1) - + "_" + lex_cast<string>(counter_number); + + "_" + lex_cast(counter_number); if (e->base_name != "$counter") throw semantic_error ("target variables not available to perfmon probes"); @@ -70,7 +70,7 @@ perfmon_var_expanding_visitor::visit_target_symbol (target_symbol *e) e->assert_no_components("perfmon"); ec->code = "THIS->__retvalue = _pfm_pmd_x[" + - lex_cast<string>(counter_number) + "].reg_num;"; + lex_cast(counter_number) + "].reg_num;"; ec->code += "/* pure */"; fdecl->name = fname; fdecl->body = ec; @@ -390,7 +390,7 @@ perfmon_derived_probe_group::emit_module_init (translator_output* o) /* output the needed bits for pmc here */ for (unsigned i=0; i < outp.pfp_pmc_count; i++) { o->newline() << "{.reg_num=" << pc[i].reg_num << ", " - << ".reg_value=" << lex_cast_hex<string>(pc[i].reg_value) + << ".reg_value=" << lex_cast_hex(pc[i].reg_value) << "},"; } diff --git a/tapset-procfs.cxx b/tapset-procfs.cxx index 527b4486..fd8ad62a 100644 --- a/tapset-procfs.cxx +++ b/tapset-procfs.cxx @@ -379,7 +379,7 @@ procfs_var_expanding_visitor::visit_target_symbol (target_symbol* e) ec->tok = e->tok; string fname = (string(lvalue ? "_procfs_value_set" : "_procfs_value_get") - + "_" + lex_cast<string>(tick++)); + + "_" + lex_cast(tick++)); string locvalue = "CONTEXT->data"; if (! lvalue) diff --git a/tapset-timers.cxx b/tapset-timers.cxx index 565a54e8..16dcefcb 100644 --- a/tapset-timers.cxx +++ b/tapset-timers.cxx @@ -193,10 +193,10 @@ struct hrtimer_derived_probe: public derived_probe { if ((i < min_ns_interval) || (i > max_ns_interval)) throw semantic_error(string("interval value out of range (") - + lex_cast<string>(scale < min_ns_interval + + lex_cast(scale < min_ns_interval ? min_ns_interval/scale : 1) + "," - + lex_cast<string>(max_ns_interval/scale) + ")"); + + lex_cast(max_ns_interval/scale) + ")"); // randomize = 0 means no randomization if ((r < 0) || (r > i)) diff --git a/tapset-utrace.cxx b/tapset-utrace.cxx index d9d95f82..490af20f 100644 --- a/tapset-utrace.cxx +++ b/tapset-utrace.cxx @@ -224,7 +224,7 @@ utrace_var_expanding_visitor::visit_target_symbol_cached (target_symbol* e) // _utrace_tvar_{name}_{num} string aname = (string("_utrace_tvar_") + e->base_name.substr(1) - + "_" + lex_cast<string>(tick++)); + + "_" + lex_cast(tick++)); vardecl* vd = new vardecl; vd->name = aname; vd->tok = e->tok; @@ -429,10 +429,10 @@ utrace_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) { if (i > 0) pf->raw_components += " "; - pf->raw_components += "$arg" + lex_cast<string>(i+1); + pf->raw_components += "$arg" + lex_cast(i+1); target_symbol *tsym = new target_symbol; tsym->tok = e->tok; - tsym->base_name = "$arg" + lex_cast<string>(i+1); + tsym->base_name = "$arg" + lex_cast(i+1); tsym->saved_conversion_error = 0; pf->raw_components += "=%#x"; //FIXME: missing type info diff --git a/tapsets.cxx b/tapsets.cxx index 6a52050c..053344cf 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -552,6 +552,10 @@ struct dwarf_query : public base_query // Track addresses we've already seen in a given module set<Dwarf_Addr> alias_dupes; + // Track inlines we've already seen as well + // NB: this can't be compared just by entrypc, as inlines can overlap + set<inline_instance_info> inline_dupes; + // Extracted parameters. string function_val; @@ -850,6 +854,7 @@ dwarf_query::handle_query_module() // reset the dupe-checking for each new module alias_dupes.clear(); + inline_dupes.clear(); if (dw.mod_info->dwarf_status == info_present) query_module_dwarf(); @@ -960,12 +965,11 @@ dwarf_query::add_probe_point(const string& funcname, { string reloc_section; // base section for relocation purposes Dwarf_Addr reloc_addr; // relocated - string blacklist_section; // linking section for blacklist purposes const string& module = dw.module_name; // "kernel" or other assert (! has_absolute); // already handled in dwarf_builder::build() - reloc_addr = dw.relocate_address(addr, reloc_section, blacklist_section); + reloc_addr = dw.relocate_address(addr, reloc_section); if (sess.verbose > 1) { @@ -977,12 +981,11 @@ dwarf_query::add_probe_point(const string& funcname, else if (has_process) clog << " process=" << module; if (reloc_section != "") clog << " reloc=" << reloc_section; - if (blacklist_section != "") clog << " section=" << blacklist_section; clog << " pc=0x" << hex << addr << dec; } bool bad = dw.blacklisted_p (funcname, filename, line, module, - blacklist_section, addr, has_return); + addr, has_return); if (sess.verbose > 1) clog << endl; @@ -1248,6 +1251,22 @@ query_srcfile_line (const dwarf_line_t& line, void * arg) } +bool +inline_instance_info::operator<(const inline_instance_info& other) const +{ + if (entrypc != other.entrypc) + return entrypc < other.entrypc; + + if (decl_line != other.decl_line) + return decl_line < other.decl_line; + + int cmp = name.compare(other.name); + if (!cmp) + cmp = strcmp(decl_file, other.decl_file); + return cmp < 0; +} + + static int query_dwarf_inline_instance (Dwarf_Die * die, void * arg) { @@ -1275,7 +1294,11 @@ query_dwarf_inline_instance (Dwarf_Die * die, void * arg) inl.entrypc = entrypc; q->dw.function_file (&inl.decl_file); q->dw.function_line (&inl.decl_line); - q->filtered_inlines.push_back(inl); + + // make sure that this inline hasn't already + // been matched from a different CU + if (q->inline_dupes.insert(inl).second) + q->filtered_inlines.push_back(inl); } } return DWARF_CB_OK; @@ -1319,9 +1342,6 @@ query_dwarf_func (Dwarf_Die * func, base_query * bq) clog << "checking instances of inline " << q->dw.function_name << "\n"; q->dw.iterate_over_inline_instances (query_dwarf_inline_instance, q); - - if (q->dw.function_name_final_match (q->function)) - return DWARF_CB_ABORT; } else if (!q->dw.func_is_inline () && (! q->has_inline)) { @@ -1382,14 +1402,9 @@ query_dwarf_func (Dwarf_Die * func, base_query * bq) func.entrypc -= q->dw.module_bias; q->filtered_functions.push_back (func); - if (q->dw.function_name_final_match (q->function)) - return DWARF_CB_ABORT; } else assert(0); - - if (q->dw.function_name_final_match (q->function)) - return DWARF_CB_ABORT; } } return DWARF_CB_OK; @@ -1845,7 +1860,7 @@ dwarf_var_expanding_visitor::visit_target_symbol_saved_return (target_symbol* e) string aname = (string("_dwarf_tvar_") + e->base_name.substr(1) - + "_" + lex_cast<string>(tick++)); + + "_" + lex_cast(tick++)); vardecl* vd = new vardecl; vd->name = aname; vd->tok = e->tok; @@ -2256,7 +2271,7 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) string fname = (string(lvalue ? "_dwarf_tvar_set" : "_dwarf_tvar_get") + "_" + e->base_name.substr(1) - + "_" + lex_cast<string>(tick++)); + + "_" + lex_cast(tick++)); try { @@ -2322,7 +2337,7 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) { vardecl *v = new vardecl; v->type = pe_long; - v->name = "index" + lex_cast<string>(i); + v->name = "index" + lex_cast(i); v->tok = e->tok; fdecl->formal_args.push_back(v); } @@ -2565,7 +2580,7 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e) string fname = (string(lvalue ? "_dwarf_tvar_set" : "_dwarf_tvar_get") + "_" + e->base_name.substr(1) - + "_" + lex_cast<string>(tick++)); + + "_" + lex_cast(tick++)); // Synthesize a function. functiondecl *fdecl = new functiondecl; @@ -2591,7 +2606,7 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e) { vardecl *v = new vardecl; v->type = pe_long; - v->name = "index" + lex_cast<string>(i); + v->name = "index" + lex_cast(i); v->tok = e->tok; fdecl->formal_args.push_back(v); } @@ -2706,7 +2721,7 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname, // Range limit maxactive() value if (q.has_maxactive && (q.maxactive_val < 0 || q.maxactive_val > USHRT_MAX)) throw semantic_error ("maxactive value out of range [0," - + lex_cast<string>(USHRT_MAX) + "]", + + lex_cast(USHRT_MAX) + "]", q.base_loc->tok); // Expand target variables in the probe body @@ -2763,7 +2778,7 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname, { retro_name += ("@" + string (filename)); if (line > 0) - retro_name += (":" + lex_cast<string> (line)); + retro_name += (":" + lex_cast (line)); } comps.push_back (new probe_point::component @@ -3363,7 +3378,7 @@ sdt_var_expanding_visitor::visit_target_symbol (target_symbol *e) cast->tok = e->tok; cast->operand = fc; cast->components = e->components; - cast->type = probe_name + "_arg" + lex_cast<string>(argno); + cast->type = probe_name + "_arg" + lex_cast(argno); cast->module = process_name; cast->visit(this); @@ -4152,7 +4167,7 @@ module_info::update_symtab(cu_function_cache_t *funcs) // if this function is a new alias, then // save it to merge into the function cache if (it->second != fi) - new_funcs[it->second->name] = it->second->die; + new_funcs.insert(make_pair(it->second->name, it->second->die)); } } @@ -4251,7 +4266,7 @@ uprobe_derived_probe::uprobe_derived_probe (const string& function, { retro_name += ("@" + string (filename)); if (line > 0) - retro_name += (":" + lex_cast<string> (line)); + retro_name += (":" + lex_cast (line)); } comps.push_back (new probe_point::component @@ -5387,7 +5402,7 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) string fname = (string(lvalue ? "_tracepoint_tvar_set" : "_tracepoint_tvar_get") + "_" + e->base_name.substr(1) - + "_" + lex_cast<string>(tick++)); + + "_" + lex_cast(tick++)); fdecl->name = fname; fdecl->body = ec; @@ -5426,7 +5441,7 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) { vardecl *v = new vardecl; v->type = pe_long; - v->name = "index" + lex_cast<string>(i); + v->name = "index" + lex_cast(i); v->tok = e->tok; fdecl->formal_args.push_back(v); } diff --git a/translate.cxx b/translate.cxx index c0f7b48b..9a25df61 100644 --- a/translate.cxx +++ b/translate.cxx @@ -384,9 +384,9 @@ public: case statistic_decl::linear: prefix += string("HIST_LINEAR") - + ", " + stringify(sd.linear_low) - + ", " + stringify(sd.linear_high) - + ", " + stringify(sd.linear_step); + + ", " + lex_cast(sd.linear_low) + + ", " + lex_cast(sd.linear_high) + + ", " + lex_cast(sd.linear_step); break; case statistic_decl::logarithmic: @@ -456,7 +456,7 @@ protected: public: tmpvar(exp_type ty, unsigned & counter) - : var(true, ty, ("__tmp" + stringify(counter++))), overridden(false) + : var(true, ty, ("__tmp" + lex_cast(counter++))), overridden(false) {} tmpvar(const var& source) @@ -487,7 +487,7 @@ struct aggvar : public var { aggvar(unsigned & counter) - : var(true, pe_stats, ("__tmp" + stringify(counter++))) + : var(true, pe_stats, ("__tmp" + lex_cast(counter++))) {} string init() const @@ -625,8 +625,8 @@ struct mapvar throw semantic_error("adding a value of an unsupported map type"); res += "; if (unlikely(rc)) { c->last_error = \"Array overflow, check " + - stringify(maxsize > 0 ? - "size limit (" + stringify(maxsize) + ")" : "MAXMAPENTRIES") + lex_cast(maxsize > 0 ? + "size limit (" + lex_cast(maxsize) + ")" : "MAXMAPENTRIES") + "\"; goto out; }}"; return res; @@ -646,8 +646,8 @@ struct mapvar throw semantic_error("setting a value of an unsupported map type"); res += "; if (unlikely(rc)) { c->last_error = \"Array overflow, check " + - stringify(maxsize > 0 ? - "size limit (" + stringify(maxsize) + ")" : "MAXMAPENTRIES") + lex_cast(maxsize > 0 ? + "size limit (" + lex_cast(maxsize) + ")" : "MAXMAPENTRIES") + "\"; goto out; }}"; return res; @@ -671,7 +671,7 @@ struct mapvar { string mtype = is_parallel() ? "pmap" : "map"; string prefix = value() + " = _stp_" + mtype + "_new_" + keysym() + " (" + - (maxsize > 0 ? stringify(maxsize) : "MAXMAPENTRIES") ; + (maxsize > 0 ? lex_cast(maxsize) : "MAXMAPENTRIES") ; // See also var::init(). @@ -689,9 +689,9 @@ struct mapvar case statistic_decl::linear: // FIXME: check for "reasonable" values in linear stats prefix = prefix + ", HIST_LINEAR" - + ", " + stringify(sdecl().linear_low) - + ", " + stringify(sdecl().linear_high) - + ", " + stringify(sdecl().linear_step); + + ", " + lex_cast(sdecl().linear_low) + + ", " + lex_cast(sdecl().linear_high) + + ", " + lex_cast(sdecl().linear_step); break; case statistic_decl::logarithmic: @@ -728,7 +728,7 @@ public: itervar (symbol* e, unsigned & counter) : referent_ty(e->referent->type), - name("__tmp" + stringify(counter++)) + name("__tmp" + lex_cast(counter++)) { if (referent_ty == pe_unknown) throw semantic_error("iterating over unknown reference type", e->tok); @@ -775,11 +775,11 @@ public: switch (ty) { case pe_long: - return "_stp_key_get_int64 ("+ value() + ", " + stringify(i+1) + ")"; + return "_stp_key_get_int64 ("+ value() + ", " + lex_cast(i+1) + ")"; case pe_string: // impedance matching: NULL -> empty strings return "({ char *v = " - "_stp_key_get_str ("+ value() + ", " + stringify(i+1) + "); " + "_stp_key_get_str ("+ value() + ", " + lex_cast(i+1) + "); " "if (! v) v = \"\"; " "v; })"; default: @@ -2464,7 +2464,7 @@ c_tmpcounter::visit_for_loop (for_loop *s) void c_unparser::visit_for_loop (for_loop *s) { - string ctr = stringify (label_counter++); + string ctr = lex_cast (label_counter++); string toplabel = "top_" + ctr; string contlabel = "continue_" + ctr; string breaklabel = "break_" + ctr; @@ -2617,7 +2617,7 @@ c_unparser::visit_foreach_loop (foreach_loop *s) itervar iv = getiter (array); vector<var> keys; - string ctr = stringify (label_counter++); + string ctr = lex_cast (label_counter++); string toplabel = "top_" + ctr; string contlabel = "continue_" + ctr; string breaklabel = "break_" + ctr; diff --git a/unordered.h b/unordered.h new file mode 100644 index 00000000..6204dbfb --- /dev/null +++ b/unordered.h @@ -0,0 +1,56 @@ +// backward-compatible unordered containers +// Copyright (C) 2009 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 UNORDERED_H +#define UNORDERED_H + +#include "config.h" + +#if 0 // uncomment to force the old mode +#undef HAVE_TR1_UNORDERED_MAP +#define _BACKWARD_BACKWARD_WARNING_H 1 // defeat deprecation warning +#endif + +#ifdef HAVE_TR1_UNORDERED_MAP + +#include <tr1/unordered_map> +using std::tr1::unordered_map; +using std::tr1::unordered_multimap; + +#include <tr1/unordered_set> +using std::tr1::unordered_set; +using std::tr1::unordered_multiset; + +#else + +#include <ext/hash_map> +#define unordered_map __gnu_cxx::hash_map +#define unordered_multimap __gnu_cxx::hash_multimap + +#include <ext/hash_set> +#define unordered_set __gnu_cxx::hash_set +#define unordered_multiset __gnu_cxx::hash_multiset + +// Hack in common hash functions for strings and raw pointers +namespace __gnu_cxx +{ + template<class T> struct hash<T*> { + size_t operator() (T* p) const + { hash<long> h; return h(reinterpret_cast<long>(p)); } + }; + template<> struct hash<std::string> { + size_t operator() (std::string const& s) const + { hash<const char*> h; return h(s.c_str()); } + }; +} + +#endif + +#endif // UNORDERED_H + +/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ @@ -23,38 +23,35 @@ int kill_stap_spawn(int sig); // stringification generics -template <typename T> -inline std::string -stringify(T t) +template <typename IN> +inline std::string lex_cast(IN const & in) { - std::ostringstream s; - s << t; - return s.str (); + std::ostringstream ss; + if (!(ss << in)) + throw std::runtime_error("bad lexical cast"); + return ss.str(); } -template <typename OUT, typename IN> -inline OUT lex_cast(IN const & in) +template <typename OUT> +inline OUT lex_cast(std::string const & in) { - std::stringstream ss; + std::istringstream ss(in); OUT out; - // NB: ss >> string out assumes that "in" renders to one word - if (!(ss << in && ss >> out)) + if (!(ss >> out && ss.eof())) throw std::runtime_error("bad lexical cast"); return out; } -template <typename OUT, typename IN> -inline OUT +template <typename IN> +inline std::string lex_cast_hex(IN const & in) { - std::stringstream ss; - OUT out; - // NB: ss >> string out assumes that "in" renders to one word - if (!(ss << "0x" << std::hex << in && ss >> out)) + std::ostringstream ss; + if (!(ss << std::showbase << std::hex << in)) throw std::runtime_error("bad lexical cast"); - return out; + return ss.str(); } @@ -65,32 +62,39 @@ inline std::string lex_cast_qstring(IN const & in) { std::stringstream ss; - std::string out, out2; if (!(ss << in)) throw std::runtime_error("bad lexical cast"); - out = ss.str(); // "in" is expected to render to more than one word - out2 += '"'; - for (unsigned i=0; i<out.length(); i++) + return lex_cast_qstring(ss.str()); +} + + +template <> +inline std::string +lex_cast_qstring(std::string const & in) +{ + std::string out; + out += '"'; + for (const char *p = in.c_str(); *p; ++p) { - unsigned char c = out[i]; + unsigned char c = *p; if (! isprint(c)) { - out2 += '\\'; + out += '\\'; // quick & dirty octal converter - out2 += "01234567" [(c >> 6) & 0x07]; - out2 += "01234567" [(c >> 3) & 0x07]; - out2 += "01234567" [(c >> 0) & 0x07]; + out += "01234567" [(c >> 6) & 0x07]; + out += "01234567" [(c >> 3) & 0x07]; + out += "01234567" [(c >> 0) & 0x07]; } else if (c == '"' || c == '\\') { - out2 += '\\'; - out2 += c; + out += '\\'; + out += c; } else - out2 += c; + out += c; } - out2 += '"'; - return out2; + out += '"'; + return out; } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ |