diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/staprun/common.c | 25 | ||||
-rw-r--r-- | runtime/staprun/mainloop.c | 23 | ||||
-rw-r--r-- | runtime/staprun/staprun.c | 102 | ||||
-rw-r--r-- | runtime/staprun/staprun.h | 1 | ||||
-rw-r--r-- | runtime/sym.c | 11 | ||||
-rw-r--r-- | runtime/transport/control.c | 7 | ||||
-rw-r--r-- | runtime/transport/symbols.c | 63 | ||||
-rw-r--r-- | runtime/transport/transport.c | 3 | ||||
-rw-r--r-- | runtime/transport/transport_msgs.h | 11 |
9 files changed, 196 insertions, 50 deletions
diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c index 93da51d8..dca45e4d 100644 --- a/runtime/staprun/common.c +++ b/runtime/staprun/common.c @@ -314,3 +314,28 @@ err: close(fd); return -1; } + + +/** + * send_request - send request to kernel over control channel + * @type: the relay-app command id + * @data: pointer to the data to be sent + * @len: length of the data to be sent + * + * Returns 0 on success, negative otherwise. + * XXX: no, it doesn't ... it should return @len on success. + */ +int send_request(int type, void *data, int len) +{ + char buf[1024]; + + /* Before doing memcpy, make sure 'buf' is big enough. */ + if ((len + 4) > (int)sizeof(buf)) { + _err("exceeded maximum send_request size.\n"); + return -1; + } + memcpy(buf, &type, 4); + memcpy(&buf[4], data, len); + + return write(control_channel, buf, len + 4); +} diff --git a/runtime/staprun/mainloop.c b/runtime/staprun/mainloop.c index 2bbadbc9..42037473 100644 --- a/runtime/staprun/mainloop.c +++ b/runtime/staprun/mainloop.c @@ -19,27 +19,6 @@ static int use_old_transport = 0; //enum _stp_sig_type { sig_none, sig_done, sig_detach }; //static enum _stp_sig_type got_signal = sig_none; -/** - * send_request - send request to kernel over control channel - * @type: the relay-app command id - * @data: pointer to the data to be sent - * @len: length of the data to be sent - * - * Returns 0 on success, negative otherwise. - */ -int send_request(int type, void *data, int len) -{ - char buf[1024]; - - /* Before doing memcpy, make sure 'buf' is big enough. */ - if ((len + 4) > (int)sizeof(buf)) { - _err("exceeded maximum send_request size.\n"); - return -1; - } - memcpy(buf, &type, 4); - memcpy(&buf[4], data, len); - return write(control_channel, buf, len + 4); -} static void *signal_thread(void *arg) { @@ -308,8 +287,8 @@ int stp_main_loop(void) setvbuf(ofp, (char *)NULL, _IOLBF, 0); setup_main_signals(); - dbug(2, "in main loop\n"); + send_request(STP_READY, NULL, 0); /* handle messages from control channel */ diff --git a/runtime/staprun/staprun.c b/runtime/staprun/staprun.c index 0291d01f..daebe705 100644 --- a/runtime/staprun/staprun.c +++ b/runtime/staprun/staprun.c @@ -21,12 +21,17 @@ */ #include "staprun.h" +#include <sys/uio.h> + /* used in dbug, _err and _perr */ char *__name__ = "staprun"; extern long delete_module(const char *, unsigned int); +int send_relocations (); + + static int run_as(uid_t uid, gid_t gid, const char *path, char *const argv[]) { pid_t pid; @@ -206,6 +211,8 @@ int init_staprun(void) return -1; if (insert_stap_module() < 0) return -1; + if (send_relocations() < 0) + return -1; } return 0; } @@ -288,3 +295,98 @@ err: remove_module(modname, 1); return 1; } + + + +/* Send a variety of relocation-related data to the kernel: for the + kernel proper, just the "_stext" symbol address; for all loaded + modules, a variety of symbol base addresses. + + We do this under protest. The kernel ought expose this data to + modules such as ourselves, but instead the upstream community + continually shrinks its module-facing interfaces, including this + stuff, even when users exist. +*/ + + +void send_a_relocation (const char* module, const char* reloc, unsigned long long address) +{ + struct _stp_msg_relocation msg; + + if (strlen(module) >= STP_MODULE_NAME_LEN) + { _perr ("module name too long: %s", module); return; } + strcpy (msg.module, module); + + if (strlen(reloc) >= STP_SYMBOL_NAME_LEN) + { _perr ("reloc name too long: %s", reloc); return; } + strcpy (msg.reloc, reloc); + + msg.address = address; + + send_request (STP_RELOCATION, & msg, sizeof (msg)); + /* XXX: verify send_request RC */ +} + + +int send_relocation_kernel () +{ + FILE* kallsyms = fopen ("/proc/kallsyms", "r"); + if (kallsyms == NULL) + { + perror("cannot open /proc/kallsyms"); + // ... and the kernel module will almost certainly fail to initialize. + } + else + { + while (! feof(kallsyms)) + { + char *line = NULL; + size_t linesz = 0; + ssize_t linesize = getline (& line, & linesz, kallsyms); + if (linesize < 0) + break; + else + { + unsigned long long address; + char type; + char* symbol = NULL; + int rc = sscanf (line, "%llx %c %as", &address, &type, &symbol); + free (line); line=NULL; + +#ifdef __powerpc__ +#define KERNEL_RELOC_SYMBOL ".__start" +#else +#define KERNEL_RELOC_SYMBOL "_stext" +#endif + if ((rc == 3) && (0 == strcmp(symbol,KERNEL_RELOC_SYMBOL))) + { + send_a_relocation ("kernel", KERNEL_RELOC_SYMBOL, address); + + /* We need nothing more from the kernel. */ + fclose (kallsyms); + return 0; + } + if (symbol != NULL) free (symbol); + } + } + fclose (kallsyms); + } + + return -1; +} + + +void send_relocation_modules () +{ + /* XXX */ +} + + + +int send_relocations () +{ + int rc = send_relocation_kernel (); + send_relocation_modules (); + return rc; +} + diff --git a/runtime/staprun/staprun.h b/runtime/staprun/staprun.h index 60bab391..0a35fee6 100644 --- a/runtime/staprun/staprun.h +++ b/runtime/staprun/staprun.h @@ -116,7 +116,6 @@ int init_stapio(void); int stp_main_loop(void); int send_request(int type, void *data, int len); void cleanup_and_exit (int); -void send_unwind_data(const char *name); int init_ctl_channel(const char *name, int verb); void close_ctl_channel(void); int init_relayfs(void); diff --git a/runtime/sym.c b/runtime/sym.c index 7163bf92..eca54a35 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -59,6 +59,8 @@ unsigned long _stp_module_relocate(const char *module, const char *section, unsi /* See also transport/symbols.c (_stp_do_symbols). */ if (strcmp(section, "_stext")) return 0; + else if (_stp_modules[0]->text == 0) /* kernel->text unavailable? STP_RELOCATE */ + return 0; else return offset + _stp_modules[0]->text; } else { @@ -88,11 +90,12 @@ static unsigned long _stp_kallsyms_lookup_name(const char *name) { struct _stp_symbol *s = _stp_modules[0]->symbols; unsigned num = _stp_modules[0]->num_symbols; + unsigned i; - while (num--) { - if (strcmp(name, s->symbol) == 0) - return s->addr; - s++; + for (i=0; i<num; i++, s++) { + if (strcmp(name, s->symbol) == 0) + return s->addr; + s++; } return 0; } diff --git a/runtime/transport/control.c b/runtime/transport/control.c index 9319b9ca..b366ccef 100644 --- a/runtime/transport/control.c +++ b/runtime/transport/control.c @@ -56,9 +56,10 @@ static ssize_t _stp_ctl_write_cmd(struct file *file, const char __user *buf, siz #else return -1; #endif + case STP_RELOCATION: + _stp_do_relocation (buf, count); + case STP_READY: - /* request symbolic information */ - /* _stp_ask_for_symbols(); */ break; default: @@ -66,7 +67,7 @@ static ssize_t _stp_ctl_write_cmd(struct file *file, const char __user *buf, siz return -EINVAL; } - return count; + return count; /* Pretend that we absorbed the entire message. */ } struct _stp_buffer { diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c index 9299fc67..cc0a1ce5 100644 --- a/runtime/transport/symbols.c +++ b/runtime/transport/symbols.c @@ -196,31 +196,54 @@ static int _stp_init_kernel_symbols(void) _stp_num_modules = 1; /* Note: this mapping is used by kernel/_stext pseudo-relocations. */ - #ifdef __powerpc__ - _stp_modules[0]->text = _stp_kallsyms_lookup_name(".__start"); - #else - _stp_modules[0]->text = _stp_kallsyms_lookup_name("_stext"); - #endif - if (_stp_modules[0]->text == 0) { - _dbug("Lookup of _stext failed. Exiting.\n"); - return -1; - } - - _stp_modules[0]->data = _stp_kallsyms_lookup_name("_etext"); - if (_stp_modules[0]->data == 0) { - _dbug("Lookup of _etext failed. Exiting.\n"); - return -1; - } + _stp_modules[0]->text = 0; /* This should be set by a STP_RELOCATE message. */ + _stp_modules[0]->data = 0; /* XXX */ + _stp_modules[0]->text_size = 0; /* XXX */ - _stp_modules[0]->text_size = _stp_modules[0]->data - _stp_modules[0]->text; + _stp_kretprobe_trampoline = 0; /* XXX */ _stp_modules_by_addr[0] = _stp_modules[0]; - - _stp_kretprobe_trampoline = _stp_kallsyms_lookup_name("kretprobe_trampoline"); - /* Lookup failure is not fatal */ + + printk (KERN_INFO "stap kernel data: symbols[%u]=%p\n", + _stp_num_kernel_symbols, _stp_kernel_symbols); return 0; } + +static void _stp_do_relocation(const char __user *buf, size_t count) +{ + struct _stp_msg_relocation msg; + if (sizeof(msg) != count) + { + errk ("STP_RELOCATE message size mismatch (%u vs %u)\n", sizeof(msg), count); + return; + } + + if (unlikely(copy_from_user (& msg, buf, count))) + return; + + dbug_sym (1, "STP_RELOCATE (%s %s %lx)\n", msg.module, msg.reloc, + (unsigned long) msg.address); + + if (!strcmp (msg.module, "kernel") && + !strcmp (msg.reloc, "_stext")) + + { + unsigned i; + + _stp_modules[0]->text = (unsigned long) msg.address; + + /* Now, relocate all the elements in the kernel symbol table. + We should at that point arrive at a strict subset of the + /proc/kallsyms table. */ + + for (i=0; i<_stp_modules[0]->num_symbols; i++) + _stp_modules[0]->symbols[i].addr += msg.address; + } +} + + +#if 0 static void _stp_do_unwind_data(const char __user *buf, size_t count) { u32 unwind_len; @@ -302,6 +325,8 @@ static void _stp_do_unwind_data(const char __user *buf, size_t count) done: write_unlock(&m->lock); } +#endif /* do_unwind_data; not used */ + static int _stp_compare_addr(const void *p1, const void *p2) { diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c index a4e4e652..d149dd15 100644 --- a/runtime/transport/transport.c +++ b/runtime/transport/transport.c @@ -267,10 +267,11 @@ int _stp_transport_init(void) if (_stp_init_kernel_symbols() < 0) goto err4; + /* dbug_trans(1, "calling init_modules\n"); if (_stp_init_modules() < 0) goto err4; - + */ return 0; err4: diff --git a/runtime/transport/transport_msgs.h b/runtime/transport/transport_msgs.h index 27476e76..493c7105 100644 --- a/runtime/transport/transport_msgs.h +++ b/runtime/transport/transport_msgs.h @@ -10,6 +10,7 @@ */ #define STP_MODULE_NAME_LEN 64 +#define STP_SYMBOL_NAME_LEN 64 struct _stp_trace { uint32_t sequence; /* event number */ @@ -34,6 +35,7 @@ enum STP_SUBBUFS_CONSUMED, STP_REALTIME_DATA, #endif + STP_RELOCATION, STP_MAX_CMD }; @@ -53,6 +55,7 @@ static const char *_stp_command_name[] = { "STP_SUBBUFS_CONSUMED", "STP_REALTIME_DATA", #endif + "STP_RELOCATION", }; #endif /* DEBUG_TRANS */ @@ -97,3 +100,11 @@ struct _stp_consumed_info uint32_t consumed; }; #endif + +/* Unwind data. stapio->module */ +struct _stp_msg_relocation +{ + char module[STP_MODULE_NAME_LEN]; + char reloc[STP_SYMBOL_NAME_LEN]; + uint64_t address; +}; |