summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfche <fche>2005-10-06 16:33:48 +0000
committerfche <fche>2005-10-06 16:33:48 +0000
commit33f88a80b716a37e6ef7b474622457906cc1f4f0 (patch)
treef786ef3895a14c572be4b11d36435f56f7916bf8
parent8714b4e52ce6efd60cefea1ca4421b426b5ddeec (diff)
downloadsystemtap-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--ChangeLog6
-rw-r--r--runtime/ChangeLog7
-rw-r--r--runtime/runtime.h68
-rw-r--r--runtime/sym.c4
-rw-r--r--runtime/sym.h25
-rw-r--r--translate.cxx72
6 files changed, 167 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index f806e3fe..6f13cbbb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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;
}