diff options
-rw-r--r-- | ChangeLog | 1 | ||||
-rw-r--r-- | main.cxx | 17 | ||||
-rw-r--r-- | runtime/transport/ChangeLog | 3 | ||||
-rw-r--r-- | session.h | 3 | ||||
-rw-r--r-- | tapsets.cxx | 8 | ||||
-rw-r--r-- | translate.cxx | 195 |
6 files changed, 131 insertions, 96 deletions
@@ -289,6 +289,7 @@ PR 6429. * Makefile.am: Don't link stapio with -ldw. + * Makefile.in: Regenerated. 2008-05-29 Mark Wielaard <mwielaard@redhat.com> @@ -106,6 +106,17 @@ usage (systemtap_session& s, int exitcode) << " -c CMD start the probes, run CMD, and exit when it finishes" << endl << " -x PID sets target() to PID" << endl + << " -d OBJECT add unwind/symbol data for OBJECT file"; + if (s.unwindsym_modules.size() == 0) + clog << endl; + else + clog << ", in addition to" << endl; + { + vector<string> syms (s.unwindsym_modules.begin(), s.unwindsym_modules.end()); + for (unsigned i=0; i<syms.size(); i++) + clog << " " << syms[i] << endl; + } + clog << " -t collect probe timing information" << endl #ifdef HAVE_LIBSQLITE3 << " -q generate information on tapset coverage" << endl @@ -393,7 +404,7 @@ main (int argc, char * const argv []) { "ignore-dwarf", 0, &long_opt, LONG_OPT_IGNORE_DWARF }, { NULL, 0, NULL, 0 } }; - int grc = getopt_long (argc, argv, "hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqwl:", + int grc = getopt_long (argc, argv, "hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqwl:d:", long_options, NULL); if (grc < 0) break; @@ -437,6 +448,10 @@ main (int argc, char * const argv []) s.include_path.push_back (string (optarg)); break; + case 'd': + s.unwindsym_modules.insert (string (optarg)); + break; + case 'e': if (have_script) { diff --git a/runtime/transport/ChangeLog b/runtime/transport/ChangeLog index 3dd65408..98548afa 100644 --- a/runtime/transport/ChangeLog +++ b/runtime/transport/ChangeLog @@ -9,7 +9,8 @@ * symbols.c (_stp_validate_addr): Add validating address in runtime. 2008-06-13 Wenji Huang <wenji.huang@oracle.com> - * control.c (_stp_ctl_write_dbug): Remove STP_UNWIND support. + + * control.c (_stp_ctl_write_dbug): Remove STP_UNWIND support. 2008-06-03 Frank Ch. Eigler <fche@elastic.org> @@ -164,7 +164,10 @@ struct systemtap_session Dwarf_Addr sym_kprobes_text_end; Dwarf_Addr sym_stext; + // List of libdwfl module names to extract symbol/unwind data for. + std::set<std::string> unwindsym_modules; struct module_cache* module_cache; + std::set<std::string> seen_errors; std::set<std::string> seen_warnings; unsigned num_errors () { return seen_errors.size(); } diff --git a/tapsets.cxx b/tapsets.cxx index a405cef0..35428fcd 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -3164,6 +3164,7 @@ dwarf_query::add_probe_point(const string& funcname, if (! bad) { + sess.unwindsym_modules.insert (module); probe = new dwarf_derived_probe(funcname, filename, line, module, reloc_section, addr, reloc_addr, *this, scope_die); results.push_back(probe); @@ -3210,7 +3211,6 @@ dwarf_query::assess_dbinfo_reqt() } - // The critical determining factor when interpreting a pattern // string is, perhaps surprisingly: "presence of a lineno". The // presence of a lineno changes the search strategy completely. @@ -4751,6 +4751,7 @@ dwarf_builder::build(systemtap_session & sess, q.statement_num_val, q.statement_num_val, q, 0); finished_results.push_back (p); + sess.unwindsym_modules.insert ("kernel"); return; } @@ -5379,6 +5380,9 @@ struct utrace_builder: public derived_probe_builder string::size_type start_pos, end_pos; string component; + // XXX: these checks should be done in terms of filesystem + // operations. + // Make sure it starts with '/'. if (path[0] != '/') throw semantic_error ("process path must start with a '/'", @@ -5405,6 +5409,8 @@ struct utrace_builder: public derived_probe_builder // Make sure it isn't relative. else if (component == "." || component == "..") throw semantic_error ("process path cannot be relative (and contain '.' or '..')", location->tok); + + sess.unwindsym_modules.insert (path); } finished_results.push_back(new utrace_derived_probe(sess, base, location, diff --git a/translate.cxx b/translate.cxx index 2c1cb84c..433b82be 100644 --- a/translate.cxx +++ b/translate.cxx @@ -14,6 +14,7 @@ #include "session.h" #include "tapsets.h" #include "util.h" +#include "dwarf_wrappers.h" #include <cstdlib> #include <iostream> @@ -4325,51 +4326,75 @@ c_unparser::visit_hist_op (hist_op*) } -static map< Dwarf_Addr, string> addrmap; -#include <string.h> - -static int -kernel_filter (const char *module, const char *file __attribute__((unused))) +struct unwindsym_dump_context { - return !strcmp(module,"kernel"); -} + systemtap_session& session; + ostream& output; +}; + static int -get_symbols (Dwfl_Module *m, - void **userdata __attribute__ ((unused)), - const char *name __attribute__ ((unused)), - Dwarf_Addr base __attribute__ ((unused)), - void *arg __attribute__ ((unused))) +dump_unwindsyms (Dwfl_Module *m, + void **userdata __attribute__ ((unused)), + const char *name, + Dwarf_Addr base, + void *arg) { + unwindsym_dump_context* c = (unwindsym_dump_context*) arg; + assert (c); + + string modname = name; + + // skip modules/files we're not actually interested in + if (c->session.unwindsym_modules.find(modname) == c->session.unwindsym_modules.end()) + return DWARF_CB_OK; + + if (c->session.verbose > 1) + clog << "dump_unwindsyms " << name << " base=0x" << hex << base << dec << endl; + + // We want to extract several bits of information: + // - parts of the program-header that map the file's physical offsets to the text section + // - symbol table of the text section + // - the contents .debug_frame section + // In the future, we'll also care about data symbols. + int syments = dwfl_module_getsymtab(m); assert(syments); for (int i = 1; i < syments; ++i) { GElf_Sym sym; const char *name = dwfl_module_getsym(m, i, &sym, NULL); - if (name) { - if (GELF_ST_TYPE (sym.st_info) == STT_FUNC || - strcmp(name, "_etext") == 0 || - strcmp(name, "_stext") == 0 || - strcmp(name, "modules_op") == 0) - addrmap[sym.st_value] = name; - } + if (name) + { + if (GELF_ST_TYPE (sym.st_info) == STT_FUNC) + ; // addrmap[sym.st_value] = name; + } } return DWARF_CB_OK; } -int -emit_symbol_data_from_debuginfo(systemtap_session& s, ofstream& kallsyms_out) + +void +emit_symbol_data (systemtap_session& s) { + string symfile = "stap-symbols.h"; + ofstream kallsyms_out ((s.tmpdir + "/" + symfile).c_str()); + + unwindsym_dump_context ctx = { s, kallsyms_out }; + + s.op->newline() << "\n\n#include \"" << symfile << "\""; + + // XXX: copied from tapsets.cxx, sadly static char debuginfo_path_arr[] = "-:.debug:/usr/lib/debug:build"; static char *debuginfo_env_arr = getenv("SYSTEMTAP_DEBUGINFO_PATH"); static char *debuginfo_path = (debuginfo_env_arr ? - debuginfo_env_arr : debuginfo_path_arr); + debuginfo_env_arr : debuginfo_path_arr); static const char *debug_path = (debuginfo_env_arr ? - debuginfo_env_arr : s.kernel_release.c_str()); - + debuginfo_env_arr : s.kernel_release.c_str()); + + // ---- step 1: process any kernel modules listed static const Dwfl_Callbacks kernel_callbacks = { dwfl_linux_kernel_find_elf, @@ -4378,75 +4403,59 @@ emit_symbol_data_from_debuginfo(systemtap_session& s, ofstream& kallsyms_out) & debuginfo_path }; - Dwfl *dwfl = dwfl_begin (&kernel_callbacks); + Dwfl *dwfl = dwfl_begin (&kernel_callbacks); + if (!dwfl) + throw semantic_error ("cannot open dwfl"); + dwfl_report_begin (dwfl); + int rc = dwfl_linux_kernel_report_offline (dwfl, debug_path, NULL /* XXX: filtering callback */); + dwfl_report_end (dwfl, NULL, NULL); + dwfl_assert ("dwfl_linux_kernel_report_offline", rc); + ptrdiff_t off = 0; + do + { + if (pending_interrupts) return; + off = dwfl_getmodules (dwfl, &dump_unwindsyms, (void *) &ctx, 0); + } + while (off > 0); + dwfl_assert("dwfl_getmodules", off == 0); + dwfl_end(dwfl); + + + // ---- step 2: process any user modules (files) listed + static const Dwfl_Callbacks user_callbacks = + { + NULL, /* dwfl_linux_kernel_find_elf, */ + dwfl_standard_find_debuginfo, + dwfl_offline_section_address, + & debuginfo_path + }; + + for (std::set<std::string>::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 open dwfl"); + throw semantic_error ("cannot create dwfl for " + modname); + dwfl_report_begin (dwfl); - - int rc = dwfl_linux_kernel_report_offline (dwfl, - debug_path, - kernel_filter); + Dwfl_Module* mod = dwfl_report_offline (dwfl, modname.c_str(), modname.c_str(), -1); dwfl_report_end (dwfl, NULL, NULL); - if (rc < 0) - return rc; - - dwfl_getmodules (dwfl, &get_symbols, NULL, 0); + dwfl_assert ("dwfl_report_offline", mod); + ptrdiff_t off = 0; + do + { + if (pending_interrupts) return; + off = dwfl_getmodules (dwfl, &dump_unwindsyms, (void *) &ctx, 0); + } + while (off > 0); + dwfl_assert("dwfl_getmodules", off == 0); dwfl_end(dwfl); - - int i = 0; - map< Dwarf_Addr, string>::iterator pos; - kallsyms_out << "struct _stp_symbol _stp_kernel_symbols [] = {"; - for (pos = addrmap.begin(); pos != addrmap.end(); pos++) { - kallsyms_out << " { 0x" << hex << pos->first << ", " << "\"" << pos->second << "\" },\n"; - i++; - } - - kallsyms_out << "};\n"; - kallsyms_out << "unsigned _stp_num_kernel_symbols = " << dec << i << ";\n"; - return i == 0; -} - -int -emit_symbol_data (systemtap_session& s) -{ - unsigned i=0; - char kallsyms_outbuf [4096]; - ofstream kallsyms_out ((s.tmpdir + "/stap-symbols.h").c_str()); - kallsyms_out.rdbuf()->pubsetbuf (kallsyms_outbuf, - sizeof(kallsyms_outbuf)); - s.op->newline() << "\n\n#include \"stap-symbols.h\""; - - // FIXME for non-debuginfo use. - if (true) { - return emit_symbol_data_from_debuginfo(s, kallsyms_out); - } else { - // For symbol-table only operation, we don't have debuginfo, - // so parse /proc/kallsyms. - - ifstream kallsyms("/proc/kallsyms"); - string lastaddr, modules_op_addr; - - kallsyms_out << "struct _stp_symbol _stp_kernel_symbols [] = {"; - while (! kallsyms.eof()) - { - string addr, type, sym; - kallsyms >> addr >> type >> sym >> ws; - - if (kallsyms.peek() == '[') - break; - - // NB: kallsyms includes some duplicate addresses - if ((type == "t" || type == "T" || type == "A" || sym == "modules_op") && lastaddr != addr) - { - kallsyms_out << " { 0x" << addr << ", " << "\"" << sym << "\" },\n"; - lastaddr = addr; - i ++; - } - } - kallsyms_out << "};\n"; - kallsyms_out << "unsigned _stp_num_kernel_symbols = " << i << ";\n"; - } - return (i == 0); + } } @@ -4612,16 +4621,16 @@ translate_pass (systemtap_session& s) s.up->emit_global_param (s.globals[i]); } - s.op->newline() << "MODULE_DESCRIPTION(\"systemtap probe\");"; - s.op->newline() << "MODULE_LICENSE(\"GPL\");"; // XXX + emit_symbol_data (s); + + s.op->newline() << "MODULE_DESCRIPTION(\"systemtap-generated probe\");"; + s.op->newline() << "MODULE_LICENSE(\"GPL\");"; } catch (const semantic_error& e) { s.print_error (e); } - rc |= emit_symbol_data (s); - s.op->line() << "\n"; delete s.op; |