summaryrefslogtreecommitdiffstats
path: root/translate.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'translate.cxx')
-rw-r--r--translate.cxx188
1 files changed, 113 insertions, 75 deletions
diff --git a/translate.cxx b/translate.cxx
index 6aef37f0..1782abd1 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -849,6 +849,7 @@ translator_output::line ()
void
c_unparser::emit_common_header ()
{
+ o->newline();
o->newline() << "typedef char string_t[MAXSTRINGLEN];";
o->newline();
o->newline() << "#define STAP_SESSION_STARTING 0";
@@ -4359,83 +4360,127 @@ c_unparser::visit_hist_op (hist_op*)
assert(false);
}
-int
-emit_symbol_data (systemtap_session& s)
+
+static map< Dwarf_Addr, string> addrmap;
+
+#include <string.h>
+
+static int
+kernel_filter (const char *module, const char *file __attribute__((unused)))
{
- int rc = 0;
+ return !strcmp(module,"kernel");
+}
- // Instead of processing elf symbol tables, for now we just snatch
- // /proc/kallsyms and convert it to our use. We need it sorted by
- // address (so we can binary search) , and filtered (to show text
- // symbols only), a task that we defer to grep(1) and sort(1). It
- // may be useful to cache the symbols.sorted file, perhaps indexed
- // by md5sum(/proc/modules), but let's not until this simple method
- // proves too costly. LC_ALL=C is already set to avoid the
- // excessive penalty of i18n code in some glibc/coreutils versions.
-
- string sorted_kallsyms = s.tmpdir + "/symbols.sorted";
- string sortcmd = "grep \" [AtT] \" /proc/kallsyms | ";
-
- if (s.symtab == false)
+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)))
+{
+ int syments = dwfl_module_getsymtab(m);
+ assert(syments);
+ for (int i = 1; i < syments; ++i)
{
- s.op->newline() << "/* filled in by runtime */";
- s.op->newline() << "struct stap_symbol *stap_symbols;";
- s.op->newline() << "unsigned stap_num_symbols;\n";
- return 0;
+ 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;
+ }
}
+ return DWARF_CB_OK;
+}
- sortcmd += "sort ";
-#if __LP64__
- sortcmd += "-k 1,16 ";
-#else
- sortcmd += "-k 1,8 ";
-#endif
- sortcmd += "-s -o " + sorted_kallsyms;
-
- if (s.verbose>1) clog << "Running " << sortcmd << endl;
- rc = system(sortcmd.c_str());
- if (rc == 0)
+int
+emit_symbol_data_from_debuginfo(systemtap_session& s, ofstream& kallsyms_out)
+{
+ 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);
+
+ static const Dwfl_Callbacks kernel_callbacks =
{
- ifstream kallsyms (sorted_kallsyms.c_str());
- char kallsyms_outbuf [4096];
- ofstream kallsyms_out ((s.tmpdir + "/stap-symbols.h").c_str());
- kallsyms_out.rdbuf()->pubsetbuf (kallsyms_outbuf,
- sizeof(kallsyms_outbuf));
+ dwfl_linux_kernel_find_elf,
+ dwfl_standard_find_debuginfo,
+ dwfl_offline_section_address,
+ & debuginfo_path
+ };
+
+ 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,
+ s.kernel_release.c_str(),
+ kernel_filter);
+ dwfl_report_end (dwfl, NULL, NULL);
+ if (rc < 0)
+ return rc;
- s.op->newline() << "\n\n#include \"stap-symbols.h\"";
+ dwfl_getmodules (dwfl, &get_symbols, NULL, 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++;
+ }
- unsigned i=0;
- kallsyms_out << "struct stap_symbol _stp_stap_symbols [] = {";
- string lastaddr;
- while (! kallsyms.eof())
- {
- string addr, type, sym, module;
- kallsyms >> addr >> type >> sym;
- kallsyms >> ws;
- if (kallsyms.peek() == '[')
- {
- string bracketed;
- kallsyms >> bracketed;
- module = bracketed.substr (1, bracketed.length()-2);
- }
-
- // NB: kallsyms includes some duplicate addresses
- if ((type == "t" || type == "T" || type == "A") && lastaddr != addr)
- {
- kallsyms_out << " { 0x" << addr << ", "
- << "\"" << sym << "\", "
- << "\"" << module << "\" },"
- << "\n";
- lastaddr = addr;
- i ++;
- }
- }
kallsyms_out << "};\n";
- kallsyms_out << "struct stap_symbol *stap_symbols = _stp_stap_symbols;";
- kallsyms_out << "unsigned stap_num_symbols = " << i << ";\n";
- }
+ kallsyms_out << "unsigned _stp_num_kernel_symbols = " << dec << i << ";\n";
+ return i == 0;
+}
- return rc;
+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);
}
@@ -4452,9 +4497,6 @@ translate_pass (systemtap_session& s)
{
// This is at the very top of the file.
- // XXX: the runtime uses #ifdef TEST_MODE to infer systemtap usage.
- s.op->line() << "#define TEST_MODE 0\n";
-
s.op->newline() << "#ifndef MAXNESTING";
s.op->newline() << "#define MAXNESTING 10";
s.op->newline() << "#endif";
@@ -4521,16 +4563,12 @@ translate_pass (systemtap_session& s)
s.op->newline() << "#include <linux/random.h>";
s.op->newline() << "#include <linux/utsname.h>";
s.op->newline() << "#include \"loc2c-runtime.h\" ";
-
+
// XXX: old 2.6 kernel hack
s.op->newline() << "#ifndef read_trylock";
s.op->newline() << "#define read_trylock(x) ({ read_lock(x); 1; })";
s.op->newline() << "#endif";
- s.op->newline() << "#if defined(CONFIG_MARKERS)";
- s.op->newline() << "#include <linux/marker.h>";
- s.op->newline() << "#endif";
-
s.up->emit_common_header (); // context etc.
for (unsigned i=0; i<s.embeds.size(); i++)