summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog1
-rw-r--r--main.cxx17
-rw-r--r--runtime/transport/ChangeLog3
-rw-r--r--session.h3
-rw-r--r--tapsets.cxx8
-rw-r--r--translate.cxx195
6 files changed, 131 insertions, 96 deletions
diff --git a/ChangeLog b/ChangeLog
index 2777fce3..4b1b25b0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
diff --git a/main.cxx b/main.cxx
index 58d7fa9f..23ab3b2f 100644
--- a/main.cxx
+++ b/main.cxx
@@ -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>
diff --git a/session.h b/session.h
index 58bc7ac5..734c8d7d 100644
--- a/session.h
+++ b/session.h
@@ -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;