diff options
author | fche <fche> | 2005-10-06 16:33:48 +0000 |
---|---|---|
committer | fche <fche> | 2005-10-06 16:33:48 +0000 |
commit | 33f88a80b716a37e6ef7b474622457906cc1f4f0 (patch) | |
tree | f786ef3895a14c572be4b11d36435f56f7916bf8 | |
parent | 8714b4e52ce6efd60cefea1ca4421b426b5ddeec (diff) | |
download | systemtap-steved-33f88a80b716a37e6ef7b474622457906cc1f4f0.tar.gz systemtap-steved-33f88a80b716a37e6ef7b474622457906cc1f4f0.tar.xz systemtap-steved-33f88a80b716a37e6ef7b474622457906cc1f4f0.zip |
2005-10-06 Frank Ch. Eigler <fche@elastic.org>
PR 1332.
* translate.cxx (emit_symbol_data): New function to transcribe
a processed address->symbol lookup table, based upon /proc/kallsyms.
2005-10-06 Frank Ch. Eigler <fche@elastic.org>
PR 1332.
* sym.h: New file to declare explicit symbol table struct.
* runtime.h (_stp_kallsyms_lookup_tabled): Use it if available.
* sym.c (_stp_symbol_sprint): HAS_LOOKUP mooted.
2005-10-06 Frank Ch. Eigler <fche@elastic.org>
PR 1132.
* systemtap.samples/symbols.*: New test.
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | runtime/ChangeLog | 7 | ||||
-rw-r--r-- | runtime/runtime.h | 68 | ||||
-rw-r--r-- | runtime/sym.c | 4 | ||||
-rw-r--r-- | runtime/sym.h | 25 | ||||
-rw-r--r-- | translate.cxx | 72 |
6 files changed, 167 insertions, 15 deletions
@@ -1,3 +1,9 @@ +2005-10-06 Frank Ch. Eigler <fche@elastic.org> + + PR 1332. + * translate.cxx (emit_symbol_data): New function to transcribe + a processed address->symbol lookup table, based upon /proc/kallsyms. + 2005-10-05 Tom Zanussi <zanussi@us.ibm.com> * buildrun.cxx (run_pass): Add bulk/buffer_size flags to flags diff --git a/runtime/ChangeLog b/runtime/ChangeLog index 548f908e..196d9486 100644 --- a/runtime/ChangeLog +++ b/runtime/ChangeLog @@ -1,3 +1,10 @@ +2005-10-06 Frank Ch. Eigler <fche@elastic.org> + + PR 1332. + * sym.h: New file to declare explicit symbol table struct. + * runtime.h (_stp_kallsyms_lookup_tabled): Use it if available. + * sym.c (_stp_symbol_sprint): HAS_LOOKUP mooted. + 2005-09-30 Graydon Hoare <graydon@redhat.com> * loc2c-runtime.h (_put_user_asm): Fix bracket-matching. diff --git a/runtime/runtime.h b/runtime/runtime.h index 94a210a6..bcee85d5 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -60,29 +60,79 @@ static struct #include "string.c" #include "arith.c" #include "copy.c" +#include "sym.h" + /************* Module Stuff ********************/ -#if defined (__x86_64__) || defined (__i386__) -#define HAS_LOOKUP 1 static int (*_stp_kta)(unsigned long addr); static const char * (*_stp_kallsyms_lookup)(unsigned long addr, unsigned long *symbolsize, unsigned long *offset, char **modname, char *namebuf); -int init_module (void) + +/* This implementation is used if stap_[num_]symbols are available. */ +static const char * _stp_kallsyms_lookup_tabled (unsigned long addr, + unsigned long *symbolsize, + unsigned long *offset, + char **modname, + char *namebuf) { - _stp_kta = (int (*)(unsigned long))kallsyms_lookup_name("__kernel_text_address"); - _stp_kallsyms_lookup = (const char * (*)(unsigned long,unsigned long *,unsigned long *,char **,char *)) - kallsyms_lookup_name("kallsyms_lookup"); - return _stp_transport_init(); + unsigned begin = 0; + unsigned end = stap_num_symbols; + /*const*/ struct stap_symbol* s; + + /* binary search on index [begin,end) */ + do + { + unsigned mid = (begin + end) / 2; + if (addr < stap_symbols[mid].addr) + end = mid; + else + begin = mid; + } while (begin + 1 < end); + /* result index in $begin, guaranteed between [0,stap_num_symbols) */ + + s = & stap_symbols [begin]; + if (addr < s->addr) + return NULL; + else + { + if (offset) *offset = addr - s->addr; + if (modname) *modname = (char *) s->modname; + if (symbolsize) + { + if ((begin + 1) < stap_num_symbols) + *symbolsize = stap_symbols[begin+1].addr - s->addr; + else + *symbolsize = 0; + // NB: This is only a heuristic. Sometimes there are large + // gaps between text areas of modules. + } + if (namebuf) + { + strlcpy (namebuf, s->symbol, KSYM_NAME_LEN+1); + return namebuf; + } + else + return s->symbol; + } } -#else + + + int init_module (void) { + _stp_kta = (int (*)(unsigned long))kallsyms_lookup_name("__kernel_text_address"); + + if (stap_num_symbols > 0) + _stp_kallsyms_lookup = & _stp_kallsyms_lookup_tabled; + else + _stp_kallsyms_lookup = (const char * (*)(unsigned long,unsigned long *,unsigned long *,char **,char *)) + kallsyms_lookup_name("kallsyms_lookup"); + return _stp_transport_init(); } -#endif int probe_start(void); diff --git a/runtime/sym.c b/runtime/sym.c index 344df373..6e686051 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -18,7 +18,6 @@ String _stp_symbol_sprint (String str, unsigned long address) { -#ifdef HAS_LOOKUP char *modname; const char *name; unsigned long offset, size; @@ -34,9 +33,6 @@ String _stp_symbol_sprint (String str, unsigned long address) else _stp_sprintf (str, " : %s+%#lx/%#lx", name, offset, size); } -#else - _stp_sprintf (str, "0x%lx", address); -#endif return str; } diff --git a/runtime/sym.h b/runtime/sym.h new file mode 100644 index 00000000..6ed08b06 --- /dev/null +++ b/runtime/sym.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2005 Red Hat Inc. + * + * This file is part of systemtap, and is free software. You can + * redistribute it and/or modify it under the terms of the GNU General + * Public License (GPL); either version 2, or (at your option) any + * later version. + */ + +#ifndef _STAP_SYMBOLS_H_ +#define _STAP_SYMBOLS_H_ + + +/* A symbol table defined by the translator. */ +struct stap_symbol { + unsigned long addr; + const char *symbol; + const char *modname; +}; + +extern struct stap_symbol stap_symbols []; +extern unsigned stap_num_symbols; + + +#endif /* _RUNTIME_H_ */ diff --git a/translate.cxx b/translate.cxx index a7caf0bd..981d71df 100644 --- a/translate.cxx +++ b/translate.cxx @@ -2362,6 +2362,72 @@ c_unparser::visit_functioncall (functioncall* e) } + +int +emit_symbol_data (systemtap_session& s) +{ + int rc = 0; + + // 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. All that LC_ALL=C stuff is there to avoid the + // excessive penalty of i18n code in some glibc/coreutils versions. + + string sorted_kallsyms = s.tmpdir + "/symbols.sorted"; + string sortcmd = "/bin/env LC_ALL=C /bin/grep \" [tT] \" /proc/kallsyms | "; + + sortcmd += "/bin/env LC_ALL=C /bin/sort "; +#if __LP64__ + sortcmd += "-k 1,16 "; +#else + sortcmd += "-k 1,8 "; +#endif + sortcmd += "-s -o " + sorted_kallsyms; + + if (s.verbose) clog << "Running " << sortcmd << endl; + rc = system(sortcmd.c_str()); + if (rc == 0) + { + ifstream kallsyms (sorted_kallsyms.c_str()); + + unsigned i=0; + s.op->newline() << "struct stap_symbol stap_symbols [] = {"; + s.op->indent(1); + 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") && lastaddr != addr) + { + s.op->newline() << "{ 0x" << addr << ", " + << "\"" << sym << "\", " + << "\"" << module << "\" },"; + lastaddr = addr; + i ++; + } + } + s.op->newline(-1) << "};"; + s.op->newline() << "unsigned stap_num_symbols = " << i << ";" << endl; + } + + return rc; +} + + int translate_pass (systemtap_session& s) { @@ -2468,16 +2534,18 @@ translate_pass (systemtap_session& s) s.op->newline() << "MODULE_DESCRIPTION(\"systemtap probe\");"; s.op->newline() << "MODULE_LICENSE(\"GPL\");"; // XXX s.op->newline() << "#endif"; - - s.op->line() << endl; } catch (const semantic_error& e) { s.print_error (e); } + rc |= emit_symbol_data (s); + s.op->line() << endl; + delete s.op; s.op = 0; s.up = 0; + return rc + s.num_errors; } |