diff options
author | Frank Ch. Eigler <fche@elastic.org> | 2008-07-17 06:42:45 -0400 |
---|---|---|
committer | Frank Ch. Eigler <fche@elastic.org> | 2008-07-17 06:42:45 -0400 |
commit | 7795c7e74987876f71fe85ab9119b8810e8897f0 (patch) | |
tree | 44761281ec3f8752b3adc055448945ef600e880c /runtime | |
parent | 4464a6bb1793076b3fa85a25c5a489cd9ef7d367 (diff) | |
download | systemtap-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/ChangeLog | 7 | ||||
-rw-r--r-- | runtime/sym.c | 101 | ||||
-rw-r--r-- | runtime/sym.h | 30 | ||||
-rw-r--r-- | runtime/transport/ChangeLog | 4 | ||||
-rw-r--r-- | runtime/transport/symbols.c | 25 |
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; |