summaryrefslogtreecommitdiffstats
path: root/runtime/transport
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/transport')
-rw-r--r--runtime/transport/ChangeLog23
-rw-r--r--runtime/transport/control.c45
-rw-r--r--runtime/transport/procfs.c38
-rw-r--r--runtime/transport/symbols.c95
-rw-r--r--runtime/transport/transport.c32
-rw-r--r--runtime/transport/transport_msgs.h42
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