From aca66a36681ac7cbf7fcc2eac4dafc83d6559ef9 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 2 Sep 2009 16:14:08 -0700 Subject: Unify lex_cast* and avoid string copies We always use lex_cast either to string or from string, so I made that explicit, and got rid of some string copies in the process. There was also stringify(), which was redundant to lex_cast. We also always used lex_cast_hex to string, so that's now hard-coded and again eliminated a string copy. For lex_cast_qstring, there's no need to write the streamify the input, so a specialization now operates directly on the input. Hopefully this is a bit cleaner, and I do measure it to be a little faster on scripts with many probes. --- dwflpp.cxx | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'dwflpp.cxx') diff --git a/dwflpp.cxx b/dwflpp.cxx index ba8dcec7..9dcfd002 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -1243,7 +1243,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(extra) + " more"; + lookup_method += ", ignored " + lex_cast(extra) + " more"; } } @@ -1437,7 +1437,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(pc) + + lex_cast_hex(pc) + ((scope_die == NULL) ? "" : (string (" in ") + (dwarf_diename(scope_die) ?: "") @@ -1456,7 +1456,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(pc) + + " near pc " + lex_cast_hex(pc) + ((scope_die == NULL) ? "" : (string (" in ") + (dwarf_diename(scope_die) ?: "") @@ -1727,7 +1727,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 +1749,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(c) + throw semantic_error ("invalid access '" + lex_cast(c) + "' vs. " + dwarf_type_name(die), c.tok); @@ -1768,14 +1768,14 @@ dwflpp::translate_components(struct obstack *pool, } else if (c.type == target_symbol::comp_expression_array_index) { - string index = "THIS->index" + lex_cast(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(c) + + lex_cast(c) + "' for array type", c.tok); break; @@ -1785,7 +1785,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(c) + + lex_cast(c) + "' for " + dwarf_type_name(die), c.tok); @@ -1811,7 +1811,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(line) + ")"; + + lex_cast(line) + ")"; } string alternatives; @@ -1836,7 +1836,7 @@ dwflpp::translate_components(struct obstack *pool, case DW_TAG_enumeration_type: case DW_TAG_base_type: throw semantic_error ("invalid access '" - + lex_cast(c) + + lex_cast(c) + "' vs. " + dwarf_type_name(die), c.tok); break; @@ -1848,7 +1848,7 @@ dwflpp::translate_components(struct obstack *pool, default: throw semantic_error (dwarf_type_name(die) + ": unexpected type tag " - + lex_cast(dwarf_tag (die)), + + lex_cast(dwarf_tag (die)), c.tok); break; } @@ -1936,7 +1936,7 @@ dwflpp::translate_final_fetch_or_store (struct obstack *pool, { default: throw semantic_error ("unsupported type tag " - + lex_cast(typetag) + + lex_cast(typetag) + " for " + dwarf_type_name(typedie), e->tok); break; @@ -1959,7 +1959,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(encoding) + ")" + + throw semantic_error ("unsupported type (mystery encoding " + lex_cast(encoding) + ")" + " for " + dwarf_type_name(typedie), e->tok); } @@ -1968,7 +1968,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(encoding) + ")" + + throw semantic_error ("unsupported type (encoding " + lex_cast(encoding) + ")" + " for " + dwarf_type_name(typedie), e->tok); } } @@ -2097,7 +2097,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(dwarf_dieoffset (&vardie)) + + lex_cast_hex(dwarf_dieoffset (&vardie)) + ")", e->tok); } -- cgit From 7a1921492e38221e1552b7698f001fa70d0e0e8b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 2 Sep 2009 18:40:14 -0700 Subject: Delete stuff that dwflpp newed * dwflpp.cxx (dwflpp::~dwflpp): Delete all of the caches. --- dwflpp.cxx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'dwflpp.cxx') diff --git a/dwflpp.cxx b/dwflpp.cxx index 9dcfd002..3c6a106d 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -93,6 +93,23 @@ dwflpp::dwflpp(systemtap_session & session, const vector& 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_function_cache_t::iterator it = global_alias_cache.begin(); + it != global_alias_cache.end(); ++it) + delete it->second; + if (dwfl) dwfl_end(dwfl); } -- cgit From b74789646bfe59131327716357c8b7c1521fa14a Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 2 Sep 2009 19:09:50 -0700 Subject: PR10572: Allow duplicate function names in a CU We can't assume that a given function name will only appear once in a CU. In C++, two functions may have the same name in different classes or namespaces, or even in the same scope with overloaded parameters. Even in C, the compiler may generate multiple copies of a single function with different optimizations. We now use a multimap for function names, so we shouldn't miss any. * dwflpp.h (cu_type_cache_t, mod_cu_type_cache_t): New typedef to keep a normal map for the global_alias_cache. (cu_function_cache_t): Use a multimap for function names. * dwflpp.cxx (dwflpp::iterate_over_functions): Walk over the range of exactly-matching functions. * tapsets.cxx (query_dwarf_func): Don't abort after seeing an exact match -- there could be more to come. --- dwflpp.cxx | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'dwflpp.cxx') diff --git a/dwflpp.cxx b/dwflpp.cxx index 3c6a106d..d55852ee 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -106,7 +106,7 @@ dwflpp::~dwflpp() it != cu_inl_function_cache.end(); ++it) delete it->second; - for (mod_cu_function_cache_t::iterator it = global_alias_cache.begin(); + for (mod_cu_type_cache_t::iterator it = global_alias_cache.begin(); it != global_alias_cache.end(); ++it) delete it->second; @@ -594,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(arg); + cu_type_cache_t *cache = static_cast(arg); const char *name = dwarf_diename(die); if (!name) @@ -616,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) @@ -650,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; } @@ -677,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)) { -- cgit From 789448a36f57e53cc6a1878f7637998b0f15652c Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 3 Sep 2009 12:00:10 -0700 Subject: Fetch the blacklist section only when needed We only check blacklisting on kernel probes, so it's a waste to dig up the section name otherwise. * dwflpp.cxx (dwflpp::blacklisted_p): Lookup the section directly. (relocate_address::relocate_address): Don't do blacklisting here. * tapsets.cxx (dwarf_query::add_probe_point): Don't carry the blacklist section directly anymore. --- dwflpp.cxx | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'dwflpp.cxx') diff --git a/dwflpp.cxx b/dwflpp.cxx index d55852ee..650acb70 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -2302,13 +2302,13 @@ 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 + string section = get_blacklist_section(addr); if (section.substr(0, 6) == string(".init.") || section.substr(0, 6) == string(".exit.") || section.substr(0, 9) == string(".devinit.") || @@ -2533,9 +2533,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 @@ -2544,7 +2542,6 @@ dwflpp::relocate_address(Dwarf_Addr dw_addr, { assert(module_name == TOK_KERNEL); reloc_section = ""; - blacklist_section = ""; } else if (dwfl_module_relocations (module) > 0) { @@ -2554,19 +2551,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; } -- cgit From 178ac3f6fdef839ef1ca646421e2c436a91ac1fb Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 3 Sep 2009 12:26:37 -0700 Subject: Use a regexp for matching blacklist sections We already use regexp for function/file blacklisting, so this just makes the section blacklisting consistent with the rest. * dwflpp.cxx (dwflpp::blacklisted_p): Use regexec instead of section==. (dwflpp::build_blacklist): Build blacklist_section too. --- dwflpp.cxx | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'dwflpp.cxx') diff --git a/dwflpp.cxx b/dwflpp.cxx index 650acb70..04561d3c 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -2309,14 +2309,7 @@ dwflpp::blacklisted_p(const string& funcname, return false; // no blacklist for userspace string section = get_blacklist_section(addr); - 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.")) + 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, @@ -2372,6 +2365,16 @@ dwflpp::build_blacklist() string blfn = "^("; string blfn_ret = "^("; string blfile = "^("; + 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"; @@ -2472,6 +2475,7 @@ dwflpp::build_blacklist() blfn += ")$"; blfn_ret += ")$"; blfile += ")$"; + blsection += ")"; // NB: no $, sections match just the beginning if (sess.verbose > 2) { @@ -2479,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); @@ -2487,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; } -- cgit From b969d16b2986a491eb37706e09da888d9914a7dd Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 3 Sep 2009 12:31:21 -0700 Subject: Escape literal '.'s in regular expressions * dwflpp.cxx (dwflpp::build_blacklist): Escape '.'s in filenames. --- dwflpp.cxx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'dwflpp.cxx') diff --git a/dwflpp.cxx b/dwflpp.cxx index 04561d3c..2437630e 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -2376,15 +2376,15 @@ dwflpp::build_blacklist() blsection += "|\\.meminit\\."; blsection += "|\\.memexit\\."; - blfile += "kernel/kprobes.c"; // first alternative, no "|" - blfile += "|arch/.*/kernel/kprobes.c"; + 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. -- cgit