summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2008-07-17 06:42:45 -0400
committerFrank Ch. Eigler <fche@elastic.org>2008-07-17 06:42:45 -0400
commit7795c7e74987876f71fe85ab9119b8810e8897f0 (patch)
tree44761281ec3f8752b3adc055448945ef600e880c /runtime
parent4464a6bb1793076b3fa85a25c5a489cd9ef7d367 (diff)
downloadsystemtap-steved-7795c7e74987876f71fe85ab9119b8810e8897f0.tar.gz
systemtap-steved-7795c7e74987876f71fe85ab9119b8810e8897f0.tar.xz
systemtap-steved-7795c7e74987876f71fe85ab9119b8810e8897f0.zip
support multiple-relocatable-section modules such as hypothetical -ffunction-sections .ko's
Diffstat (limited to 'runtime')
-rw-r--r--runtime/ChangeLog7
-rw-r--r--runtime/sym.c101
-rw-r--r--runtime/sym.h30
-rw-r--r--runtime/transport/ChangeLog4
-rw-r--r--runtime/transport/symbols.c25
5 files changed, 75 insertions, 92 deletions
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index 4fe2d033..025a7b86 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,10 @@
+2008-07-17 Frank Ch. Eigler <fche@elastic.org>
+
+ * sym.c (_stp_kallsyms_lookup, _stp_module_relocate): Add
+ multiple-section-per-module support.
+ * sym.h (_stp_section): New type for separately relocatable
+ _stp_module pieces.
+
2008-07-12 Frank Ch. Eigler <fche@elastic.org>
PR 6738.
diff --git a/runtime/sym.c b/runtime/sym.c
index 178c6219..dcdbaf69 100644
--- a/runtime/sym.c
+++ b/runtime/sym.c
@@ -20,10 +20,11 @@
* @{
*/
+/* XXX: this needs to be address-space-specific. */
unsigned long _stp_module_relocate(const char *module, const char *section, unsigned long offset)
{
static struct _stp_module *last = NULL;
- static struct _stp_symbol *last_sec;
+ static struct _stp_section *last_sec;
unsigned long flags;
unsigned i, j;
@@ -42,7 +43,7 @@ unsigned long _stp_module_relocate(const char *module, const char *section, unsi
/* Most likely our relocation is in the same section of the same module as the last. */
if (last) {
- if (!strcmp(module, last->name) && !strcmp(section, last_sec->symbol)) {
+ if (!strcmp(module, last->name) && !strcmp(section, last_sec->name)) {
offset += last_sec->addr;
dbug_sym(1, "cached address=%lx\n", offset);
return offset;
@@ -55,7 +56,7 @@ unsigned long _stp_module_relocate(const char *module, const char *section, unsi
continue;
for (j = 0; j < last->num_sections; j++) {
last_sec = &last->sections[j];
- if (!strcmp(section, last_sec->symbol)) {
+ if (!strcmp(section, last_sec->name)) {
if (last_sec->addr == 0) /* module/section not in memory */
continue;
@@ -72,73 +73,69 @@ unsigned long _stp_module_relocate(const char *module, const char *section, unsi
}
-/* Return the module that likely contains the given address. */
-/* XXX: This query only makes sense with respect to a particular
- address space. A more general interface would have to identify
- the address space, and also pass back the section. */
-static struct _stp_module *_stp_find_module_by_addr(unsigned long addr)
-{
- unsigned i;
- struct _stp_module *closest_module = NULL;
- unsigned long closest_module_offset = ~0; /* minimum[addr - module->.text] */
-
- for (i=0; i<_stp_num_modules; i++)
- {
- unsigned long module_text_addr, this_module_offset;
-
- if (_stp_modules[i]->num_sections < 1) continue;
- module_text_addr = _stp_modules[i]->sections[0].addr; /* XXX: assume section[0]=>text */
- if (addr < module_text_addr) continue;
- this_module_offset = module_text_addr - addr;
-
- if (this_module_offset < closest_module_offset)
- {
- closest_module = _stp_modules[i];
- closest_module_offset = this_module_offset;
- }
- }
-
- return closest_module;
-}
-
-
-
+/* XXX: needs to be address-space-specific. */
static const char *_stp_kallsyms_lookup(unsigned long addr, unsigned long *symbolsize,
- unsigned long *offset, char **modname, char *namebuf)
+ unsigned long *offset,
+ const char **modname,
+ /* char ** secname? */
+ char *namebuf)
{
- struct _stp_module *m;
- struct _stp_symbol *s;
+ struct _stp_module *m = NULL;
+ struct _stp_section *sec = NULL;
+ struct _stp_symbol *s = NULL;
unsigned long flags;
unsigned end, begin = 0;
- m = _stp_find_module_by_addr(addr);
- if (unlikely(m == NULL)) {
- return NULL;
- }
-
- /* NB: relativize the address to the (XXX) presumed text section. */
- addr -= m->sections[0].addr;
- end = m->num_symbols;
+ /* Find the closest section (and its owner module); fill in m & sec. */
+ {
+ unsigned midx = 0;
+ unsigned long closest_section_offset = ~0;
+ for (midx = 0; midx < _stp_num_modules; midx++)
+ {
+ unsigned secidx;
+ for (secidx = 0; secidx < _stp_modules[midx]->num_sections; secidx++)
+ {
+ unsigned long this_section_addr = _stp_modules[midx]->sections[secidx].addr;
+ unsigned long this_section_offset;
+ if (addr < this_section_addr) continue;
+ this_section_offset = this_section_addr - addr;
+ if (this_section_offset < closest_section_offset)
+ {
+ closest_section_offset = this_section_offset;
+ m = _stp_modules[midx];
+ sec = & m->sections[secidx];
+ }
+ }
+ }
+ }
+
+ if (unlikely (m == NULL || sec == NULL))
+ return NULL;
+
+ /* NB: relativize the address to the section. */
+ addr -= sec->addr;
+ end = sec->num_symbols;
/* binary search for symbols within the module */
do {
unsigned mid = (begin + end) / 2;
- if (addr < m->symbols[mid].addr)
+ if (addr < sec->symbols[mid].addr)
end = mid;
else
begin = mid;
} while (begin + 1 < end);
/* result index in $begin */
- s = &m->symbols[begin];
+ s = & sec->symbols[begin];
if (likely(addr >= s->addr)) {
if (offset)
*offset = addr - s->addr;
if (modname)
*modname = m->name;
+ /* We could also pass sec->name here. */
if (symbolsize) {
- if ((begin + 1) < m->num_symbols)
- *symbolsize = m->symbols[begin + 1].addr - s->addr;
+ if ((begin + 1) < sec->num_symbols)
+ *symbolsize = sec->symbols[begin + 1].addr - s->addr;
else
*symbolsize = 0;
// NB: This is only a heuristic. Sometimes there are large
@@ -163,7 +160,7 @@ static const char *_stp_kallsyms_lookup(unsigned long addr, unsigned long *symbo
void _stp_symbol_print(unsigned long address)
{
- char *modname;
+ const char *modname;
const char *name;
unsigned long offset, size;
@@ -182,7 +179,7 @@ void _stp_symbol_print(unsigned long address)
/* Like _stp_symbol_print, except only print if the address is a valid function address */
int _stp_func_print(unsigned long address, int verbose, int exact)
{
- char *modname;
+ const char *modname;
const char *name;
unsigned long offset, size;
char *exstr;
@@ -210,7 +207,7 @@ int _stp_func_print(unsigned long address, int verbose, int exact)
void _stp_symbol_snprint(char *str, size_t len, unsigned long address)
{
- char *modname;
+ const char *modname;
const char *name;
unsigned long offset, size;
diff --git a/runtime/sym.h b/runtime/sym.h
index c7caacae..b2fb8ee9 100644
--- a/runtime/sym.h
+++ b/runtime/sym.h
@@ -10,28 +10,30 @@
#ifndef _STP_SYM_H_
#define _STP_SYM_H_
-#define STP_MODULE_NAME_LEN 64
-
struct _stp_symbol {
unsigned long addr;
const char *symbol;
};
+struct _stp_section {
+ const char *name;
+ unsigned long addr; /* XXX: belongs in per-address-space tables */
+ struct _stp_symbol *symbols; /* ordered by address */
+ unsigned num_symbols;
+};
+
+
struct _stp_module {
- /* the module name, or "" for kernel */
- char name[STP_MODULE_NAME_LEN];
-
+ const char* name;
+ struct _stp_section *sections;
+ unsigned num_sections;
+
/* A pointer to the struct module. Note that we cannot */
/* trust this because as of 2.6.19, there are not yet */
/* any notifier hooks that will tell us when a module */
/* is unloading. */
unsigned long module; /* XXX: why not struct module * ? */
- struct _stp_symbol *sections;
- unsigned num_sections;
- struct _stp_symbol *symbols; /* ordered by address */
- unsigned num_symbols;
-
/* the stack unwind data for this module */
void *unwind_data;
void *unwind_hdr;
@@ -43,13 +45,8 @@ struct _stp_module {
/* Defined by translator-generated stap-symbols.h. */
struct _stp_module *_stp_modules [];
-int _stp_num_modules;
-
+unsigned _stp_num_modules;
-#if 0
-/* the array of modules ordered by addresses */
-struct _stp_module *_stp_modules_by_addr[STP_MAX_MODULES];
-#endif
/* the number of modules in the arrays */
@@ -57,4 +54,5 @@ static unsigned long _stp_kretprobe_trampoline = 0;
unsigned long _stp_module_relocate (const char *module, const char *section, unsigned long offset);
static struct _stp_module *_stp_get_unwind_info (unsigned long addr);
+
#endif /* _STP_SYM_H_ */
diff --git a/runtime/transport/ChangeLog b/runtime/transport/ChangeLog
index f766e138..693f06d1 100644
--- a/runtime/transport/ChangeLog
+++ b/runtime/transport/ChangeLog
@@ -1,3 +1,7 @@
+2008-07-17 Frank Ch. Eigler <fche@elastic.org>
+
+ * symbols.c (_stp_do_relocation): Adapt to stp_module decl changes.
+
2008-07-12 Frank Ch. Eigler <fche@elastic.org>
PR 6738.
diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c
index c868c5fd..4bdd0904 100644
--- a/runtime/transport/symbols.c
+++ b/runtime/transport/symbols.c
@@ -53,7 +53,7 @@ static void _stp_do_relocation(const char __user *buf, size_t count)
for (si=0; si<_stp_modules[mi]->num_sections; si++)
{
- if (strcmp (_stp_modules[mi]->sections[si].symbol, msg.reloc))
+ if (strcmp (_stp_modules[mi]->sections[si].name, msg.reloc))
continue;
_stp_modules[mi]->sections[si].addr = msg.address;
@@ -62,29 +62,6 @@ static void _stp_do_relocation(const char __user *buf, size_t count)
}
-static int _stp_compare_addr(const void *p1, const void *p2)
-{
- struct _stp_symbol *s1 = (struct _stp_symbol *)p1;
- struct _stp_symbol *s2 = (struct _stp_symbol *)p2;
- if (s1->addr == s2->addr)
- return 0;
- if (s1->addr < s2->addr)
- return -1;
- return 1;
-}
-
-static void _stp_swap_symbol(void *x, void *y, int size)
-{
- struct _stp_symbol *a = (struct _stp_symbol *)x;
- struct _stp_symbol *b = (struct _stp_symbol *)y;
- unsigned long addr = a->addr;
- const char *symbol = a->symbol;
- a->addr = b->addr;
- a->symbol = b->symbol;
- b->addr = addr;
- b->symbol = symbol;
-}
-
static void u32_swap(void *a, void *b, int size)
{
u32 t = *(u32 *)a;