diff options
Diffstat (limited to 'runtime/transport')
-rw-r--r-- | runtime/transport/ChangeLog | 23 | ||||
-rw-r--r-- | runtime/transport/control.c | 45 | ||||
-rw-r--r-- | runtime/transport/procfs.c | 38 | ||||
-rw-r--r-- | runtime/transport/symbols.c | 95 | ||||
-rw-r--r-- | runtime/transport/transport.c | 32 | ||||
-rw-r--r-- | runtime/transport/transport_msgs.h | 42 |
6 files changed, 191 insertions, 84 deletions
diff --git a/runtime/transport/ChangeLog b/runtime/transport/ChangeLog index 26268e66..e7bbabd8 100644 --- a/runtime/transport/ChangeLog +++ b/runtime/transport/ChangeLog @@ -1,4 +1,27 @@ 2008-01-15 Martin Hunt <hunt@redhat.com> + + PR4037 and fixes to better synchronize staprun and stapio. + * transport_msgs.h (struct _stp_symbol32): New. + (struct _stp_symbol64): New. + (struct _stp_msg_symbol_hdr): New. + (struct _stp_msg_module): New. + (STP_READY): Declare. + + * transport.c (_stp_handle_start): Don't set _stp_start_finished. + (_stp_work_queue): Don't use _stp_start_finished. + (_stp_transport_init): Don't call _stp_ask_for_symbols(). + + * symbols.c (_stp_do_symbols): Use _stp_msg_symbol_hdr; + + * control.c (_stp_sym_write_cmd): Allow sending of headers + and data in separate messages. + (_stp_ctl_write_cmd): Add STP_READY message. + + * procfs.c (_stp_sym_write_cmd): Allow sending of headers + and data in separate messages. + (_stp_ctl_write_cmd): Add STP_READY message. + +2008-01-15 Martin Hunt <hunt@redhat.com> Support for DEBUG_MEM * transport.c (_stp_transport): Call stp_mem_debug_done(); diff --git a/runtime/transport/control.c b/runtime/transport/control.c index 3cfeca1e..3179f507 100644 --- a/runtime/transport/control.c +++ b/runtime/transport/control.c @@ -1,7 +1,7 @@ /* -*- linux-c -*- * * debugfs control channel - * Copyright (C) 2007, 2008 Red Hat Inc. + * Copyright (C) 2007 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 @@ -22,38 +22,44 @@ spinlock_t _stp_sym_ready_lock = SPIN_LOCK_UNLOCKED; static ssize_t _stp_sym_write_cmd (struct file *file, const char __user *buf, size_t count, loff_t *ppos) { + static int saved_type = 0; int type; - if (count < sizeof(int)) + if (count < sizeof(int32_t)) return 0; - if (get_user(type, (int __user *)buf)) - return -EFAULT; - - kbug ("count:%d type:%d\n", count, type); - - if (type == STP_SYMBOLS) { - count -= sizeof(long); - buf += sizeof(long); + /* Allow sending of packet type followed by data in the next packet.*/ + if (count == sizeof(int32_t)) { + if (get_user(saved_type, (int __user *)buf)) + return -EFAULT; + return count; + } else if (saved_type) { + type = saved_type; + saved_type = 0; } else { + if (get_user(type, (int __user *)buf)) + return -EFAULT; count -= sizeof(int); buf += sizeof(int); } + + kbug ("count:%d type:%d\n", (int)count, type); switch (type) { - case STP_SYMBOLS: - - if (count) - count = _stp_do_symbols(buf, count); + case STP_SYMBOLS: + count = _stp_do_symbols(buf, count); break; case STP_MODULE: - if (count) + if (count > 1) count = _stp_do_module(buf, count); else { - /* count == 0 indicates end of initial modules list */ + /* count == 1 indicates end of initial modules list */ _stp_ctl_send(STP_TRANSPORT, NULL, 0); } break; + case STP_EXIT: + _stp_exit_flag = 1; + break; default: errk ("invalid symbol command type %d\n", type); return -EINVAL; @@ -73,7 +79,7 @@ static ssize_t _stp_ctl_write_cmd (struct file *file, const char __user *buf, if (get_user(type, (int __user *)buf)) return -EFAULT; - // kbug ("count:%d type:%d\n", count, type); + kbug ("count:%d type:%d\n", (int)count, type); count -= sizeof(int); buf += sizeof(int); @@ -99,6 +105,11 @@ static ssize_t _stp_ctl_write_cmd (struct file *file, const char __user *buf, #else return -1; #endif + case STP_READY: + /* request symbolic information */ + _stp_ask_for_symbols(); + break; + default: errk ("invalid command type %d\n", type); return -EINVAL; diff --git a/runtime/transport/procfs.c b/runtime/transport/procfs.c index 5d40cae4..85e97d15 100644 --- a/runtime/transport/procfs.c +++ b/runtime/transport/procfs.c @@ -68,35 +68,38 @@ static struct file_operations _stp_proc_fops = { static ssize_t _stp_sym_write_cmd (struct file *file, const char __user *buf, size_t count, loff_t *ppos) { + static int saved_type = 0; int type; - if (count < sizeof(int)) + if (count < sizeof(int32_t)) return 0; - if (get_user(type, (int __user *)buf)) - return -EFAULT; - - kbug ("count:%d type:%d\n", (int)count, type); - - if (type == STP_SYMBOLS) { - count -= sizeof(long); - buf += sizeof(long); + /* Allow sending of packet type followed by data in the next packet.*/ + if (count == sizeof(int32_t)) { + if (get_user(saved_type, (int __user *)buf)) + return -EFAULT; + return count; + } else if (saved_type) { + type = saved_type; + saved_type = 0; } else { + if (get_user(type, (int __user *)buf)) + return -EFAULT; count -= sizeof(int); buf += sizeof(int); } + + // kbug ("count:%d type:%d\n", (int)count, type); switch (type) { - case STP_SYMBOLS: - - if (count) - count = _stp_do_symbols(buf, count); + case STP_SYMBOLS: + count = _stp_do_symbols(buf, count); break; case STP_MODULE: - if (count) + if (count > 1) count = _stp_do_module(buf, count); else { - /* count == 0 indicates end of initial modules list */ + /* count == 1 indicates end of initial modules list */ _stp_ctl_send(STP_TRANSPORT, NULL, 0); } break; @@ -106,6 +109,7 @@ static ssize_t _stp_sym_write_cmd (struct file *file, const char __user *buf, } return count; + } static ssize_t _stp_ctl_write_cmd (struct file *file, const char __user *buf, size_t count, loff_t *ppos) @@ -139,6 +143,10 @@ static ssize_t _stp_ctl_write_cmd (struct file *file, const char __user *buf, case STP_EXIT: _stp_exit_flag = 1; break; + case STP_READY: + /* request symbolic information */ + _stp_ask_for_symbols(); + break; default: errk ("invalid command type %d\n", type); return -EINVAL; diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c index a3ab5807..dde0f967 100644 --- a/runtime/transport/symbols.c +++ b/runtime/transport/symbols.c @@ -1,7 +1,7 @@ /* -*- linux-c -*- * symbols.c - stp symbol and module functions * - * Copyright (C) Red Hat Inc, 2006, 2007 + * Copyright (C) Red Hat Inc, 2006-2008 * * 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 @@ -84,15 +84,19 @@ static struct _stp_module * _stp_alloc_module(unsigned num, unsigned datasize) goto bad; mod->allocated |= 2; } + mod->num_symbols = num; return mod; bad: if (mod) { - if (mod->allocated && mod->symbols) - _stp_vfree(mod->symbols); - else - _stp_kfree(mod->symbols); + if (mod->symbols) { + if (mod->allocated & 1) + _stp_vfree(mod->symbols); + else + _stp_kfree(mod->symbols); + mod->symbols = NULL; + } _stp_kfree(mod); } return NULL; @@ -107,19 +111,25 @@ static struct _stp_module * _stp_alloc_module_from_module (struct module *m) static void _stp_free_module(struct _stp_module *mod) { /* free symbol memory */ - if (mod->num_symbols) { + if (mod->symbols) { if (mod->allocated & 1) _stp_vfree(mod->symbols); else _stp_kfree(mod->symbols); + mod->symbols = NULL; + } + if (mod->symbol_data) { if (mod->allocated & 2) _stp_vfree(mod->symbol_data); else _stp_kfree(mod->symbol_data); + mod->symbol_data = NULL; + } - if (mod->sections) + if (mod->sections) { _stp_kfree(mod->sections); - + mod->sections = NULL; + } /* free module memory */ _stp_kfree(mod); } @@ -174,20 +184,21 @@ static unsigned long _stp_kallsyms_lookup_name(const char *name); /* process the KERNEL symbols */ static int _stp_do_symbols(const char __user *buf, int count) { - unsigned i, datasize, num; struct _stp_symbol *s; + unsigned datasize, num; + int i; switch (_stp_symbol_state) { case 0: - if (count != 8) { - errk(" _stp_do_symbols: count=%d\n", count); + if (count != sizeof(struct _stp_msg_symbol_hdr)) { + errk("count=%d\n", count); return -EFAULT; } if (get_user(num, (unsigned __user *)buf)) return -EFAULT; if (get_user(datasize, (unsigned __user *)(buf+4))) return -EFAULT; - // kbug("num=%d datasize=%d\n", num, datasize); + //kbug("num=%d datasize=%d\n", num, datasize); _stp_modules[0] = _stp_alloc_module(num, datasize); if (_stp_modules[0] == NULL) { @@ -197,26 +208,27 @@ static int _stp_do_symbols(const char __user *buf, int count) _stp_symbol_state = 1; break; case 1: + //kbug("got stap_symbols, count=%d\n", count); if (copy_from_user ((char *)_stp_modules[0]->symbols, buf, count)) return -EFAULT; - // kbug("got stap_symbols, count=%d\n", count); _stp_symbol_state = 2; break; case 2: + //kbug("got symbol data, count=%d buf=%p\n", count, buf); if (copy_from_user (_stp_modules[0]->symbol_data, buf, count)) return -EFAULT; - // kbug("got symbol data, count=%d\n", count); _stp_num_modules = 1; - s = _stp_modules[0]->symbols; 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[0]->data = _stp_kallsyms_lookup_name("_etext"); _stp_modules_by_addr[0] = _stp_modules[0]; + //kbug("done with symbol data\n"); break; default: errk("unexpected symbol data of size %d.\n", count); @@ -433,8 +445,9 @@ done: /* Called from procfs.c when a STP_MODULE msg is received */ static int _stp_do_module(const char __user *buf, int count) { - struct _stp_module tmpmod, *mod; - unsigned i; + struct _stp_msg_module tmpmod; + struct _stp_module mod, *m; + unsigned i, section_len; if (count < (int)sizeof(tmpmod)) { errk("expected %d and got %d\n", (int)sizeof(tmpmod), count); @@ -443,41 +456,53 @@ static int _stp_do_module(const char __user *buf, int count) if (copy_from_user ((char *)&tmpmod, buf, sizeof(tmpmod))) return -EFAULT; - // kbug("Got module %s, count=%d(0x%x)\n", tmpmod.name, count,count); - - if (_stp_module_exists(&tmpmod)) + section_len = count - sizeof(tmpmod); + if (section_len <= 0) { + errk("section_len = %d\n", section_len); + return -EFAULT; + } + kbug("Got module %s, count=%d section_len=%d\n", + tmpmod.name, count, section_len); + + strcpy(mod.name, tmpmod.name); + mod.module = tmpmod.module; + mod.text = tmpmod.text; + mod.data = tmpmod.data; + mod.num_sections = tmpmod.num_sections; + + if (_stp_module_exists(&mod)) return count; /* copy in section data */ - tmpmod.sections = _stp_kmalloc(count - sizeof(tmpmod)); - if (tmpmod.sections == NULL) { + mod.sections = _stp_kmalloc(section_len); + if (mod.sections == NULL) { errk("unable to allocate memory.\n"); return -EFAULT; } - if (copy_from_user ((char *)tmpmod.sections, buf+sizeof(tmpmod), count-sizeof(tmpmod))) { - _stp_kfree(tmpmod.sections); + if (copy_from_user ((char *)mod.sections, buf+sizeof(tmpmod), section_len)) { + _stp_kfree(mod.sections); return -EFAULT; } - for (i = 0; i < tmpmod.num_sections; i++) { - tmpmod.sections[i].symbol = - (char *)((long)tmpmod.sections[i].symbol - + (long)((long)tmpmod.sections + tmpmod.num_sections * sizeof(struct _stp_symbol))); + for (i = 0; i < mod.num_sections; i++) { + mod.sections[i].symbol = + (char *)((long)mod.sections[i].symbol + + (long)((long)mod.sections + mod.num_sections * sizeof(struct _stp_symbol))); } #ifdef DEBUG_SYMBOLS - for (i = 0; i < tmpmod.num_sections; i++) - printk("section %d (stored at %p): %s %lx\n", i, &tmpmod.sections[i], tmpmod.sections[i].symbol, tmpmod.sections[i].addr); + for (i = 0; i < mod.num_sections; i++) + printk("section %d (stored at %p): %s %lx\n", i, &mod.sections[i], mod.sections[i].symbol, mod.sections[i].addr); #endif /* load symbols from tmpmod.module to mod */ - mod = _stp_load_module_symbols(&tmpmod); - if (mod == NULL) { - _stp_kfree(tmpmod.sections); + m = _stp_load_module_symbols(&mod); + if (m == NULL) { + _stp_kfree(mod.sections); return 0; } - if (_stp_ins_module(mod) < 0) { - _stp_free_module(mod); + if (_stp_ins_module(m) < 0) { + _stp_free_module(m); return -ENOMEM; } diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c index 0b18b275..6b90ee64 100644 --- a/runtime/transport/transport.c +++ b/runtime/transport/transport.c @@ -31,7 +31,6 @@ static struct utt_trace *_stp_utt = NULL; static unsigned int utt_seq = 1; -static int _stp_start_finished = 0; static int _stp_probes_started = 0; /* module parameters */ @@ -61,6 +60,7 @@ static DECLARE_WORK(_stp_work, _stp_work_queue, NULL); #endif static struct workqueue_struct *_stp_wq; +static void _stp_ask_for_symbols(void); #ifdef STP_OLD_TRANSPORT #include "procfs.c" @@ -72,16 +72,20 @@ static void _stp_ask_for_symbols(void) { struct _stp_msg_symbol req; struct _stp_module mod; - - /* ask for symbols and modules */ - kbug("AFS\n"); - - req.endian = 0x1234; - req.ptr_size = sizeof(char *); - _stp_ctl_send(STP_SYMBOLS, &req, sizeof(req)); - - strcpy(mod.name, ""); - _stp_ctl_send(STP_MODULE, &mod, sizeof(mod)); + static int sent_symbols = 0; + + if (sent_symbols == 0) { + /* ask for symbols and modules */ + kbug("AFS\n"); + + req.endian = 0x1234; + req.ptr_size = sizeof(char *); + _stp_ctl_send(STP_SYMBOLS, &req, sizeof(req)); + + strcpy(mod.name, ""); + _stp_ctl_send(STP_MODULE, &mod, sizeof(mod)); + sent_symbols = 1; + } } /* @@ -97,7 +101,6 @@ void _stp_handle_start (struct _stp_msg_start *st) _stp_target = st->target; st->res = probe_start(); - _stp_start_finished = 1; if (st->res >= 0) _stp_probes_started = 1; @@ -193,7 +196,7 @@ static void _stp_work_queue (void *data) wake_up_interruptible(&_stp_ctl_wq); /* if exit flag is set AND we have finished with probe_start() */ - if (unlikely(_stp_exit_flag && _stp_start_finished)) + if (unlikely(_stp_exit_flag)) _stp_cleanup_and_exit(0); else if (likely(_stp_attached)) queue_delayed_work(_stp_wq, &_stp_work, STP_WORK_TIMER); @@ -288,9 +291,6 @@ int _stp_transport_init(void) _stp_wq = create_workqueue("systemtap"); if (!_stp_wq) goto err3; - - /* request symbolic information */ - _stp_ask_for_symbols(); return 0; err3: diff --git a/runtime/transport/transport_msgs.h b/runtime/transport/transport_msgs.h index c6090969..b2187cd5 100644 --- a/runtime/transport/transport_msgs.h +++ b/runtime/transport/transport_msgs.h @@ -1,7 +1,7 @@ /* -*- linux-c -*- * transport_msgs.h - messages exchanged between module and userspace * - * Copyright (C) Red Hat Inc, 2006-2007 + * Copyright (C) Red Hat Inc, 2006-2008 * * 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 @@ -9,6 +9,8 @@ * later version. */ +#define STP_MODULE_NAME_LEN 64 + struct _stp_trace { uint32_t sequence; /* event number */ uint32_t pdu_len; /* length of data after this trace */ @@ -27,6 +29,7 @@ enum STP_CONNECT, STP_DISCONNECT, STP_BULK, + STP_READY, #ifdef STP_OLD_TRANSPORT /** deprecated **/ STP_BUF_INFO, @@ -58,6 +61,43 @@ struct _stp_msg_start int32_t res; // for reply: result of probe_start() }; +struct _stp_symbol32 +{ + uint32_t addr; + uint32_t symbol; +}; + +struct _stp_symbol64 +{ + uint64_t addr; + uint64_t symbol; +}; + +struct _stp_msg_symbol_hdr +{ + uint32_t num_syms; + uint32_t sym_size; + uint32_t unwind_size; +}; + +struct _stp_msg_module { + /* the module name, or "" for kernel */ + char name[STP_MODULE_NAME_LEN]; + + /* A pointer to the struct module */ + uint64_t module; + + /* the start of the module's text and data sections */ + uint64_t text; + uint64_t data; + + /* how many sections this module has */ + uint32_t num_sections; + + /* length of unwind data */ + uint32_t unwind_len; +}; + #ifdef STP_OLD_TRANSPORT /**** for compatibility with old relayfs ****/ struct _stp_buf_info |