summaryrefslogtreecommitdiffstats
path: root/runtime/transport
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/transport')
-rw-r--r--runtime/transport/ChangeLog25
-rw-r--r--runtime/transport/control.c224
-rw-r--r--runtime/transport/procfs.c2
-rw-r--r--runtime/transport/symbols.c627
-rw-r--r--runtime/transport/transport.c147
-rw-r--r--runtime/transport/transport.h20
-rw-r--r--runtime/transport/transport_msgs.h63
7 files changed, 482 insertions, 626 deletions
diff --git a/runtime/transport/ChangeLog b/runtime/transport/ChangeLog
index c3837f86..b3a159e3 100644
--- a/runtime/transport/ChangeLog
+++ b/runtime/transport/ChangeLog
@@ -1,3 +1,28 @@
+2008-04-09 Martin Hunt <hunt@dragon>
+
+ * symbols.c (_stp_init_kernel_symbols): Print error
+ messages and exit if symbol lookups fail.
+ (_stp_init_modules): Lookup modules_op.
+
+2008-03-31 Martin Hunt <hunt@redhat.com>
+
+ * symbols.c (_stp_init_modules): Use STP_USE_DWARF_UNWINDER.
+
+ * transport.c (_stp_get_root_dir): Remove misleading error message.
+
+2008-03-30 Martin Hunt <hunt@redhat.com>
+
+ * symbols.c (_stp_init_modules): If using frames, don't
+ request unwind info.
+
+2008-03-25 Martin Hunt <hunt@redhat.com>
+
+ * control.c (_stp_ctl_write_dbug): Insert missing break.
+
+ 32-bit systems can't do 64-bit get_user(), so
+ * symbols.c (_stp_do_unwind_data): Change unwind_len to a u32.
+ * transport_msgs.h (struct _stp_msg_unwind): Ditto.
+
2008-02-27 Martin Hunt <hunt@redhat.com>
* symbols.c: Use rwlocks. Use new dbug macros. Handle
diff --git a/runtime/transport/control.c b/runtime/transport/control.c
index 6a5b272d..92334b9c 100644
--- a/runtime/transport/control.c
+++ b/runtime/transport/control.c
@@ -14,80 +14,31 @@ static int _stp_current_buffers = STP_DEFAULT_BUFFERS;
static _stp_mempool_t *_stp_pool_q;
static struct list_head _stp_ctl_ready_q;
-static struct list_head _stp_sym_ready_q;
DEFINE_SPINLOCK(_stp_ctl_ready_lock);
-DEFINE_SPINLOCK(_stp_sym_ready_lock);
-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(int32_t))
- return 0;
-
- /* 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);
- }
-
-#if DEBUG_TRANSPORT > 0
- if (type < STP_MAX_CMD)
- _dbug("Got %s. len=%d\n", _stp_command_name[type], (int)count);
-#endif
-
- switch (type) {
- case STP_SYMBOLS:
- count = _stp_do_symbols(buf, count);
- break;
- case STP_MODULE:
- if (count > 1)
- count = _stp_do_module(buf, count);
- else {
- /* 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;
- }
-
- return count;
-}
static ssize_t _stp_ctl_write_cmd(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
- int type;
+ u32 type;
static int started = 0;
- if (count < sizeof(int))
+ if (count < sizeof(u32))
return 0;
- if (get_user(type, (int __user *)buf))
+ if (get_user(type, (u32 __user *)buf))
return -EFAULT;
-#if DEBUG_TRANSPORT > 0
+ count -= sizeof(u32);
+ buf += sizeof(u32);
+
+#ifdef DEBUG_TRANS
if (type < STP_MAX_CMD)
_dbug("Got %s. len=%d\n", _stp_command_name[type], (int)count);
#endif
- count -= sizeof(int);
- buf += sizeof(int);
-
switch (type) {
+ case STP_UNWIND:
+ _stp_do_unwind_data(buf, count);
+ break;
case STP_START:
if (started == 0) {
struct _stp_msg_start st;
@@ -110,7 +61,7 @@ static ssize_t _stp_ctl_write_cmd(struct file *file, const char __user *buf, siz
#endif
case STP_READY:
/* request symbolic information */
- _stp_ask_for_symbols();
+ /* _stp_ask_for_symbols(); */
break;
default:
@@ -121,8 +72,6 @@ static ssize_t _stp_ctl_write_cmd(struct file *file, const char __user *buf, siz
return count;
}
-#define STP_CTL_BUFFER_SIZE 256
-
struct _stp_buffer {
struct list_head list;
int len;
@@ -131,9 +80,8 @@ struct _stp_buffer {
};
static DECLARE_WAIT_QUEUE_HEAD(_stp_ctl_wq);
-static DECLARE_WAIT_QUEUE_HEAD(_stp_sym_wq);
-#if DEBUG_TRANSPORT > 0
+#ifdef DEBUG_TRANS
static void _stp_ctl_write_dbug(int type, void *data, int len)
{
char buf[64];
@@ -155,19 +103,9 @@ static void _stp_ctl_write_dbug(int type, void *data, int len)
case STP_TRANSPORT:
_dbug("sending STP_TRANSPORT\n");
break;
- default:
- _dbug("ERROR: unknown message type: %d\n", type);
- break;
- }
-}
-static void _stp_sym_write_dbug(int type, void *data, int len)
-{
- switch (type) {
- case STP_SYMBOLS:
- _dbug("sending STP_SYMBOLS\n");
- break;
- case STP_MODULE:
- _dbug("sending STP_MODULE\n");
+ case STP_UNWIND:
+ snprintf(buf, sizeof(buf), "%s", (char *)data);
+ _dbug("sending STP_UNWIND %s [len=%d]\n", buf, len);
break;
default:
_dbug("ERROR: unknown message type: %d\n", type);
@@ -181,7 +119,7 @@ static int _stp_ctl_write(int type, void *data, unsigned len)
struct _stp_buffer *bptr;
unsigned long flags;
-#if DEBUG_TRANSPORT > 0
+#ifdef DEBUG_TRANS
_stp_ctl_write_dbug(type, data, len);
#endif
@@ -206,96 +144,19 @@ static int _stp_ctl_write(int type, void *data, unsigned len)
return len;
}
-static int _stp_sym_write(int type, void *data, unsigned len)
-{
- struct _stp_buffer *bptr;
- unsigned long flags;
-
-#if DEBUG_TRANSPORT > 0
- _stp_sym_write_dbug(type, data, len);
-#endif
-
- /* make sure we won't overflow the buffer */
- if (unlikely(len > STP_CTL_BUFFER_SIZE))
- return 0;
-
- /* get a buffer from the free pool */
- bptr = _stp_mempool_alloc(_stp_pool_q);
- if (unlikely(bptr == NULL))
- return -1;
-
- bptr->type = type;
- memcpy(bptr->buf, data, len);
- bptr->len = len;
-
- /* put it on the pool of ready buffers */
- spin_lock_irqsave(&_stp_sym_ready_lock, flags);
- list_add_tail(&bptr->list, &_stp_sym_ready_q);
- spin_unlock_irqrestore(&_stp_sym_ready_lock, flags);
-
- /* OK, it's queued. Now signal any waiters. */
- wake_up_interruptible(&_stp_sym_wq);
-
- return len;
-}
-
/* send commands with timeout and retry */
static int _stp_ctl_send(int type, void *data, int len)
{
int err, trylimit = 50;
- kbug(DEBUG_TRANSPORT, "ctl_send: type=%d len=%d\n", type, len);
- if (unlikely(type == STP_SYMBOLS || type == STP_MODULE)) {
- while ((err = _stp_sym_write(type, data, len)) < 0 && trylimit--)
- msleep(5);
- } else {
- while ((err = _stp_ctl_write(type, data, len)) < 0 && trylimit--)
- msleep(5);
- if (err > 0)
- wake_up_interruptible(&_stp_ctl_wq);
- }
- kbug(DEBUG_TRANSPORT, "returning %d\n", err);
+ dbug_trans(1, "ctl_send: type=%d len=%d\n", type, len);
+ while ((err = _stp_ctl_write(type, data, len)) < 0 && trylimit--)
+ msleep(5);
+ if (err > 0)
+ wake_up_interruptible(&_stp_ctl_wq);
+ dbug_trans(1, "returning %d\n", err);
return err;
}
-static ssize_t _stp_sym_read_cmd(struct file *file, char __user *buf, size_t count, loff_t *ppos)
-{
- struct _stp_buffer *bptr;
- int len;
- unsigned long flags;
-
- /* wait for nonempty ready queue */
- spin_lock_irqsave(&_stp_sym_ready_lock, flags);
- while (list_empty(&_stp_sym_ready_q)) {
- spin_unlock_irqrestore(&_stp_sym_ready_lock, flags);
- if (file->f_flags & O_NONBLOCK)
- return -EAGAIN;
- if (wait_event_interruptible(_stp_sym_wq, !list_empty(&_stp_sym_ready_q)))
- return -ERESTARTSYS;
- spin_lock_irqsave(&_stp_sym_ready_lock, flags);
- }
-
- /* get the next buffer off the ready list */
- bptr = (struct _stp_buffer *)_stp_sym_ready_q.next;
- list_del_init(&bptr->list);
- spin_unlock_irqrestore(&_stp_sym_ready_lock, flags);
-
- /* write it out */
- len = bptr->len + 4;
- if (len > count || copy_to_user(buf, &bptr->type, len)) {
- /* now what? We took it off the queue then failed to send it */
- /* we can't put it back on the queue because it will likely be out-of-order */
- /* fortunately this should never happen */
- /* FIXME need to mark this as a transport failure */
- errk("Supplied buffer too small. count:%d len:%d\n", (int)count, len);
- return -EFAULT;
- }
-
- /* put it on the pool of free buffers */
- _stp_mempool_free(bptr);
-
- return len;
-}
-
static ssize_t _stp_ctl_read_cmd(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
struct _stp_buffer *bptr;
@@ -335,29 +196,10 @@ static ssize_t _stp_ctl_read_cmd(struct file *file, char __user *buf, size_t cou
return len;
}
-static int _stp_sym_opens = 0;
-static int _stp_sym_open_cmd(struct inode *inode, struct file *file)
-{
- /* only allow one reader */
- if (_stp_sym_opens)
- return -1;
-
- _stp_sym_opens++;
- return 0;
-}
-
-static int _stp_sym_close_cmd(struct inode *inode, struct file *file)
-{
- if (_stp_sym_opens)
- _stp_sym_opens--;
- return 0;
-}
-
static int _stp_ctl_open_cmd(struct inode *inode, struct file *file)
{
if (_stp_attached)
return -1;
-
_stp_attach();
return 0;
}
@@ -377,16 +219,7 @@ static struct file_operations _stp_ctl_fops_cmd = {
.release = _stp_ctl_close_cmd,
};
-static struct file_operations _stp_sym_fops_cmd = {
- .owner = THIS_MODULE,
- .read = _stp_sym_read_cmd,
- .write = _stp_sym_write_cmd,
- .open = _stp_sym_open_cmd,
- .release = _stp_sym_close_cmd,
-};
-
static struct dentry *_stp_cmd_file = NULL;
-static struct dentry *_stp_sym_file = NULL;
static int _stp_register_ctl_channel(void)
{
@@ -400,7 +233,6 @@ static int _stp_register_ctl_channel(void)
}
INIT_LIST_HEAD(&_stp_ctl_ready_q);
- INIT_LIST_HEAD(&_stp_sym_ready_q);
/* allocate buffers */
_stp_pool_q = _stp_mempool_init(sizeof(struct _stp_buffer), STP_DEFAULT_BUFFERS);
@@ -415,15 +247,9 @@ static int _stp_register_ctl_channel(void)
_stp_cmd_file->d_inode->i_uid = _stp_uid;
_stp_cmd_file->d_inode->i_gid = _stp_gid;
- /* create [debugfs]/systemtap/module_name/.symbols */
- _stp_sym_file = debugfs_create_file(".symbols", 0600, _stp_utt->dir, NULL, &_stp_sym_fops_cmd);
- if (_stp_sym_file == NULL)
- goto err0;
return 0;
err0:
- if (_stp_cmd_file)
- debugfs_remove(_stp_cmd_file);
_stp_mempool_destroy(_stp_pool_q);
errk("Error creating systemtap debugfs entries.\n");
return -1;
@@ -432,16 +258,10 @@ err0:
static void _stp_unregister_ctl_channel(void)
{
struct list_head *p, *tmp;
- if (_stp_sym_file)
- debugfs_remove(_stp_sym_file);
if (_stp_cmd_file)
debugfs_remove(_stp_cmd_file);
/* Return memory to pool and free it. */
- list_for_each_safe(p, tmp, &_stp_sym_ready_q) {
- list_del(p);
- _stp_mempool_free(p);
- }
list_for_each_safe(p, tmp, &_stp_ctl_ready_q) {
list_del(p);
_stp_mempool_free(p);
diff --git a/runtime/transport/procfs.c b/runtime/transport/procfs.c
index 2afea1c9..750e1994 100644
--- a/runtime/transport/procfs.c
+++ b/runtime/transport/procfs.c
@@ -161,7 +161,7 @@ struct _stp_buffer {
struct list_head list;
int len;
int type;
- char buf[STP_BUFFER_SIZE];
+ char buf[STP_CTL_BUFFER_SIZE];
};
static DECLARE_WAIT_QUEUE_HEAD(_stp_ctl_wq);
diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c
index 8c453a55..b0e7c319 100644
--- a/runtime/transport/symbols.c
+++ b/runtime/transport/symbols.c
@@ -12,8 +12,8 @@
* lib/sort.c of kernel 2.6.22-rc5. It was written by Matt Mackall.
*/
-#ifndef _SYMBOLS_C_
-#define _SYMBOLS_C_
+#ifndef _STP_SYMBOLS_C_
+#define _STP_SYMBOLS_C_
#include "../sym.h"
static char *_stp_symbol_data = NULL;
@@ -21,17 +21,12 @@ static int _stp_symbol_state = 0;
static char *_stp_module_data = NULL;
static int _stp_module_state = 0;
-
/* these are all the symbol types we are interested in */
static int _stp_sym_type_ok(int type)
{
- switch (type) {
- case 'T':
- case 't':
+ /* we only care about function symbols, which are in the text section */
+ if (type == 'T' || type == 't')
return 1;
- default:
- return 0;
- }
return 0;
}
@@ -41,10 +36,10 @@ static unsigned _stp_get_sym_sizes(struct module *m, unsigned *dsize)
{
unsigned int i;
unsigned num = 0, datasize = 0;
- for (i=0; i < m->num_symtab; i++) {
+ for (i = 0; i < m->num_symtab; i++) {
char *str = (char *)(m->strtab + m->symtab[i].st_name);
if (*str != '\0' && _stp_sym_type_ok(m->symtab[i].st_info)) {
- datasize += strlen(str)+1;
+ datasize += strlen(str) + 1;
num++;
}
}
@@ -52,19 +47,23 @@ static unsigned _stp_get_sym_sizes(struct module *m, unsigned *dsize)
return num;
}
-/* allocate space for a module and symbols */
-static struct _stp_module * _stp_alloc_module(unsigned num, unsigned datasize, unsigned unwindsize)
+/* allocate space for a module, sections, and symbols */
+static struct _stp_module *_stp_alloc_module(unsigned sectsize, unsigned num, unsigned datasize)
{
struct _stp_module *mod = (struct _stp_module *)_stp_kzalloc(sizeof(struct _stp_module));
if (mod == NULL)
goto bad;
+ mod->sections = (struct _stp_symbol *)_stp_kmalloc(sectsize);
+ if (mod->sections == NULL)
+ goto bad;
+
mod->symbols = (struct _stp_symbol *)_stp_kmalloc(num * sizeof(struct _stp_symbol));
if (mod->symbols == NULL) {
mod->symbols = (struct _stp_symbol *)_stp_vmalloc(num * sizeof(struct _stp_symbol));
if (mod->symbols == NULL)
goto bad;
- mod->allocated = 1;
+ mod->allocated.symbols = 1;
}
mod->symbol_data = _stp_kmalloc(datasize);
@@ -72,91 +71,63 @@ static struct _stp_module * _stp_alloc_module(unsigned num, unsigned datasize, u
mod->symbol_data = _stp_vmalloc(datasize);
if (mod->symbol_data == NULL)
goto bad;
- mod->allocated |= 2;
+ mod->allocated.symbol_data = 1;
}
- mod->unwind_data = _stp_kmalloc(unwindsize);
- if (mod->unwind_data == NULL) {
- mod->unwind_data = _stp_vmalloc(unwindsize);
- if (mod->unwind_data == NULL)
- goto bad;
- mod->allocated |= 4;
- }
-
mod->num_symbols = num;
return mod;
bad:
if (mod) {
+ if (mod->sections)
+ _stp_kfree(mod->sections);
if (mod->symbols) {
- if (mod->allocated & 1)
+ if (mod->allocated.symbols)
_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;
- }
- _stp_kfree(mod);
- if (mod->symbols) {
- if (mod->allocated & 1)
- _stp_vfree(mod->symbols);
- else
- _stp_kfree(mod->symbols);
- mod->symbols = NULL;
- }
- _stp_kfree(mod);
+ _stp_kfree(mod);
}
return NULL;
}
-static struct _stp_module * _stp_alloc_module_from_module (struct module *m, uint32_t unwind_len)
-{
- unsigned datasize, num = _stp_get_sym_sizes(m, &datasize);
- return _stp_alloc_module(num, datasize, unwind_len);
-}
-
static void _stp_free_module(struct _stp_module *mod)
{
/* The module write lock is held. Any prior readers of this */
/* module's data will have read locks and need to finish before */
/* the memory is freed. */
write_lock(&mod->lock);
- write_unlock(&mod->lock); /* there will be no more readers */
+ write_unlock(&mod->lock); /* there will be no more readers */
- /* free symbol memory */
- if (mod->symbols) {
- if (mod->allocated & 1)
- _stp_vfree(mod->symbols);
- else
- _stp_kfree(mod->symbols);
- mod->symbols = NULL;
- }
+ /* Free symbol memory */
+ /* If symbol_data wasn't allocated, then symbols weren't either. */
if (mod->symbol_data) {
- if (mod->allocated & 2)
+ if (mod->symbols) {
+ if (mod->allocated.symbols)
+ _stp_vfree(mod->symbols);
+ else
+ _stp_kfree(mod->symbols);
+ }
+ if (mod->allocated.symbol_data)
_stp_vfree(mod->symbol_data);
else
_stp_kfree(mod->symbol_data);
- mod->symbol_data = NULL;
-
}
if (mod->unwind_data) {
- if (mod->allocated & 4)
+ if (mod->allocated.unwind_data)
_stp_vfree(mod->unwind_data);
else
_stp_kfree(mod->unwind_data);
- mod->unwind_data = NULL;
-
}
- if (mod->sections) {
- _stp_kfree(mod->sections);
- mod->sections = NULL;
+ if (mod->unwind_hdr) {
+ if (mod->allocated.unwind_hdr)
+ _stp_vfree(mod->unwind_hdr);
+ else
+ _stp_kfree(mod->unwind_hdr);
}
+ if (mod->sections)
+ _stp_kfree(mod->sections);
/* free module memory */
_stp_kfree(mod);
@@ -168,7 +139,7 @@ static void _stp_del_module(struct _stp_module *mod)
{
int i, num;
- // kbug(DEBUG_SYMBOLS, "deleting %s\n", mod->name);
+ dbug_sym(1, "deleting module %s\n", mod->name);
/* signal relocation code to clear its cache */
_stp_module_relocate((char *)-1, NULL, 0);
@@ -181,15 +152,15 @@ static void _stp_del_module(struct _stp_module *mod)
if (num >= _stp_num_modules)
return;
- for (i = num; i < _stp_num_modules-1; i++)
- _stp_modules[i] = _stp_modules[i+1];
+ for (i = num; i < _stp_num_modules - 1; i++)
+ _stp_modules[i] = _stp_modules[i + 1];
for (num = 0; num < _stp_num_modules; num++) {
if (_stp_modules_by_addr[num] == mod)
break;
}
- for (i = num; i < _stp_num_modules-1; i++)
- _stp_modules_by_addr[i] = _stp_modules_by_addr[i+1];
+ for (i = num; i < _stp_num_modules - 1; i++)
+ _stp_modules_by_addr[i] = _stp_modules_by_addr[i + 1];
_stp_num_modules--;
@@ -197,10 +168,8 @@ static void _stp_del_module(struct _stp_module *mod)
}
static void _stp_free_modules(void)
-{
+{
int i;
- unsigned long flags;
-
/* This only happens when the systemtap module unloads */
/* so there is no need for locks. */
for (i = _stp_num_modules - 1; i >= 0; i--)
@@ -208,82 +177,132 @@ static void _stp_free_modules(void)
}
static unsigned long _stp_kallsyms_lookup_name(const char *name);
+static void _stp_create_unwind_hdr(struct _stp_module *m);
+
+extern unsigned _stp_num_kernel_symbols;
+extern struct _stp_symbol _stp_kernel_symbols[];
-/* process the KERNEL symbols */
-static int _stp_do_symbols(const char __user *buf, int count)
+/* initialize the kernel symbols */
+static int _stp_init_kernel_symbols(void)
{
- struct _stp_symbol *s;
- unsigned datasize, num, unwindsize;
+ _stp_modules[0] = (struct _stp_module *)_stp_kzalloc(sizeof(struct _stp_module));
+ if (_stp_modules[0] == NULL) {
+ _dbug("cannot allocate memory\n");
+ return -1;
+ }
+ _stp_modules[0]->symbols = _stp_kernel_symbols;
+ _stp_modules[0]->num_symbols = _stp_num_kernel_symbols;
+ rwlock_init(&_stp_modules[0]->lock);
+ _stp_num_modules = 1;
+
+ /* Note: this mapping is used by kernel/_stext pseudo-relocations. */
+ _stp_modules[0]->text = _stp_kallsyms_lookup_name("_stext");
+ 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_size = _stp_modules[0]->data - _stp_modules[0]->text;
+ _stp_modules_by_addr[0] = _stp_modules[0];
+
+ _stp_kretprobe_trampoline = _stp_kallsyms_lookup_name("kretprobe_trampoline");
+ /* Lookup failure is not fatal */
+
+ return 0;
+}
+
+static void _stp_do_unwind_data(const char __user *buf, size_t count)
+{
+ u32 unwind_len;
+ unsigned long flags;
+ char name[STP_MODULE_NAME_LEN];
int i;
+ struct _stp_module *m;
+
+ dbug_unwind(1, "got unwind data, count=%d\n", count);
- switch (_stp_symbol_state) {
- case 0:
- 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;
- if (get_user(unwindsize, (unsigned __user *)(buf+8)))
- return -EFAULT;
- dbug(DEBUG_UNWIND, "num=%d datasize=%d unwindsize=%d\n", num, datasize, unwindsize);
-
- _stp_modules[0] = _stp_alloc_module(num, datasize, unwindsize);
- if (_stp_modules[0] == NULL) {
- errk("cannot allocate memory\n");
- return -EFAULT;
+ if (count < STP_MODULE_NAME_LEN + sizeof(unwind_len)) {
+ dbug_unwind(1, "unwind message too short\n");
+ return;
+ }
+ if (strncpy_from_user(name, buf, STP_MODULE_NAME_LEN) < 0) {
+ errk("userspace copy failed\n");
+ return;
+ }
+ dbug_unwind(1, "name=%s\n", name);
+ if (!strcmp(name,"*")) {
+ /* OK, all initial unwind data received. Ready to go. */
+ _stp_ctl_send(STP_TRANSPORT, NULL, 0);
+ return;
+ }
+ count -= STP_MODULE_NAME_LEN;
+ buf += STP_MODULE_NAME_LEN;
+
+ if (get_user(unwind_len, (u32 __user *)buf)) {
+ errk("userspace copy failed\n");
+ return;
+ }
+ count -= sizeof(unwind_len);
+ buf += sizeof(unwind_len);
+ if (count != unwind_len) {
+ dbug_unwind(1, "count=%d unwind_len=%d\n", (int)count, (int)unwind_len);
+ return;
+ }
+
+ STP_RLOCK_MODULES;
+ for (i = 0; i < _stp_num_modules; i++) {
+ if (strcmp(name, _stp_modules[i]->name) == 0)
+ break;
+ }
+ if (unlikely(i == _stp_num_modules)) {
+ dbug_unwind(1, "module %s not found!\n", name);
+ STP_RUNLOCK_MODULES;
+ return;
+ }
+ m = _stp_modules[i];
+ write_lock(&m->lock);
+ STP_RUNLOCK_MODULES;
+
+ /* allocate space for unwind data */
+ m->unwind_data = _stp_kmalloc(count);
+ if (unlikely(m->unwind_data == NULL)) {
+ m->unwind_data = _stp_vmalloc(count);
+ if (m->unwind_data == NULL) {
+ errk("kmalloc failed\n");
+ goto done;
}
- rwlock_init(&_stp_modules[0]->lock);
- _stp_symbol_state = 1;
- break;
- case 1:
- dbug(DEBUG_SYMBOLS, "got stap_symbols, count=%d\n", count);
- if (copy_from_user ((char *)_stp_modules[0]->symbols, buf, count))
- return -EFAULT;
- _stp_symbol_state = 2;
- break;
- case 2:
- dbug(DEBUG_SYMBOLS, "got symbol data, count=%d buf=%p\n", count, buf);
- if (copy_from_user (_stp_modules[0]->symbol_data, buf, count))
- return -EFAULT;
- _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[0]->text_size = _stp_modules[0]->data - _stp_modules[0]->text;
- _stp_modules_by_addr[0] = _stp_modules[0];
- dbug(DEBUG_SYMBOLS, "Got kernel symbols. text=%p len=%u\n",
- (int64_t)_stp_modules[0]->text, _stp_modules[0]->text_size);
- break;
- case 3:
- dbug(DEBUG_UNWIND, "got unwind data, count=%d\n", count);
- _stp_symbol_state = 4;
- if (copy_from_user (_stp_modules[0]->unwind_data, buf, count)) {
- _dbug("cfu failed\n");
- return -EFAULT;
+ m->allocated.unwind_data = 1;
+ }
+
+ if (unlikely(copy_from_user(m->unwind_data, buf, count))) {
+ errk("userspace copy failed\n");
+ if (m->unwind_data) {
+ if (m->allocated.unwind_data)
+ _stp_vfree(m->unwind_data);
+ else
+ _stp_kfree(m->unwind_data);
+ m->unwind_data = NULL;
}
- _stp_modules[0]->unwind_data_len = count;
- break;
- default:
- errk("unexpected symbol data of size %d.\n", count);
+ goto done;
}
- return count;
+ m->unwind_data_len = count;
+ _stp_create_unwind_hdr(m);
+done:
+ write_unlock(&m->lock);
}
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;
+ if (s1->addr == s2->addr)
+ return 0;
+ if (s1->addr < s2->addr)
+ return -1;
return 1;
}
@@ -332,18 +351,17 @@ static void generic_swap(void *a, void *b, int size)
* it less suitable for kernel use.
*/
void _stp_sort(void *base, size_t num, size_t size,
- int (*cmp)(const void *, const void *),
- void (*swap)(void *, void *, int size))
+ int (*cmp) (const void *, const void *), void (*swap) (void *, void *, int size))
{
/* pre-scale counters for performance */
- int i = (num/2 - 1) * size, n = num * size, c, r;
+ int i = (num / 2 - 1) * size, n = num * size, c, r;
if (!swap)
swap = (size == 4 ? u32_swap : generic_swap);
/* heapify */
- for ( ; i >= 0; i -= size) {
- for (r = i; r * 2 + size < n; r = c) {
+ for (; i >= 0; i -= size) {
+ for (r = i; r * 2 + size < n; r = c) {
c = r * 2 + size;
if (c < n - size && cmp(base + c, base + c + size) < 0)
c += size;
@@ -367,65 +385,114 @@ void _stp_sort(void *base, size_t num, size_t size,
}
}
+/* filter out section names we don't care about */
+static int _stp_section_is_interesting(const char *name)
+{
+ int ret = 1;
+ if (!strncmp("__", name, 2)
+ || !strncmp(".note", name, 5)
+ || !strncmp(".gnu", name, 4)
+ || !strncmp(".mod", name, 4))
+ ret = 0;
+ return ret;
+}
+
/* Create a new _stp_module and load the symbols */
-static struct _stp_module *_stp_load_module_symbols (struct _stp_module *imod, uint32_t unwind_len)
+static struct _stp_module *_stp_load_module_symbols(struct module *mod)
{
- unsigned i, num=0;
- struct module *m = (struct module *)imod->module;
- struct _stp_module *mod = NULL;
- char *dataptr;
+ int i, num, overflow = 0;
+ struct module_sect_attrs *sa;
+ unsigned sect_size = 0, sect_num = 0, sym_size, sym_num;
+ struct _stp_module *sm;
+ char *dataptr, *endptr;
+
+ sa = mod->sect_attrs;
+ /* calculate how much space to allocate for section strings */
+ for (i = 0; i < sa->nsections; i++) {
+ if (_stp_section_is_interesting(sa->attrs[i].name)) {
+ sect_num++;
+ sect_size += strlen(sa->attrs[i].name) + 1;
+ dbug_sym(2, "\t%s\t%lx\n", sa->attrs[i].name, sa->attrs[i].address);
+ }
+ }
+ sect_size += sect_num * sizeof(struct _stp_symbol);
- if (m == NULL) {
- kbug(DEBUG_SYMBOLS, "imod->module is NULL\n");
+ /* and how much space for symbols */
+ sym_num = _stp_get_sym_sizes(mod, &sym_size);
+
+ sm = _stp_alloc_module(sect_size, sym_num, sym_size);
+ if (!sm) {
+ errk("failed to allocate memory for module.\n");
return NULL;
}
- if (try_module_get(m)) {
- mod = _stp_alloc_module_from_module(m, unwind_len);
- if (mod == NULL) {
- module_put(m);
- errk("failed to allocate memory for module.\n");
- return NULL;
- }
+ strlcpy(sm->name, mod->name, STP_MODULE_NAME_LEN);
+ sm->module = (unsigned long)mod;
+ sm->text = (unsigned long)mod->module_core;
+ sm->text_size = mod->core_text_size;
+ sm->data = 0; /* fixme */
+ sm->num_sections = sect_num;
+ rwlock_init(&sm->lock);
- strlcpy(mod->name, imod->name, STP_MODULE_NAME_LEN);
- mod->module = imod->module;
- mod->text = imod->text;
- mod->data = imod->data;
- mod->num_sections = imod->num_sections;
- mod->sections = imod->sections;
- mod->text_size = m->core_text_size;
- rwlock_init(&mod->lock);
-
- /* now copy all the symbols we are interested in */
- dataptr = mod->symbol_data;
- for (i=0; i < m->num_symtab; i++) {
- char *str = (char *)(m->strtab + m->symtab[i].st_name);
- if (*str != '\0' && _stp_sym_type_ok(m->symtab[i].st_info)) {
- mod->symbols[num].symbol = dataptr;
- mod->symbols[num].addr = m->symtab[i].st_value;
- while (*str) *dataptr++ = *str++;
- *dataptr++ = 0;
- num++;
+ /* copy in section data */
+ dataptr = (char *)((long)sm->sections + sect_num * sizeof(struct _stp_symbol));
+ endptr = (char *)((long)sm->sections + sect_size);
+ num = 0;
+ for (i = 0; i < sa->nsections; i++) {
+ size_t len, maxlen;
+ if (_stp_section_is_interesting(sa->attrs[i].name)) {
+ sm->sections[num].addr = sa->attrs[i].address;
+ sm->sections[num].symbol = dataptr;
+ maxlen = (size_t) (endptr - dataptr);
+ len = strlcpy(dataptr, sa->attrs[i].name, maxlen);
+ if (unlikely(len >= maxlen)) {
+ _dbug("dataptr=%lx endptr=%lx len=%d maxlen=%d\n", dataptr, endptr, len, maxlen);
+ overflow = 1;
}
+ dataptr += len + 1;
+ num++;
}
- module_put(m);
+ }
+ if (unlikely(overflow)) {
+ errk("Section names truncated!!! Should never happen!!\n");
+ *endptr = 0;
+ overflow = 0;
+ }
- /* sort symbols by address */
- _stp_sort (mod->symbols, num, sizeof(struct _stp_symbol), _stp_compare_addr, _stp_swap_symbol);
+ /* now copy all the symbols we are interested in */
+ dataptr = sm->symbol_data;
+ endptr = dataptr + sym_size - 1;
+ num = 0;
+ for (i = 0; i < mod->num_symtab; i++) {
+ char *str = (char *)(mod->strtab + mod->symtab[i].st_name);
+ if (*str != '\0' && _stp_sym_type_ok(mod->symtab[i].st_info)) {
+ sm->symbols[num].symbol = dataptr;
+ sm->symbols[num].addr = mod->symtab[i].st_value;
+ while (*str && (dataptr < endptr))
+ *dataptr++ = *str++;
+ if (unlikely(*str))
+ overflow = 1;
+ *dataptr++ = 0;
+ num++;
+ }
}
- return mod;
+ if (unlikely(overflow))
+ errk("Symbol names truncated!!! Should never happen!!\n");
+
+ /* sort symbols by address */
+ _stp_sort(sm->symbols, num, sizeof(struct _stp_symbol), _stp_compare_addr, _stp_swap_symbol);
+
+ return sm;
}
-/* Remove any old module info from our database */
-static void _stp_module_exists_delete (struct _stp_module *mod)
+/* Remove any old module info from our database. */
+static void _stp_module_exists_delete(struct _stp_module *mod)
{
int i, num;
-
/* remove any old modules with the same name */
for (num = 1; num < _stp_num_modules; num++) {
if (strcmp(_stp_modules[num]->name, mod->name) == 0) {
- dbug(DEBUG_SYMBOLS, "found existing module with name %s. Deleting.\n", mod->name);
+ dbug_sym(1, "found existing module with name %s. Deleting.\n", mod->name);
_stp_del_module(_stp_modules[num]);
break;
}
@@ -435,143 +502,61 @@ static void _stp_module_exists_delete (struct _stp_module *mod)
for (num = 1; num < _stp_num_modules; num++) {
if (mod->text + mod->text_size < _stp_modules_by_addr[num]->text)
continue;
- if (mod->text < _stp_modules_by_addr[num]->text
- + _stp_modules_by_addr[num]->text_size) {
- dbug(DEBUG_SYMBOLS, "New module %s overlaps with old module %s. Deleting old.\n",
- mod->name, _stp_modules_by_addr[num]->name);
+ if (mod->text < _stp_modules_by_addr[num]->text + _stp_modules_by_addr[num]->text_size) {
+ dbug_sym(1, "New module %s overlaps with old module %s. Deleting old.\n",
+ mod->name, _stp_modules_by_addr[num]->name);
_stp_del_module(_stp_modules_by_addr[num]);
}
}
}
-static int _stp_ins_module(struct _stp_module *mod)
+static void _stp_ins_module(struct module *mod)
{
- int i, num, res, ret = 0;
+ int i, num, res;
unsigned long flags;
-
- // kbug(DEBUG_SYMBOLS, "insert %s\n", mod->name);
+ struct _stp_module *m;
+ dbug_sym(1, "insert %s\n", mod->name);
+ m = _stp_load_module_symbols(mod);
+ if (m == NULL)
+ return;
STP_WLOCK_MODULES;
-
- _stp_module_exists_delete(mod);
-
+ _stp_module_exists_delete(m);
/* check for overflow */
if (_stp_num_modules == STP_MAX_MODULES) {
errk("Exceeded the limit of %d modules\n", STP_MAX_MODULES);
- ret = -ENOMEM;
goto done;
}
-
+
/* insert alphabetically in _stp_modules[] */
for (num = 1; num < _stp_num_modules; num++)
- if (strcmp(_stp_modules[num]->name, mod->name) > 0)
+ if (strcmp(_stp_modules[num]->name, m->name) > 0)
break;
for (i = _stp_num_modules; i > num; i--)
- _stp_modules[i] = _stp_modules[i-1];
- _stp_modules[num] = mod;
-
+ _stp_modules[i] = _stp_modules[i - 1];
+ _stp_modules[num] = m;
/* insert by text address in _stp_modules_by_addr[] */
for (num = 1; num < _stp_num_modules; num++)
- if (mod->text < _stp_modules_by_addr[num]->text)
+ if (m->text < _stp_modules_by_addr[num]->text)
break;
for (i = _stp_num_modules; i > num; i--)
- _stp_modules_by_addr[i] = _stp_modules_by_addr[i-1];
- _stp_modules_by_addr[num] = mod;
-
+ _stp_modules_by_addr[i] = _stp_modules_by_addr[i - 1];
+ _stp_modules_by_addr[num] = m;
_stp_num_modules++;
-
done:
STP_WUNLOCK_MODULES;
- return ret;
-}
-
-
-/* Called from procfs.c when a STP_MODULE msg is received */
-static int _stp_do_module(const char __user *buf, int count)
-{
- 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);
- return -EFAULT;
- }
- if (copy_from_user ((char *)&tmpmod, buf, sizeof(tmpmod)))
- return -EFAULT;
-
- section_len = count - sizeof(tmpmod) - tmpmod.unwind_len;
- if (section_len <= 0) {
- errk("section_len = %d\n", section_len);
- return -EFAULT;
- }
- dbug(DEBUG_SYMBOLS, "Got module %s, count=%d section_len=%d unwind_len=%d\n",
- tmpmod.name, count, section_len, tmpmod.unwind_len);
-
- strcpy(mod.name, tmpmod.name);
- mod.module = tmpmod.module;
- mod.text = tmpmod.text;
- mod.data = tmpmod.data;
- mod.num_sections = tmpmod.num_sections;
-
- /* copy in section data */
- mod.sections = _stp_kmalloc(section_len);
- if (mod.sections == NULL) {
- errk("unable to allocate memory.\n");
- return -EFAULT;
- }
- if (copy_from_user ((char *)mod.sections, buf+sizeof(tmpmod), section_len)) {
- _stp_kfree(mod.sections);
- return -EFAULT;
- }
- 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)));
- }
-
- #if 0
- for (i = 0; i < mod.num_sections; i++)
- _dbug("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 */
- m = _stp_load_module_symbols(&mod, tmpmod.unwind_len);
- if (m == NULL) {
- _stp_kfree(mod.sections);
- return 0;
- }
-
- dbug(DEBUG_SYMBOLS, "module %s loaded. Text=%p text_size=%u\n", m->name, (int64_t)m->text, m->text_size);
- /* finally copy unwind info */
- if (copy_from_user (m->unwind_data, buf+sizeof(tmpmod)+section_len, tmpmod.unwind_len)) {
- _stp_free_module(m);
- _stp_kfree(mod.sections);
- return -EFAULT;
- }
- m->unwind_data_len = tmpmod.unwind_len;
-
- if (_stp_ins_module(m) < 0) {
- _stp_free_module(m);
- return -ENOMEM;
- }
-
- return count;
+ return;
}
-static int _stp_ctl_send (int type, void *data, int len);
-
-static int _stp_module_load_notify(struct notifier_block * self, unsigned long val, void * data)
+static int _stp_module_load_notify(struct notifier_block *self, unsigned long val, void *data)
{
struct module *mod = (struct module *)data;
struct _stp_module rmod;
-
switch (val) {
case MODULE_STATE_COMING:
- dbug(DEBUG_SYMBOLS, "module %s load notify\n", mod->name);
- strlcpy(rmod.name, mod->name, STP_MODULE_NAME_LEN);
- _stp_ctl_send(STP_MODULE, &rmod, sizeof(struct _stp_module));
+ dbug_sym(1, "module %s load notify\n", mod->name);
+ _stp_ins_module(mod);
break;
default:
errk("module loaded? val=%ld\n", val);
@@ -583,4 +568,72 @@ static struct notifier_block _stp_module_load_nb = {
.notifier_call = _stp_module_load_notify,
};
-#endif /* _SYMBOLS_C_ */
+#include <linux/seq_file.h>
+
+static int _stp_init_modules(void)
+{
+ loff_t pos = 0;
+ void *res;
+ struct module *mod;
+ const struct seq_operations *modules_op = (const struct seq_operations *)_stp_kallsyms_lookup_name("modules_op");
+
+ if (modules_op == NULL) {
+ _dbug("Lookup of modules_op failed.\n");
+ return -1;
+ }
+
+ /* Use the seq_file interface to safely get a list of installed modules */
+ res = modules_op->start(NULL, &pos);
+ while (res) {
+ mod = list_entry(res, struct module, list);
+ _stp_ins_module(mod);
+ res = modules_op->next(NULL, res, &pos);
+ }
+
+ if (register_module_notifier(&_stp_module_load_nb))
+ errk("failed to load module notifier\n");
+
+ /* unlocks the list */
+ modules_op->stop(NULL, NULL);
+
+#ifdef STP_USE_DWARF_UNWINDER
+ /* now that we have all the modules, ask for their unwind info */
+ {
+ unsigned long flags;
+ int i, left = STP_CTL_BUFFER_SIZE;
+ char buf[STP_CTL_BUFFER_SIZE];
+ char *ptr = buf;
+ *ptr = 0;
+
+ STP_RLOCK_MODULES;
+ /* Loop through modules, sending module names packed into */
+ /* messages of size STP_CTL_BUFFER. */
+ for (i = 0; i < _stp_num_modules; i++) {
+ char *name = _stp_modules[i]->name;
+ int len = strlen(name);
+ if (len >= left) {
+ _stp_ctl_send(STP_UNWIND, buf, sizeof(buf) - left);
+ ptr = buf;
+ left = STP_CTL_BUFFER_SIZE;
+ }
+ strlcpy(ptr, name, left);
+ ptr += len + 1;
+ left -= len + 1;
+ }
+ STP_RUNLOCK_MODULES;
+
+ /* Send terminator. When we get this back from stapio */
+ /* that means all the unwind info has been sent. */
+ strlcpy(ptr, "*", left);
+ left -= 2;
+ _stp_ctl_send(STP_UNWIND, buf, sizeof(buf) - left);
+ }
+#else
+ /* done with modules, now go */
+ _stp_ctl_send(STP_TRANSPORT, NULL, 0);
+#endif /* STP_USE_DWARF_UNWINDER */
+
+ return 0;
+}
+
+#endif /* _STP_SYMBOLS_C_ */
diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c
index 8335e44b..7ff9c8c0 100644
--- a/runtime/transport/transport.c
+++ b/runtime/transport/transport.c
@@ -23,83 +23,47 @@
#include "../procfs.c"
static struct utt_trace *_stp_utt = NULL;
-
+static unsigned int utt_seq = 1;
+static int _stp_probes_started = 0;
+pid_t _stp_target = 0;
+static int _stp_exit_called = 0;
+int _stp_exit_flag = 0;
#ifdef STP_OLD_TRANSPORT
#include "relayfs.c"
+#include "procfs.c"
#else
#include "utt.c"
+#include "control.c"
#endif
-static unsigned int utt_seq = 1;
-
-static int _stp_probes_started = 0;
-
/* module parameters */
static int _stp_bufsize;
module_param(_stp_bufsize, int, 0);
MODULE_PARM_DESC(_stp_bufsize, "buffer size");
-pid_t _stp_target = 0;
-static int _stp_exit_called = 0;
-int _stp_exit_flag = 0;
-
/* forward declarations */
void probe_exit(void);
int probe_start(void);
void _stp_exit(void);
-void _stp_handle_start (struct _stp_msg_start *st);
-static void _stp_detach(void);
-static void _stp_attach(void);
/* check for new workqueue API */
-#ifdef DECLARE_DELAYED_WORK
-static void _stp_work_queue (struct work_struct *data);
+#ifdef DECLARE_DELAYED_WORK
+static void _stp_work_queue(struct work_struct *data);
static DECLARE_DELAYED_WORK(_stp_work, _stp_work_queue);
#else
-static void _stp_work_queue (void *data);
+static void _stp_work_queue(void *data);
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"
-#else
-#include "control.c"
-#endif
-
-static void _stp_ask_for_symbols(void)
-{
- struct _stp_msg_symbol req;
- struct _stp_module mod;
- static int sent_symbols = 0;
-
- if (sent_symbols == 0) {
- /* ask for symbols and modules */
- kbug(DEBUG_SYMBOLS|DEBUG_TRANSPORT, "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;
- }
-}
/*
* _stp_handle_start - handle STP_START
*/
-void _stp_handle_start (struct _stp_msg_start *st)
+void _stp_handle_start(struct _stp_msg_start *st)
{
- kbug (DEBUG_TRANSPORT, "stp_handle_start\n");
-
- if (register_module_notifier(&_stp_module_load_nb))
- errk("failed to load module notifier\n");
-
+ dbug_trans(1, "stp_handle_start\n");
_stp_target = st->target;
st->res = probe_start();
if (st->res >= 0)
@@ -108,16 +72,15 @@ void _stp_handle_start (struct _stp_msg_start *st)
_stp_ctl_send(STP_START, st, sizeof(*st));
}
-
/* common cleanup code. */
/* This is called from the kernel thread when an exit was requested */
/* by staprun or the exit() function. It is also called by transport_close() */
/* when the module is removed. In that case "dont_rmmod" is set to 1. */
/* We need to call it both times because we want to clean up properly */
/* when someone does /sbin/rmmod on a loaded systemtap module. */
-static void _stp_cleanup_and_exit (int dont_rmmod)
+static void _stp_cleanup_and_exit(int dont_rmmod)
{
- kbug(DEBUG_TRANSPORT, "cleanup_and_exit (%d)\n", dont_rmmod);
+ dbug_trans(1, "cleanup_and_exit (%d)\n", dont_rmmod);
if (!_stp_exit_called) {
int failures;
@@ -128,23 +91,24 @@ static void _stp_cleanup_and_exit (int dont_rmmod)
_stp_exit_called = 1;
if (_stp_probes_started) {
- kbug(DEBUG_TRANSPORT, "calling probe_exit\n");
+ dbug_trans(1, "calling probe_exit\n");
/* tell the stap-generated code to unload its probes, etc */
probe_exit();
- kbug(DEBUG_TRANSPORT, "done with probe_exit\n");
+ dbug_trans(1, "done with probe_exit\n");
}
failures = atomic_read(&_stp_transport_failures);
if (failures)
- _stp_warn ("There were %d transport failures.\n", failures);
+ _stp_warn("There were %d transport failures.\n", failures);
- kbug(DEBUG_TRANSPORT, "************** calling startstop 0 *************\n");
- if (_stp_utt) utt_trace_startstop(_stp_utt, 0, &utt_seq);
+ dbug_trans(1, "************** calling startstop 0 *************\n");
+ if (_stp_utt)
+ utt_trace_startstop(_stp_utt, 0, &utt_seq);
- kbug(DEBUG_TRANSPORT, "ctl_send STP_EXIT\n");
+ dbug_trans(1, "ctl_send STP_EXIT\n");
/* tell staprun to exit (if it is still there) */
_stp_ctl_send(STP_EXIT, &dont_rmmod, sizeof(int));
- kbug(DEBUG_TRANSPORT, "done with ctl_send STP_EXIT\n");
+ dbug_trans(1, "done with ctl_send STP_EXIT\n");
}
}
@@ -153,7 +117,7 @@ static void _stp_cleanup_and_exit (int dont_rmmod)
*/
static void _stp_detach(void)
{
- kbug(DEBUG_TRANSPORT, "detach\n");
+ dbug_trans(1, "detach\n");
_stp_attached = 0;
_stp_pid = 0;
@@ -169,10 +133,10 @@ static void _stp_detach(void)
*/
static void _stp_attach(void)
{
- kbug(DEBUG_TRANSPORT, "attach\n");
+ dbug_trans(1, "attach\n");
_stp_attached = 1;
_stp_pid = current->pid;
- utt_set_overwrite(0);
+ utt_set_overwrite(0);
queue_delayed_work(_stp_wq, &_stp_work, STP_WORK_TIMER);
}
@@ -180,10 +144,10 @@ static void _stp_attach(void)
* _stp_work_queue - periodically check for IO or exit
* This is run by a kernel thread and may sleep.
*/
-#ifdef DECLARE_DELAYED_WORK
-static void _stp_work_queue (struct work_struct *data)
+#ifdef DECLARE_DELAYED_WORK
+static void _stp_work_queue(struct work_struct *data)
#else
-static void _stp_work_queue (void *data)
+static void _stp_work_queue(void *data)
#endif
{
int do_io = 0;
@@ -211,19 +175,19 @@ static void _stp_work_queue (void *data)
*/
void _stp_transport_close()
{
- kbug(DEBUG_TRANSPORT, "%d: ************** transport_close *************\n", current->pid);
+ dbug_trans(1, "%d: ************** transport_close *************\n", current->pid);
_stp_cleanup_and_exit(1);
destroy_workqueue(_stp_wq);
_stp_unregister_ctl_channel();
- if (_stp_utt) utt_trace_remove(_stp_utt);
+ if (_stp_utt)
+ utt_trace_remove(_stp_utt);
_stp_free_modules();
_stp_kill_time();
- _stp_print_cleanup(); /* free print buffers */
+ _stp_print_cleanup(); /* free print buffers */
_stp_mem_debug_done();
- kbug(DEBUG_TRANSPORT, "---- CLOSED ----\n");
+ dbug_trans(1, "---- CLOSED ----\n");
}
-
static struct utt_trace *_stp_utt_open(void)
{
struct utt_trace_setup utts;
@@ -249,22 +213,22 @@ int _stp_transport_init(void)
{
int ret;
- kbug(DEBUG_TRANSPORT, "transport_init\n");
+ dbug_trans(1, "transport_init\n");
_stp_init_pid = current->pid;
_stp_uid = current->uid;
_stp_gid = current->gid;
#ifdef RELAY_GUEST
- /* Guest scripts use relay only for reporting warnings and errors */
- _stp_subbuf_size = 65536;
- _stp_nsubbufs = 2;
+ /* Guest scripts use relay only for reporting warnings and errors */
+ _stp_subbuf_size = 65536;
+ _stp_nsubbufs = 2;
#endif
if (_stp_bufsize) {
unsigned size = _stp_bufsize * 1024 * 1024;
_stp_subbuf_size = ((size >> 2) + 1) * 65536;
_stp_nsubbufs = size / _stp_subbuf_size;
- kbug(DEBUG_TRANSPORT, "Using %d subbufs of size %d\n", _stp_nsubbufs, _stp_subbuf_size);
+ dbug_trans(1, "Using %d subbufs of size %d\n", _stp_nsubbufs, _stp_subbuf_size);
}
/* initialize timer code */
@@ -286,41 +250,57 @@ int _stp_transport_init(void)
if (_stp_print_init() < 0)
goto err2;
+ /* start transport */
utt_trace_startstop(_stp_utt, 1, &utt_seq);
/* create workqueue of kernel threads */
_stp_wq = create_workqueue("systemtap");
if (!_stp_wq)
goto err3;
+
+ _stp_transport_state = 1;
+
+ dbug_trans(1, "calling init_kernel_symbols\n");
+ 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:
+ errk("failed to initialize modules\n");
+ _stp_free_modules();
+ destroy_workqueue(_stp_wq);
err3:
_stp_print_cleanup();
err2:
_stp_unregister_ctl_channel();
err1:
- if (_stp_utt) utt_trace_remove(_stp_utt);
+ if (_stp_utt)
+ utt_trace_remove(_stp_utt);
err0:
_stp_kill_time();
return -1;
}
-
static inline void _stp_lock_inode(struct inode *inode)
{
#ifdef DEFINE_MUTEX
- mutex_lock(&inode->i_mutex);
+ mutex_lock(&inode->i_mutex);
#else
- down(&inode->i_sem);
+ down(&inode->i_sem);
#endif
}
static inline void _stp_unlock_inode(struct inode *inode)
{
#ifdef DEFINE_MUTEX
- mutex_unlock(&inode->i_mutex);
+ mutex_unlock(&inode->i_mutex);
#else
- up(&inode->i_sem);
+ up(&inode->i_sem);
#endif
}
@@ -358,7 +338,8 @@ static void _stp_unlock_debugfs(void)
/* utt.c and relayfs.c. Will not be necessary if utt is included */
/* in the kernel. */
-static struct dentry *_stp_get_root_dir(const char *name) {
+static struct dentry *_stp_get_root_dir(const char *name)
+{
struct file_system_type *fs;
struct dentry *root;
struct super_block *sb;
@@ -377,7 +358,6 @@ static struct dentry *_stp_get_root_dir(const char *name) {
errk("Couldn't lock transport directory.\n");
return NULL;
}
-
#ifdef STP_OLD_TRANSPORT
root = relayfs_create_dir(name, NULL);
#else
@@ -389,12 +369,11 @@ static struct dentry *_stp_get_root_dir(const char *name) {
_stp_lock_inode(sb->s_root->d_inode);
root = lookup_one_len(name, sb->s_root, strlen(name));
_stp_unlock_inode(sb->s_root->d_inode);
- kbug(DEBUG_TRANSPORT, "root=%p\n", root);
if (!IS_ERR(root))
dput(root);
else {
root = NULL;
- kbug(DEBUG_TRANSPORT, "Could not create or find transport directory.\n");
+ errk("Could not create or find transport directory.\n");
}
}
_stp_unlock_debugfs();
diff --git a/runtime/transport/transport.h b/runtime/transport/transport.h
index 6dc00d2b..dc499961 100644
--- a/runtime/transport/transport.h
+++ b/runtime/transport/transport.h
@@ -7,21 +7,37 @@
#include "transport_msgs.h"
-void _stp_warn (const char *fmt, ...);
-
+/* The size of print buffers. This limits the maximum */
+/* amount of data a print can send. */
#define STP_BUFFER_SIZE 8192
+/* STP_CTL_BUFFER_SIZE is the maximum size of a message */
+/* exchanged on the control channel. */
+#ifdef STP_OLD_TRANSPORT
+/* Old transport sends print output on control channel */
+#define STP_CTL_BUFFER_SIZE STP_BUFFER_SIZE
+#else
+#define STP_CTL_BUFFER_SIZE 256
+#endif
+
/* how often the work queue wakes up and checks buffers */
#define STP_WORK_TIMER (HZ/100)
static unsigned _stp_nsubbufs = 8;
static unsigned _stp_subbuf_size = 65536*4;
+
+void _stp_warn (const char *fmt, ...);
extern void _stp_transport_close(void);
extern int _stp_print_init(void);
extern void _stp_print_cleanup(void);
static struct dentry *_stp_get_root_dir(const char *name);
static int _stp_lock_debugfs(void);
static void _stp_unlock_debugfs(void);
+static int _stp_ctl_send(int type, void *data, int len);
+static void _stp_attach(void);
+static void _stp_detach(void);
+void _stp_handle_start(struct _stp_msg_start *st);
+
int _stp_pid = 0;
uid_t _stp_uid = 0;
gid_t _stp_gid = 0;
diff --git a/runtime/transport/transport_msgs.h b/runtime/transport/transport_msgs.h
index 55de2d4a..5f385565 100644
--- a/runtime/transport/transport_msgs.h
+++ b/runtime/transport/transport_msgs.h
@@ -23,8 +23,7 @@ enum
STP_EXIT,
STP_OOB_DATA,
STP_SYSTEM,
- STP_SYMBOLS,
- STP_MODULE,
+ STP_UNWIND,
STP_TRANSPORT,
STP_CONNECT,
STP_DISCONNECT,
@@ -36,18 +35,16 @@ enum
STP_SUBBUFS_CONSUMED,
STP_REALTIME_DATA,
#endif
-
STP_MAX_CMD
};
-#ifdef DEBUG_TRANSPORT
+#ifdef DEBUG_TRANS
static const char *_stp_command_name[] = {
"STP_START",
"STP_EXIT",
"STP_OOB_DATA",
"STP_SYSTEM",
- "STP_SYMBOLS",
- "STP_MODULE",
+ "STP_UNWIND",
"STP_TRANSPORT",
"STP_CONNECT",
"STP_DISCONNECT",
@@ -59,68 +56,34 @@ static const char *_stp_command_name[] = {
"STP_REALTIME_DATA",
#endif
};
-#endif /* DEBUG_TRANSPORT */
+#endif /* DEBUG_TRANS */
/* control channel messages */
-/* command to execute: sent to staprun */
+/* command to execute: module->stapio */
struct _stp_msg_cmd
{
char cmd[128];
};
-/* request for symbol data. sent to staprun */
-struct _stp_msg_symbol
+/* Unwind data. stapio->module */
+struct _stp_msg_unwind
{
- int32_t endian;
- int32_t ptr_size;
+ /* the module name, or "*" for all */
+ char name[STP_MODULE_NAME_LEN];
+ /* length of unwind data */
+ uint32_t unwind_len;
+ /* data ...*/
};
/* Request to start probes. */
-/* Sent from staprun. Then returned from module. */
+/* stapio->module->stapio */
struct _stp_msg_start
{
pid_t target;
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