From 5f8ca04fbb0682ff8647b4df5de68cd1042e312d Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 29 Sep 2009 00:12:26 +0200 Subject: Factor out duplicated code to setup user/module Dwfl from dwflpp/translate. * setupdwfl.h: Add setup_dwfl_user() and is_user_module(). * setupdwfl.cxx: Likewise. * dwflpp.cxx (setup_user): Use setup_dwfl_user(). * translate.cxx (emit_symbol_data): Likewise and is_user_module(). * tapsets.cxx (dwarf_cast_expanding_visitor::visit_cast_op): Use is_user_module(). --- dwflpp.cxx | 55 +++++++++----------------------------------------- setupdwfl.cxx | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ setupdwfl.h | 10 +++++++++ tapsets.cxx | 3 ++- translate.cxx | 33 ++++++------------------------ 5 files changed, 92 insertions(+), 74 deletions(-) diff --git a/dwflpp.cxx b/dwflpp.cxx index cc882e5d..b8e39b69 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -354,54 +354,17 @@ dwflpp::setup_user(const vector& modules, bool debuginfo_needed) if (! sess.module_cache) sess.module_cache = new module_cache (); - static const char *debuginfo_path_arr = "+:.debug:/usr/lib/debug:build"; - static const char *debuginfo_env_arr = getenv("SYSTEMTAP_DEBUGINFO_PATH"); - // NB: kernel_build_tree doesn't enter into this, as it's for - // kernel-side modules only. - static const char *debuginfo_path = (debuginfo_env_arr ?: debuginfo_path_arr); - - static const Dwfl_Callbacks user_callbacks = - { - NULL, /* dwfl_linux_kernel_find_elf, */ - dwfl_standard_find_debuginfo, - dwfl_offline_section_address, - (char **) & debuginfo_path - }; - - dwfl = dwfl_begin (&user_callbacks); - if (!dwfl) - throw semantic_error ("cannot open dwfl"); - dwfl_report_begin (dwfl); - - vector::const_iterator it; - for (it = modules.begin(); it != modules.end(); ++it) - { - // XXX: should support buildid-based naming - - const string& module_name = *it; - Dwfl_Module *mod = dwfl_report_offline (dwfl, - module_name.c_str(), - module_name.c_str(), - -1); - - if (debuginfo_needed) - dwfl_assert (string("missing process ") + - module_name + - string(" ") + - sess.architecture + - string(" debuginfo"), - mod); - } - - // NB: the result of an _offline call is the assignment of - // virtualized addresses to relocatable objects such as - // modules. These have to be converted to real addresses at - // run time. See the dwarf_derived_probe ctor and its caller. - - dwfl_assert ("dwfl_report_end", dwfl_report_end(dwfl, NULL, NULL)); + vector::const_iterator it = modules.begin(); + dwfl = setup_dwfl_user(it, modules.end(), debuginfo_needed); + if (debuginfo_needed && it != modules.end()) + dwfl_assert (string("missing process ") + + *it + + string(" ") + + sess.architecture + + string(" debuginfo"), + dwfl); } - void dwflpp::iterate_over_modules(int (* callback)(Dwfl_Module *, void **, const char *, Dwarf_Addr, diff --git a/setupdwfl.cxx b/setupdwfl.cxx index 49667152..33d481ef 100644 --- a/setupdwfl.cxx +++ b/setupdwfl.cxx @@ -25,6 +25,12 @@ static const char *debuginfo_path_arr = "+:.debug:/usr/lib/debug:build"; static const char *debuginfo_env_arr = getenv("SYSTEMTAP_DEBUGINFO_PATH"); static const char *debuginfo_path = (debuginfo_env_arr ?: debuginfo_path_arr); +// NB: kernel_build_tree doesn't enter into this, as it's for +// kernel-side modules only. +static const char *debuginfo_usr_path_arr = "+:.debug:/usr/lib/debug"; +static const char *debuginfo_usr_path = (debuginfo_env_arr + ?: debuginfo_usr_path_arr); + static const Dwfl_Callbacks kernel_callbacks = { dwfl_linux_kernel_find_elf, @@ -33,6 +39,15 @@ static const Dwfl_Callbacks kernel_callbacks = (char **) & debuginfo_path }; +static const Dwfl_Callbacks user_callbacks = + { + NULL, + dwfl_standard_find_debuginfo, + NULL, /* ET_REL not supported for user space, only ET_EXEC and ET_DYN. + dwfl_offline_section_address, */ + (char **) & debuginfo_usr_path + }; + using namespace std; // Setup in setup_dwfl_kernel(), for use in setup_dwfl_report_kernel_p(). @@ -191,3 +206,53 @@ setup_dwfl_kernel(const std::set &names, offline_search_names = names; return setup_dwfl_kernel(found, s); } + +Dwfl* +setup_dwfl_user(const std::string &name) +{ + Dwfl *dwfl = dwfl_begin (&user_callbacks); + dwfl_assert("dwfl_begin", dwfl); + dwfl_report_begin (dwfl); + + // XXX: should support buildid-based naming + const char *cname = name.c_str(); + Dwfl_Module *mod = dwfl_report_offline (dwfl, cname, cname, -1); + dwfl_assert ("dwfl_report_end", dwfl_report_end(dwfl, NULL, NULL)); + if (! mod) + { + dwfl_end(dwfl); + dwfl = NULL; + } + return dwfl; +} + +Dwfl* +setup_dwfl_user(std::vector::const_iterator &begin, + const std::vector::const_iterator &end, + bool all_needed) +{ + Dwfl *dwfl = dwfl_begin (&user_callbacks); + dwfl_assert("dwfl_begin", dwfl); + dwfl_report_begin (dwfl); + + // XXX: should support buildid-based naming + while (begin != end && dwfl != NULL) + { + const char *cname = (*begin).c_str(); + Dwfl_Module *mod = dwfl_report_offline (dwfl, cname, cname, -1); + if (! mod && all_needed) + { + dwfl_end(dwfl); + dwfl = NULL; + } + begin++; + } + if (dwfl) + dwfl_assert ("dwfl_report_end", dwfl_report_end(dwfl, NULL, NULL)); + return dwfl; +} + +bool is_user_module(const std::string &m) +{ + return m[0] == '/' && m.rfind(".ko", m.length() - 1) != m.length() - 3; +} diff --git a/setupdwfl.h b/setupdwfl.h index 7884e4da..67a66397 100644 --- a/setupdwfl.h +++ b/setupdwfl.h @@ -14,6 +14,7 @@ #include #include +#include extern "C" { #include @@ -25,4 +26,13 @@ Dwfl *setup_dwfl_kernel(const std::string &name, Dwfl *setup_dwfl_kernel(const std::set &names, unsigned *found, systemtap_session &s); + +Dwfl* setup_dwfl_user(const std::string &name); +Dwfl* setup_dwfl_user(std::vector::const_iterator &begin, + const std::vector::const_iterator &end, + bool all_needed); + +// user-space files must be full paths and not end in .ko +bool is_user_module(const std::string &m); + #endif diff --git a/tapsets.cxx b/tapsets.cxx index 4a8432f7..bedb267a 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -21,6 +21,7 @@ #include "auto_free.h" #include "hash.h" #include "dwflpp.h" +#include "setupdwfl.h" #include #include @@ -2606,7 +2607,7 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e) dwflpp* dw; try { - if (module.find('/') == string::npos) + if (! is_user_module (module)) { // kernel or kernel module target dw = db.get_kern_dw(s, module); diff --git a/translate.cxx b/translate.cxx index 1bb6252f..0f53dc78 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4957,8 +4957,9 @@ emit_symbol_data (systemtap_session& s) it++) { string foo = *it; - if (foo[0] != '/') /* Omit user-space, since we're only using this for - kernel space offline searches. */ + if (! is_user_module (foo)) /* Omit user-space, since we're only + using this for kernel space + offline searches. */ offline_search_modules.insert (foo); } Dwfl *dwfl = setup_dwfl_kernel (offline_search_modules, &count, s); @@ -4978,37 +4979,15 @@ emit_symbol_data (systemtap_session& s) // ---- step 2: process any user modules (files) listed - // XXX: see dwflpp::setup_user. - - // XXX: copied from tapsets.cxx dwflpp::, sadly - static const char *debuginfo_path_arr = "+:.debug:/usr/lib/debug:build"; - static const char *debuginfo_env_arr = getenv("SYSTEMTAP_DEBUGINFO_PATH"); - static const char *debuginfo_path = (debuginfo_env_arr ?: debuginfo_path_arr); - - static const Dwfl_Callbacks user_callbacks = - { - NULL, /* dwfl_linux_kernel_find_elf, */ - dwfl_standard_find_debuginfo, - NULL, /* ET_REL not supported for user space, only ET_EXEC and ET_DYN. - dwfl_offline_section_address, */ - (char **) & debuginfo_path - }; - for (std::set::iterator it = s.unwindsym_modules.begin(); it != s.unwindsym_modules.end(); it++) { string modname = *it; assert (modname.length() != 0); - if (modname[0] != '/') continue; // user-space files must be full paths - Dwfl *dwfl = dwfl_begin (&user_callbacks); - if (!dwfl) - throw semantic_error ("cannot create dwfl for " + modname); - - dwfl_report_begin (dwfl); - Dwfl_Module* mod = dwfl_report_offline (dwfl, modname.c_str(), modname.c_str(), -1); - dwfl_report_end (dwfl, NULL, NULL); - if (mod != 0) // tolerate missing data; will warn below + if (! is_user_module (modname)) continue; + Dwfl *dwfl = setup_dwfl_user (modname); + if (dwfl != NULL) // tolerate missing data; will warn below { ptrdiff_t off = 0; do -- cgit