diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | runtime/transport/ChangeLog | 6 | ||||
-rw-r--r-- | runtime/transport/symbols.c | 23 | ||||
-rw-r--r-- | translate.cxx | 137 |
4 files changed, 138 insertions, 33 deletions
@@ -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); } |