summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--elaborate.cxx4
-rw-r--r--runtime/ChangeLog5
-rw-r--r--runtime/sym.c50
-rw-r--r--runtime/transport/ChangeLog5
-rw-r--r--runtime/transport/symbols.c1
-rw-r--r--session.h11
-rw-r--r--tapsets.cxx113
-rw-r--r--translate.cxx3
9 files changed, 124 insertions, 80 deletions
diff --git a/ChangeLog b/ChangeLog
index 19318d35..1e277306 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2007-03-20 Frank Ch. Eigler <fche@elastic.org>
+
+ PR 4224.
+ * tapsets.cxx (add_probe_point): Make kernel implicitly relocated
+ relative to the _stext symbol.
+ (dwarf_derived_probe ctor, emit_module_decls): Cooperate.
+ (lookup_symbol_address): New function.
+ (dwarf_builder::build): Call it thrice.
+ (in_kprobes_function): Simplify.
+ * session.h (systemtap_session): Rename cached symbol addresses.
+ * translate.cxx, elaborate.cxx: Corresponding tweaks.
+
2007-03-19 David Smith <dsmith@redhat.com>
PR 4146 (partial fix)
diff --git a/elaborate.cxx b/elaborate.cxx
index ef019016..c2e57856 100644
--- a/elaborate.cxx
+++ b/elaborate.cxx
@@ -973,9 +973,7 @@ systemtap_session::systemtap_session ():
mark_derived_probes(0),
hrtimer_derived_probes(0),
perfmon_derived_probes(0),
- op (0), up (0),
- kprobes_text_initialized (false),
- kprobes_text_start (0), kprobes_text_end (0)
+ op (0), up (0)
{
}
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index 2b068b5c..4c714b01 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,8 @@
+2007-03-20 Frank Ch. Eigler <fche@elastic.org>
+
+ PR 4224.
+ * sym.c (_stp_module_relocate): Support kernel relocations.
+
2007-03-19 Frank Ch. Eigler <fche@elastic.org>
* autoconf-hrtimer-rel.c: New file.
diff --git a/runtime/sym.c b/runtime/sym.c
index a5bc0195..70efd82d 100644
--- a/runtime/sym.c
+++ b/runtime/sym.c
@@ -34,24 +34,44 @@ static unsigned long _stp_module_relocate (const char *module, const char *secti
if (last) {
if (!strcmp (module, last->name) && !strcmp (section, last_sec->symbol)) {
- STP_UNLOCK_MODULES;
- return offset + last_sec->addr;
+ /* XXX: But is this enough protection? What if the module `last' is
+ unloaded sometime between the last relocate call and this one? Do
+ the last/last_sec pointers become invalid to traverse like that? */
+ STP_UNLOCK_MODULES;
+ return offset + last_sec->addr;
}
}
/* need to scan all modules */
- for (i = 1; i < _stp_num_modules; i++) { /* XXX: why start at i=1? */
- last = _stp_modules[i];
- if (strcmp(module, last->name))
- continue;
- for (j = 0; j < (int)last->num_sections; j++) {
- last_sec = &last->sections[j];
- if (!strcmp (section, last_sec->symbol)) {
- STP_UNLOCK_MODULES;
- return offset + last_sec->addr;
- }
- }
- }
+ if (! strcmp (module, "kernel"))
+ {
+ STP_UNLOCK_MODULES;
+
+ /* See also transport/symbols.c (_stp_do_symbols). */
+ if (strcmp (section, "_stext"))
+ return 0;
+ else
+ return offset + _stp_modules[0]->text;
+
+ /* NB: we could also use _stp_kallsyms_lookup_name (section); */
+ /* If _stp_kallsyms_lookup_name also returned the symbol,
+ we could set last & last_sym and take some advantage of
+ caching. But OTOH the advantage would be tiny in comparison
+ to the hard-coded calculation above. */
+ }
+ else /* relocatable module */
+ for (i = 1; i < _stp_num_modules; i++) { /* skip over [0]=kernel */
+ last = _stp_modules[i];
+ if (strcmp(module, last->name))
+ continue;
+ for (j = 0; j < (int)last->num_sections; j++) {
+ last_sec = &last->sections[j];
+ if (!strcmp (section, last_sec->symbol)) {
+ STP_UNLOCK_MODULES;
+ return offset + last_sec->addr;
+ }
+ }
+ }
STP_UNLOCK_MODULES;
last = NULL;
return 0;
@@ -65,7 +85,7 @@ static unsigned long _stp_kallsyms_lookup_name(const char *name)
while (num--) {
if (strcmp(name, s->symbol) == 0)
- return s->addr;
+ return s->addr;
s++;
}
return 0;
diff --git a/runtime/transport/ChangeLog b/runtime/transport/ChangeLog
index dcee1d79..90661baf 100644
--- a/runtime/transport/ChangeLog
+++ b/runtime/transport/ChangeLog
@@ -1,3 +1,8 @@
+2007-03-20 Frank Ch. Eigler <fche@elastic.org>
+
+ * symbols.c (_stp_do_symbols): Add cautionary blurb for important
+ setup of _stp_modules[0]->text.
+
2007-03-20 Martin Hunt <hunt@redhat.com>
* symbols.c (_stp_alloc_module): Fix up error
diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c
index 9d5163d0..ee5e967e 100644
--- a/runtime/transport/symbols.c
+++ b/runtime/transport/symbols.c
@@ -203,6 +203,7 @@ static int _stp_do_symbols(const char __user *buf, int count)
for (i = 0; i < _stp_modules[0]->num_symbols; i++)
s[i].symbol += (long)_stp_modules[0]->symbol_data;
_stp_symbol_state = 3;
+ /* NB: this mapping is used by kernel/_stext pseudo-relocations. */
_stp_modules[0]->text = _stp_kallsyms_lookup_name("_stext");
_stp_modules_by_addr[0] = _stp_modules[0];
break;
diff --git a/session.h b/session.h
index 956d4394..7798b32f 100644
--- a/session.h
+++ b/session.h
@@ -93,7 +93,7 @@ struct systemtap_session
bool merge;
int buffer_size;
unsigned perfmon;
- bool symtab;
+ bool symtab; /* true: emit symbol table at translation time; false: let staprun do it. */
bool prologue_searching;
// Cache data
@@ -136,10 +136,11 @@ struct systemtap_session
translator_output* op;
unparser* up;
- // kprobes_text data
- bool kprobes_text_initialized;
- Dwarf_Addr kprobes_text_start;
- Dwarf_Addr kprobes_text_end;
+ // some symbol addresses
+ // XXX: these belong elsewhere; perhaps the dwflpp instance
+ Dwarf_Addr sym_kprobes_text_start;
+ Dwarf_Addr sym_kprobes_text_end;
+ Dwarf_Addr sym_stext;
std::set<std::string> seen_errors;
unsigned num_errors () { return seen_errors.size(); }
diff --git a/tapsets.cxx b/tapsets.cxx
index eb66f2bc..78d47dc7 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -2278,55 +2278,11 @@ static int query_kernel_module (Dwfl_Module *, void **, const char *,
static bool
in_kprobes_function(systemtap_session& sess, Dwarf_Addr addr)
{
- if (! sess.kprobes_text_initialized)
- {
- // Only attempt kprobes_text_start/kprobes_text_end
- // initialization once
- sess.kprobes_text_initialized = true;
-
- dwflpp *kernel_dw = new dwflpp(sess);
- assert(kernel_dw);
- kernel_dw->setup(true);
-
- Dwfl_Module *m = NULL;
- kernel_dw->iterate_over_modules(&query_kernel_module, &m);
- assert(m);
- kernel_dw->focus_on_module(m);
-
- // Look through the symbol table for "__kprobes_text_{start,end}"
- int syments = dwfl_module_getsymtab(kernel_dw->module);
- assert(syments);
- for (int i = 1; i < syments; ++i)
- {
- GElf_Sym sym;
- const char *name = dwfl_module_getsym(kernel_dw->module, i,
- &sym, NULL);
-
- // Look for a symbol that starts with "__kprobes_text_"
- if (name != NULL
- && strncmp(name, "__kprobes_text_", 15) == 0)
- {
- // Match either "__kprobes_text_start" or "__kprobes_text_end"
- if (strcmp(name, "__kprobes_text_start") == 0)
- sess.kprobes_text_start = sym.st_value;
- else if (strcmp(name, "__kprobes_text_end") == 0)
- sess.kprobes_text_end = sym.st_value;
-
- // If we've got both values, quit processing symbols.
- if (sess.kprobes_text_start != 0 && sess.kprobes_text_end != 0)
- i = syments;
- }
- }
-
- if (kernel_dw)
- delete kernel_dw;
- }
-
- if (sess.kprobes_text_start != 0 && sess.kprobes_text_end != 0)
+ if (sess.sym_kprobes_text_start != 0 && sess.sym_kprobes_text_end != 0)
{
// If the probe point address is anywhere in the __kprobes
// address range, we can't use this probe point.
- if (addr >= sess.kprobes_text_start && addr < sess.kprobes_text_end)
+ if (addr >= sess.sym_kprobes_text_start && addr < sess.sym_kprobes_text_end)
return true;
}
return false;
@@ -2455,6 +2411,13 @@ dwarf_query::add_probe_point(const string& funcname,
if (sess.verbose > 1)
clog << endl;
+ if (module == TOK_KERNEL)
+ {
+ // PR 4224: adapt to relocatable kernel by subtracting the _stext address here.
+ reloc_addr = addr - sess.sym_stext;
+ reloc_section = "_stext"; // a deliberate eyesore
+ }
+
if (! bad)
{
probe = new dwarf_derived_probe(funcname, filename, line,
@@ -2938,9 +2901,9 @@ query_module (Dwfl_Module *mod __attribute__ ((unused)),
if (q->sess.verbose>2)
clog << "focused on module '" << q->dw.module_name
- << " = [" << hex << q->dw.module_start
- << "-" << q->dw.module_end
- << ", bias " << q->dw.module_bias << "]" << dec
+ << " = [0x" << hex << q->dw.module_start
+ << "-0x" << q->dw.module_end
+ << ", bias 0x" << q->dw.module_bias << "]" << dec
<< " file " << debug_filename
<< " ELF machine " << expect_machine
<< " (code " << elf_machine << ")"
@@ -3495,11 +3458,9 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
maxactive_val (q.maxactive_val)
{
// Assert relocation invariants
- if (module == TOK_KERNEL && section != "")
- throw semantic_error ("relocation requested against kernel", q.base_loc->tok);
- if (module != TOK_KERNEL && section == "")
- throw semantic_error ("missing relocation base against module", q.base_loc->tok);
- if (module != TOK_KERNEL && section != "" && dwfl_addr == addr) // addr should be an offset
+ if (section == "")
+ throw semantic_error ("missing relocation base against", q.base_loc->tok);
+ if (section != "" && dwfl_addr == addr) // addr should be an offset
throw semantic_error ("inconsistent relocation address", q.base_loc->tok);
// Make a target-variable-expanded copy of the probe body
@@ -3734,9 +3695,9 @@ dwarf_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->line() << " .return_p=1,";
if (p->has_maxactive)
s.op->line() << " .maxactive_p=1,";
- if (p->module != TOK_KERNEL) // relocation info
- s.op->line() << " .module=\"" << p->module << "\", .section=\"" << p->section << "\",";
s.op->line() << " .address=0x" << hex << p->addr << dec << "UL,";
+ s.op->line() << " .module=\"" << p->module << "\",";
+ s.op->line() << " .section=\"" << p->section << "\",";
if (p->has_maxactive)
s.op->line() << " .maxactive_val=" << p->maxactive_val << "UL,";
s.op->line() << " .pp=" << lex_cast_qstring (*p->sole_location()) << ",";
@@ -3827,6 +3788,26 @@ dwarf_derived_probe_group::emit_module_exit (systemtap_session& s)
}
+
+static Dwarf_Addr
+lookup_symbol_address (Dwfl_Module *m, const char* wanted)
+{
+ 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 != NULL && strcmp(name, wanted) == 0)
+ return sym.st_value;
+ }
+
+ return 0;
+}
+
+
+
+
void
dwarf_builder::build(systemtap_session & sess,
probe * base,
@@ -3852,6 +3833,26 @@ dwarf_builder::build(systemtap_session & sess,
kern_dw->setup(true);
}
dw = kern_dw;
+
+
+ Dwfl_Module* km = 0;
+ dw->iterate_over_modules(&query_kernel_module, &km);
+ if (km)
+ {
+ sess.sym_kprobes_text_start = lookup_symbol_address (km, "__kprobes_text_start");
+ sess.sym_kprobes_text_end = lookup_symbol_address (km, "__kprobes_text_end");
+ sess.sym_stext = lookup_symbol_address (km, "_stext");
+
+ if (sess.verbose > 2)
+ {
+ clog << "control symbols:"
+ // abbreviate the names - they're for our debugging only anyway
+ << " kts: 0x" << hex << sess.sym_kprobes_text_start
+ << " kte: 0x" << sess.sym_kprobes_text_end
+ << " stext: 0x" << sess.sym_stext
+ << dec << endl;
+ }
+ }
}
else
{
diff --git a/translate.cxx b/translate.cxx
index 89a961e3..d3f9467a 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -3986,8 +3986,9 @@ emit_symbol_data (systemtap_session& s)
if (s.symtab == false)
{
+ s.op->newline() << "/* filled in by runtime */";
s.op->newline() << "struct stap_symbol *stap_symbols;";
- s.op->newline() << "unsigned stap_num_symbols = 0;\n";
+ s.op->newline() << "unsigned stap_num_symbols;\n";
return 0;
}