diff options
Diffstat (limited to 'translate.cxx')
-rw-r--r-- | translate.cxx | 184 |
1 files changed, 112 insertions, 72 deletions
diff --git a/translate.cxx b/translate.cxx index ba848d43..1b812ec1 100644 --- a/translate.cxx +++ b/translate.cxx @@ -849,10 +849,6 @@ translator_output::line () void c_unparser::emit_common_header () { - vector<derived_probe_group*> g = all_session_groups (*session); - for (unsigned i=0; i<g.size(); i++) - g[i]->emit_module_header (*session); - o->newline(); o->newline() << "typedef char string_t[MAXSTRINGLEN];"; o->newline(); @@ -4363,83 +4359,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"; + 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); - s.op->newline() << "\n\n#include \"stap-symbols.h\""; + 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++; + } - 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); } @@ -4525,7 +4565,7 @@ 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; })"; |