summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Hunt <hunt@redhat.com>2008-04-09 11:32:50 -0400
committerMartin Hunt <hunt@redhat.com>2008-04-09 11:32:50 -0400
commitfa670082537aea7f090bc8dcfab69ac5f62546bc (patch)
tree85831b4fa3ec69d8db97e33a4b0a642d8eadb4fd
parent073b6ba57a498c3c97426f6f6d0666f1f5eb30d4 (diff)
downloadsystemtap-steved-fa670082537aea7f090bc8dcfab69ac5f62546bc.tar.gz
systemtap-steved-fa670082537aea7f090bc8dcfab69ac5f62546bc.tar.xz
systemtap-steved-fa670082537aea7f090bc8dcfab69ac5f62546bc.zip
Change stap to get kernel symbols from debuginfo and
compile them into the module.
-rw-r--r--ChangeLog5
-rw-r--r--runtime/transport/ChangeLog6
-rw-r--r--runtime/transport/symbols.c23
-rw-r--r--translate.cxx137
4 files changed, 138 insertions, 33 deletions
diff --git a/ChangeLog b/ChangeLog
index 8eb41250..d193233b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2008-04-09 Martin Hunt <hunt@dragon>
+
+ * translate.cxx (emit_symbol_data): When available,
+ grab symbols from debuginfo instead of /proc/kallsyms.
+
2008-03-31 Frank Ch. Eigler <fche@elastic.org>
* configure.ac: Bump version to 0.7.
diff --git a/runtime/transport/ChangeLog b/runtime/transport/ChangeLog
index 0bb62497..b3a159e3 100644
--- a/runtime/transport/ChangeLog
+++ b/runtime/transport/ChangeLog
@@ -1,3 +1,9 @@
+2008-04-09 Martin Hunt <hunt@dragon>
+
+ * symbols.c (_stp_init_kernel_symbols): Print error
+ messages and exit if symbol lookups fail.
+ (_stp_init_modules): Lookup modules_op.
+
2008-03-31 Martin Hunt <hunt@redhat.com>
* symbols.c (_stp_init_modules): Use STP_USE_DWARF_UNWINDER.
diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c
index 8bab1e70..b0e7c319 100644
--- a/runtime/transport/symbols.c
+++ b/runtime/transport/symbols.c
@@ -187,8 +187,8 @@ static int _stp_init_kernel_symbols(void)
{
_stp_modules[0] = (struct _stp_module *)_stp_kzalloc(sizeof(struct _stp_module));
if (_stp_modules[0] == NULL) {
- errk("cannot allocate memory\n");
- return -EFAULT;
+ _dbug("cannot allocate memory\n");
+ return -1;
}
_stp_modules[0]->symbols = _stp_kernel_symbols;
_stp_modules[0]->num_symbols = _stp_num_kernel_symbols;
@@ -197,11 +197,21 @@ static int _stp_init_kernel_symbols(void)
/* Note: this mapping is used by kernel/_stext pseudo-relocations. */
_stp_modules[0]->text = _stp_kallsyms_lookup_name("_stext");
+ if (_stp_modules[0]->text == 0) {
+ _dbug("Lookup of _stext failed. Exiting.\n");
+ return -1;
+ }
_stp_modules[0]->data = _stp_kallsyms_lookup_name("_etext");
+ if (_stp_modules[0]->data == 0) {
+ _dbug("Lookup of _etext failed. Exiting.\n");
+ return -1;
+ }
_stp_modules[0]->text_size = _stp_modules[0]->data - _stp_modules[0]->text;
_stp_modules_by_addr[0] = _stp_modules[0];
_stp_kretprobe_trampoline = _stp_kallsyms_lookup_name("kretprobe_trampoline");
+ /* Lookup failure is not fatal */
+
return 0;
}
@@ -559,14 +569,19 @@ static struct notifier_block _stp_module_load_nb = {
};
#include <linux/seq_file.h>
-extern unsigned long _stp_modules_op; /* from stap */
+
static int _stp_init_modules(void)
{
loff_t pos = 0;
void *res;
struct module *mod;
+ const struct seq_operations *modules_op = (const struct seq_operations *)_stp_kallsyms_lookup_name("modules_op");
+
+ if (modules_op == NULL) {
+ _dbug("Lookup of modules_op failed.\n");
+ return -1;
+ }
- const struct seq_operations *modules_op = (const struct seq_operations *)_stp_modules_op;
/* Use the seq_file interface to safely get a list of installed modules */
res = modules_op->start(NULL, &pos);
while (res) {
diff --git a/translate.cxx b/translate.cxx
index baa64741..dc6dd9f8 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -4356,45 +4356,124 @@ c_unparser::visit_hist_op (hist_op*)
assert(false);
}
+
+static map< Dwarf_Addr, string> addrmap;
+
+static int
+kernel_filter (const char *module, const char *file __attribute__((unused)))
+{
+ return !strcmp(module,"kernel");
+}
+
+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)
+ {
+ 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;
+}
+
+int
+emit_symbol_data_from_debuginfo(systemtap_session& s, ofstream& kallsyms_out)
+{
+ static char debuginfo_path_arr[] = "-:.debug:/usr/lib/debug";
+ 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 =
+ {
+ 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;
+
+ 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++;
+ }
+
+ kallsyms_out << "};\n";
+ kallsyms_out << "unsigned _stp_num_kernel_symbols = " << dec << i << ";\n";
+ return i == 0;
+}
+
int
emit_symbol_data (systemtap_session& s)
{
- // Instead of processing elf symbol tables, for now we just snatch
- // /proc/kallsyms and convert it to our use.
-
unsigned i=0;
- ifstream kallsyms("/proc/kallsyms");
char kallsyms_outbuf [4096];
ofstream kallsyms_out ((s.tmpdir + "/stap-symbols.h").c_str());
kallsyms_out.rdbuf()->pubsetbuf (kallsyms_outbuf,
- sizeof(kallsyms_outbuf));
-
+ sizeof(kallsyms_outbuf));
s.op->newline() << "\n\n#include \"stap-symbols.h\"";
- kallsyms_out << "struct _stp_symbol _stp_kernel_symbols [] = {";
- string lastaddr, modules_op_addr;
-
- 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") && lastaddr != addr)
- {
- kallsyms_out << " { 0x" << addr << ", " << "\"" << sym << "\" },\n";
- lastaddr = addr;
- i ++;
- }
- else if (sym == "modules_op")
- modules_op_addr = addr;
- }
- kallsyms_out << "};\n";
- kallsyms_out << "unsigned _stp_num_kernel_symbols = " << i << ";\n";
- kallsyms_out << "unsigned long _stp_modules_op = 0x" << modules_op_addr << ";\n";
+ // 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);
}