summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2008-01-17 21:52:42 -0500
committerFrank Ch. Eigler <fche@elastic.org>2008-01-17 21:52:42 -0500
commit7ee3e80ec0b7880c33d0ca3018025855d9dd5123 (patch)
treec39e234447fed3ca04c6467784fae5ddc85ce7d6
parent2b7f11a05877405a3dd232ac297e11f9d8253c2d (diff)
parentaf3047833424103c4e17728e849670da865d37c3 (diff)
downloadsystemtap-steved-7ee3e80ec0b7880c33d0ca3018025855d9dd5123.tar.gz
systemtap-steved-7ee3e80ec0b7880c33d0ca3018025855d9dd5123.tar.xz
systemtap-steved-7ee3e80ec0b7880c33d0ca3018025855d9dd5123.zip
Merge branch 'master' of git://sources.redhat.com/git/systemtap
-rw-r--r--ChangeLog30
-rw-r--r--runtime/ChangeLog10
-rw-r--r--runtime/alloc.c335
-rw-r--r--runtime/bench2/bench.rb21
-rw-r--r--runtime/counter.c4
-rw-r--r--runtime/map.c26
-rw-r--r--runtime/print.c39
-rw-r--r--runtime/stack-i386.c4
-rw-r--r--runtime/stack-x86_64.c2
-rw-r--r--runtime/staprun/ChangeLog22
-rw-r--r--runtime/staprun/mainloop.c3
-rw-r--r--runtime/staprun/staprun.h5
-rw-r--r--runtime/staprun/staprun_funcs.c36
-rw-r--r--runtime/staprun/symbols.c214
-rw-r--r--runtime/stat.c12
-rw-r--r--runtime/sym.c20
-rw-r--r--runtime/time.c5
-rw-r--r--runtime/transport/ChangeLog29
-rw-r--r--runtime/transport/control.c53
-rw-r--r--runtime/transport/procfs.c58
-rw-r--r--runtime/transport/relayfs.c4
-rw-r--r--runtime/transport/symbols.c109
-rw-r--r--runtime/transport/transport.c35
-rw-r--r--runtime/transport/transport_msgs.h42
-rw-r--r--runtime/transport/utt.c6
-rw-r--r--stapfuncs.5.in23
-rw-r--r--tapset/ChangeLog13
-rw-r--r--tapset/signal.stp163
-rw-r--r--tapsets.cxx142
-rw-r--r--testsuite/ChangeLog22
-rwxr-xr-xtestsuite/buildok/signal-embedded.stp5
-rwxr-xr-xtestsuite/semko/procfs11.stp4
-rwxr-xr-xtestsuite/semko/procfs12.stp4
-rw-r--r--testsuite/systemtap.base/marker.exp40
-rw-r--r--testsuite/systemtap.base/onoffprobe.exp67
-rw-r--r--testsuite/systemtap.base/onoffprobe.stp23
-rw-r--r--translate.cxx25
37 files changed, 1251 insertions, 404 deletions
diff --git a/ChangeLog b/ChangeLog
index 28109604..71cb2001 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+2008-01-17 David Smith <dsmith@redhat.com>
+
+ * tapsets.cxx
+ (procfs_var_expanding_copy_visitor::visit_target_symbol): Print an
+ error when trying to use the procfs target variable '$value' as an
+ array or structure.
+ (perfmon_var_expanding_copy_visitor::visit_target_symbol): Print an
+ error when trying to use the perfmon target variable '$counter as
+ an array or structure.
+
+2008-01-16 David Smith <dsmith@redhat.com>
+
+ PR 5608.
+ * tapsets.cxx
+ (mark_var_expanding_copy_visitor::visit_target_symbol): Print an
+ error when trying to use a marker argument as an array or
+ structure.
+
+2008-01-16 Eugene Teo <eteo@redhat.com>
+
+ * stapfuncs.5.in: Document signal.stp tapset functions.
+
+2008-01-14 Martin Hunt <hunt@redhat.com>
+ * translate.cxx (emit_module_init): Call _stp_print_kernel_info()
+ to print out version information and internal memory usage stats.
+
+2008-01-14 Martin Hunt <hunt@redhat.com>
+ * translate.cxx (emit_module_exit): When using timing, delete timing
+ stats when finished.
+
2008-01-12 Frank Ch. Eigler <fche@elastic.org>
* configure.ac: Generate a build tree SNAPSHOT file from git-rev-list,
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index 8fa11695..7536cc88 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,13 @@
+2008-01-14 Martin Hunt <hunt@redhat.com>
+
+ * print.c (_stp_print_kernel_info): New function.
+ (all): Call stp memory functions.
+
+ * alloc.c: Rewrite to track allocated memory if
+ DEBUG_MEM is defined.
+ * counter.c, map.c, stat.c, time.c: Call stp
+ memory functions.
+
2007-11-14 Zhaolei <zhaolei@cn.fujitsu.com>
From Cai Fei <caifei@cn.fujitsu.com>
diff --git a/runtime/alloc.c b/runtime/alloc.c
index 8f2a7451..f022755a 100644
--- a/runtime/alloc.c
+++ b/runtime/alloc.c
@@ -1,6 +1,6 @@
/* -*- linux-c -*-
* Memory allocation functions
- * Copyright (C) 2005, 2006, 2007 Red Hat Inc.
+ * Copyright (C) 2005-2008 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
@@ -11,55 +11,356 @@
#ifndef _ALLOC_C_
#define _ALLOC_C_
-/* counters of how much memory has been allocated */
-static int _stp_allocated_memory = 0;
static int _stp_allocated_net_memory = 0;
-
#define STP_ALLOC_FLAGS (GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN)
+//#define DEBUG_MEM
+/*
+ * If DEBUG_MEM is defined (stap -DDEBUG_MEM ...) then full memory
+ * tracking is used. Each allocation is recorded and matched with
+ * a free. Also a fence is set around the allocated memory so overflows
+ * and underflows can be detected. Errors are written to the system log
+ * with printk.
+ *
+ * NOTE: if youy system is slow or your script makes a very large number
+ * of allocations, you may get a warning in the system log:
+ * BUG: soft lockup - CPU#1 stuck for 11s! [staprun:28269]
+ * This is an expected side-effect of the overhead of tracking, especially
+ * with a simple linked list of allocations. Optimization
+ * would be nice, but DEBUG_MEM is only for testing.
+ */
+
+#ifdef DEBUG_MEM
+
+static spinlock_t _stp_mem_lock = SPIN_LOCK_UNLOCKED;
+static int _stp_allocated_memory = 0;
+
+#define MEM_MAGIC 0xc11cf77f
+#define MEM_FENCE_SIZE 32
+
+enum _stp_memtype { MEM_KMALLOC, MEM_VMALLOC, MEM_PERCPU };
+
+typedef struct {
+ enum _stp_memtype type;
+ char *alloc;
+ char *free;
+} _stp_malloc_type;
+
+static const _stp_malloc_type const _stp_malloc_types[] = {
+ {MEM_KMALLOC, "kmalloc", "kfree"},
+ {MEM_VMALLOC, "vmalloc", "vfree"},
+ {MEM_PERCPU, "alloc_percpu", "free_percpu"}
+};
+
+struct _stp_mem_entry {
+ struct list_head list;
+ int32_t magic;
+ enum _stp_memtype type;
+ size_t len;
+ void *addr;
+};
+
+#define MEM_DEBUG_SIZE (2*MEM_FENCE_SIZE+sizeof(struct _stp_mem_entry))
+
+static LIST_HEAD(_stp_mem_list);
+
+void _stp_check_mem_fence (char *addr, int size)
+{
+ char *ptr;
+ int i;
+
+ ptr = addr - MEM_FENCE_SIZE;
+ while (ptr < addr) {
+ if (*ptr != 0x55) {
+ printk("SYSTEMTAP ERROR: Memory fence corrupted before allocated memory\n");
+ printk("at addr %p. (Allocation starts at %p)", ptr, addr);
+ return;
+ }
+ ptr++;
+ }
+ ptr = addr + size;
+ while (ptr < addr + size + MEM_FENCE_SIZE) {
+ if (*ptr != 0x55) {
+ printk("SYSTEMTAP ERROR: Memory fence corrupted after allocated memory\n");
+ printk("at addr %p. (Allocation ends at %p)", ptr, addr + size - 1);
+ return;
+ }
+ ptr++;
+ }
+}
+
+void *_stp_mem_debug_setup(void *addr, size_t size, enum _stp_memtype type)
+{
+ struct list_head *p;
+ struct _stp_mem_entry *m;
+ memset(addr, 0x55, MEM_FENCE_SIZE);
+ addr += MEM_FENCE_SIZE;
+ memset(addr + size, 0x55, MEM_FENCE_SIZE);
+ p = (struct list_head *)(addr + size + MEM_FENCE_SIZE);
+ m = (struct _stp_mem_entry *)p;
+ m->magic = MEM_MAGIC;
+ m->type = type;
+ m->len = size;
+ m->addr = addr;
+ spin_lock(&_stp_mem_lock);
+ list_add(p, &_stp_mem_list);
+ spin_unlock(&_stp_mem_lock);
+ return addr;
+}
+
+/* Percpu allocations don't have the fence. Implementing it is problematic. */
+void _stp_mem_debug_percpu(struct _stp_mem_entry *m, void *addr, size_t size)
+{
+ struct list_head *p = (struct list_head *)m;
+ m->magic = MEM_MAGIC;
+ m->type = MEM_PERCPU;
+ m->len = size;
+ m->addr = addr;
+ spin_lock(&_stp_mem_lock);
+ list_add(p, &_stp_mem_list);
+ spin_unlock(&_stp_mem_lock);
+}
+
+void _stp_mem_debug_free(void *addr, enum _stp_memtype type)
+{
+ int found = 0;
+ struct list_head *p, *tmp;
+ struct _stp_mem_entry *m = NULL;
+
+ spin_lock(&_stp_mem_lock);
+ list_for_each_safe(p, tmp, &_stp_mem_list) {
+ m = list_entry(p, struct _stp_mem_entry, list);
+ if (m->addr == addr) {
+ list_del(p);
+ found = 1;
+ break;
+ }
+ }
+ spin_unlock(&_stp_mem_lock);
+ if (!found) {
+ printk("SYSTEMTAP ERROR: Free of unallocated memory %p type=%s\n",
+ addr, _stp_malloc_types[type].free);
+ return;
+ }
+ if (m->magic != MEM_MAGIC) {
+ printk("SYSTEMTAP ERROR: Memory at %p corrupted!!\n", addr);
+ return;
+ }
+ if (m->type != type) {
+ printk("SYSTEMTAP ERROR: Memory allocated with %s and freed with %s\n",
+ _stp_malloc_types[m->type].alloc,
+ _stp_malloc_types[type].free);
+ }
+
+ switch (m->type) {
+ case MEM_KMALLOC:
+ _stp_check_mem_fence(addr, m->len);
+ kfree(addr - MEM_FENCE_SIZE);
+ break;
+ case MEM_PERCPU:
+ free_percpu(addr);
+ kfree(p);
+ break;
+ case MEM_VMALLOC:
+ _stp_check_mem_fence(addr, m->len);
+ vfree(addr - MEM_FENCE_SIZE);
+ break;
+ default:
+ printk("SYSTEMTAP ERROR: Attempted to free memory at addr %p len=%d with unknown allocation type.\n", addr, (int)m->len);
+ }
+
+ return;
+}
+#endif
+
static void *_stp_kmalloc(size_t size)
{
- void *ret = kmalloc(size, STP_ALLOC_FLAGS);
- if (ret)
+#ifdef DEBUG_MEM
+ void *ret = kmalloc(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS);
+ if (likely(ret)) {
+ ret = _stp_mem_debug_setup(ret, size, MEM_KMALLOC);
_stp_allocated_memory += size;
+ }
return ret;
+#else
+ return kmalloc(size, STP_ALLOC_FLAGS);
+#endif
}
static void *_stp_kzalloc(size_t size)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
{
- void *ret = kmalloc(size, STP_ALLOC_FLAGS);
- if (ret) {
+#ifdef DEBUG_MEM
+ void *ret = kmalloc(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS);
+ if (likely(ret)) {
+ ret = _stp_mem_debug_setup(ret, size, MEM_KMALLOC);
memset (ret, 0, size);
_stp_allocated_memory += size;
}
+#else
+ void *ret = kmalloc(size, STP_ALLOC_FLAGS);
+ if (likely(ret))
+ memset (ret, 0, size);
+#endif /* DEBUG_MEM */
return ret;
}
-#else
+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) */
{
- void *ret = kzalloc(size, STP_ALLOC_FLAGS);
- if (ret)
+#ifdef DEBUG_MEM
+ void *ret = kzalloc(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS);
+ if (likely(ret)) {
+ ret = _stp_mem_debug_setup(ret, size, MEM_KMALLOC);
_stp_allocated_memory += size;
+ }
return ret;
-}
+#else
+ return kzalloc(size, STP_ALLOC_FLAGS);
#endif
+}
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) */
static void *_stp_vmalloc(unsigned long size)
{
- void *ret = __vmalloc(size, STP_ALLOC_FLAGS, PAGE_KERNEL);
- if (ret)
+#ifdef DEBUG_MEM
+ void *ret = __vmalloc(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS, PAGE_KERNEL);
+ if (likely(ret)) {
+ ret = _stp_mem_debug_setup(ret, size, MEM_VMALLOC);
_stp_allocated_memory += size;
+ }
return ret;
+#else
+ return __vmalloc(size, STP_ALLOC_FLAGS, PAGE_KERNEL);
+#endif
+
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
-#define _stp_alloc_percpu(size) __alloc_percpu(size, 8)
+static void *_stp_alloc_percpu(size_t size)
+{
+#ifdef DEBUG_MEM
+ void *ret = __alloc_percpu(size, 8);
+ if (likely(ret)) {
+ struct _stp_mem_entry *m = kmalloc(sizeof(struct _stp_mem_entry), STP_ALLOC_FLAGS);
+ if (unlikely(m == NULL)) {
+ free_percpu(ret);
+ return NULL;
+ }
+ _stp_mem_debug_percpu(m, ret, size);
+ _stp_allocated_memory += size * num_online_cpus();
+ }
+ return ret;
#else
-#define _stp_alloc_percpu(size) __alloc_percpu(size)
+ return __alloc_percpu(size, 8);
#endif
+}
+#else
+static void *_stp_alloc_percpu(size_t size)
+{
+#ifdef DEBUG_MEM
+ void *ret = __alloc_percpu(size);
+ if (likely(ret)) {
+ struct _stp_mem_entry *m = kmalloc(sizeof(struct _stp_mem_entry), STP_ALLOC_FLAGS);
+ if (unlikely(m == NULL)) {
+ free_percpu(ret);
+ return NULL;
+ }
+ _stp_mem_debug_percpu(m, ret, size);
+ _stp_allocated_memory += size * num_online_cpus();
+ }
+ return ret;
+#else
+ return __alloc_percpu(size);
+#endif
+}
+#endif /* LINUX_VERSION_CODE */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
-#define kmalloc_node(size,flags,node) kmalloc(size,flags)
+#define _stp_kmalloc_node(size,node) _stp_kmalloc(size)
+#else
+static void *_stp_kmalloc_node(size_t size, int node)
+{
+#ifdef DEBUG_MEM
+ void *ret = kmalloc_node(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS, node);
+ if (likely(ret)) {
+ ret = _stp_mem_debug_setup(ret, size, MEM_KMALLOC);
+ _stp_allocated_memory += size;
+ }
+ return ret;
+#else
+ return kmalloc_node(size, STP_ALLOC_FLAGS, node);
+#endif
+}
#endif /* LINUX_VERSION_CODE */
+void _stp_kfree(void *addr)
+{
+#ifdef DEBUG_MEM
+ _stp_mem_debug_free(addr, MEM_KMALLOC);
+#else
+ kfree(addr);
+#endif
+}
+
+void _stp_vfree(void *addr)
+{
+#ifdef DEBUG_MEM
+ _stp_mem_debug_free(addr, MEM_VMALLOC);
+#else
+ vfree(addr);
+#endif
+}
+
+void _stp_free_percpu(void *addr)
+{
+#ifdef DEBUG_MEM
+ _stp_mem_debug_free(addr, MEM_PERCPU);
+#else
+ free_percpu(addr);
+#endif
+}
+
+void _stp_mem_debug_done(void)
+{
+#ifdef DEBUG_MEM
+ struct list_head *p, *tmp;
+ struct _stp_mem_entry *m;
+
+ spin_lock(&_stp_mem_lock);
+ list_for_each_safe(p, tmp, &_stp_mem_list) {
+ m = list_entry(p, struct _stp_mem_entry, list);
+ list_del(p);
+
+ printk("SYSTEMTAP ERROR: Memory %p len=%d allocation type: %s. Not freed.\n",
+ m->addr, (int)m->len, _stp_malloc_types[m->type].alloc);
+
+ if (m->magic != MEM_MAGIC) {
+ printk("SYSTEMTAP ERROR: Memory at %p len=%d corrupted!!\n", m->addr, (int)m->len);
+ /* Don't free. Too dangerous */
+ goto done;
+ }
+
+ switch (m->type) {
+ case MEM_KMALLOC:
+ _stp_check_mem_fence(m->addr, m->len);
+ kfree(m->addr - MEM_FENCE_SIZE);
+ break;
+ case MEM_PERCPU:
+ free_percpu(m->addr);
+ kfree(p);
+ break;
+ case MEM_VMALLOC:
+ _stp_check_mem_fence(m->addr, m->len);
+ vfree(m->addr - MEM_FENCE_SIZE);
+ break;
+ default:
+ printk("SYSTEMTAP ERROR: Attempted to free memory at addr %p len=%d with unknown allocation type.\n", m->addr, (int)m->len);
+ }
+ }
+done:
+ spin_unlock(&_stp_mem_lock);
+
+ return;
+
+#endif
+}
#endif /* _ALLOC_C_ */
diff --git a/runtime/bench2/bench.rb b/runtime/bench2/bench.rb
index a671b582..b3e30204 100644
--- a/runtime/bench2/bench.rb
+++ b/runtime/bench2/bench.rb
@@ -138,9 +138,8 @@ class Bench
end
def load
- args = "-q"
- fork do exec "sudo #{@@staprun} #{args} -o #{@outfile} #{@dir}/bench.ko &> #{@dir}/xxx.out" end
- sleep 10
+ fork do exec "sudo #{@@staprun} -o #{@outfile} #{@dir}/bench.ko &> #{@dir}/xxx.out" end
+ sleep 5
end
def compile
@@ -287,10 +286,8 @@ class Stapbench < Bench
protected
def load
- args = "-vv -DSTP_NO_OVERLOAD"
- if @trans == BULK then args = "-bvv -DSTP_NO_OVERLOAD" end
- fork do exec "stap #{args} -o #{@outfile} bench.stp &> xxx.out" end
- sleep 30
+ fork do exec "sudo #{@@staprun} bench.ko &> xxx.out" end
+ sleep 5
end
def compile
@@ -316,6 +313,14 @@ class Stapbench < Bench
else
puts "NO CODE!"
end
+ args = "-p4 -vv -DSTP_NO_OVERLOAD"
+ if @trans == BULK then args = "-p4 -bvv -DSTP_NO_OVERLOAD" end
+ `stap #{args} -m bench.ko bench.stp &> xxx.out`
+ if ($? != 0)
+ puts "compile failed. status=#{$?}"
+ system("tail xxx.out")
+ exit
+ end
end
-
+
end
diff --git a/runtime/counter.c b/runtime/counter.c
index def734f6..42555dfa 100644
--- a/runtime/counter.c
+++ b/runtime/counter.c
@@ -54,7 +54,7 @@ typedef struct _counter *Counter;
*/
Counter _stp_counter_init (void)
{
- Counter cnt = alloc_percpu (struct _counter);
+ Counter cnt = _stp_alloc_percpu (struct _counter);
#if NEED_COUNTER_LOCKS == 1
{
int i;
@@ -135,7 +135,7 @@ int64_t _stp_counter_get (Counter cnt, int clear)
*/
void _stp_counter_free (Counter cnt)
{
- free_percpu (cnt);
+ _stp_free_percpu (cnt);
}
/** @} */
diff --git a/runtime/map.c b/runtime/map.c
index 2acf2fe2..70990876 100644
--- a/runtime/map.c
+++ b/runtime/map.c
@@ -205,18 +205,13 @@ static int _stp_map_init(MAP m, unsigned max_entries, int type, int key_size, in
for (i = 0; i < max_entries; i++) {
if (cpu < 0)
- tmp = kmalloc(size, STP_ALLOC_FLAGS);
+ tmp = _stp_kmalloc(size);
else
- tmp = kmalloc_node(size, STP_ALLOC_FLAGS, cpu_to_node(cpu));
+ tmp = _stp_kmalloc_node(size, cpu_to_node(cpu));
if (!tmp)
return -1;
- if (cpu < 0)
- _stp_allocated_memory += size;
- else
- _stp_allocated_memory += size * num_online_cpus();
-
// dbug ("allocated %lx\n", (long)tmp);
list_add((struct list_head *)tmp, &m->pool);
((struct map_node *)tmp)->map = m;
@@ -252,10 +247,9 @@ static PMAP _stp_pmap_new(unsigned max_entries, int type, int key_size, int data
if (pmap == NULL)
return NULL;
- pmap->map = map = (MAP) alloc_percpu (struct map_root);
+ pmap->map = map = (MAP) _stp_alloc_percpu (sizeof(struct map_root));
if (map == NULL)
goto err;
- _stp_allocated_memory += sizeof(struct map_root) * num_online_cpus();
/* initialize the memory lists first so if allocations fail */
/* at some point, it is easy to clean up. */
@@ -284,9 +278,9 @@ err1:
m = per_cpu_ptr (map, i);
__stp_map_del(m);
}
- free_percpu(map);
+ _stp_free_percpu(map);
err:
- kfree(pmap);
+ _stp_kfree(pmap);
return NULL;
}
@@ -387,13 +381,13 @@ static void __stp_map_del(MAP map)
/* free unused pool */
list_for_each_safe(p, tmp, &map->pool) {
list_del(p);
- kfree(p);
+ _stp_kfree(p);
}
/* free used list */
list_for_each_safe(p, tmp, &map->head) {
list_del(p);
- kfree(p);
+ _stp_kfree(p);
}
}
@@ -409,7 +403,7 @@ void _stp_map_del(MAP map)
__stp_map_del(map);
- kfree(map);
+ _stp_kfree(map);
}
void _stp_pmap_del(PMAP pmap)
@@ -423,12 +417,12 @@ void _stp_pmap_del(PMAP pmap)
MAP m = per_cpu_ptr (pmap->map, i);
__stp_map_del(m);
}
- free_percpu(pmap->map);
+ _stp_free_percpu(pmap->map);
/* free agg map elements */
__stp_map_del(&pmap->agg);
- kfree(pmap);
+ _stp_kfree(pmap);
}
/* sort keynum values */
diff --git a/runtime/print.c b/runtime/print.c
index a451f622..0442ba09 100644
--- a/runtime/print.c
+++ b/runtime/print.c
@@ -1,6 +1,6 @@
/* -*- linux-c -*-
* Print Functions
- * Copyright (C) 2007 Red Hat Inc.
+ * Copyright (C) 2007-2008 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
@@ -50,26 +50,25 @@ void *Stp_lbuf = NULL;
/* create percpu print and io buffers */
int _stp_print_init (void)
{
- Stp_pbuf = alloc_percpu(_stp_pbuf);
+ Stp_pbuf = _stp_alloc_percpu(sizeof(_stp_pbuf));
if (unlikely(Stp_pbuf == 0))
return -1;
/* now initialize IO buffer used in io.c */
- Stp_lbuf = alloc_percpu(_stp_lbuf);
+ Stp_lbuf = _stp_alloc_percpu(sizeof(_stp_lbuf));
if (unlikely(Stp_lbuf == 0)) {
- free_percpu(Stp_pbuf);
+ _stp_free_percpu(Stp_pbuf);
return -1;
}
- _stp_allocated_memory += (sizeof(_stp_pbuf)+sizeof(_stp_lbuf)) * num_online_cpus();
return 0;
}
void _stp_print_cleanup (void)
{
if (Stp_pbuf)
- free_percpu(Stp_pbuf);
+ _stp_free_percpu(Stp_pbuf);
if (Stp_lbuf)
- free_percpu(Stp_lbuf);
+ _stp_free_percpu(Stp_lbuf);
}
#define __DEF_EXPORT_FN(fn, postfix) fn ## _ ## postfix
@@ -276,5 +275,31 @@ static char *next_fmt(char *fmt, int *num)
return f;
}
+void _stp_print_kernel_info(char *vstr, int ctx, int num_probes)
+{
+#ifdef DEBUG_MEM
+ printk(KERN_DEBUG "%s: systemtap: %s, base: %p, memory: %lu+%lu+%u+%u+%u data+text+ctx+net+alloc, probes: %d\n",
+ THIS_MODULE->name,
+ vstr,
+ THIS_MODULE->module_core,
+ (unsigned long) (THIS_MODULE->core_size - THIS_MODULE->core_text_size),
+ (unsigned long) THIS_MODULE->core_text_size,
+ ctx,
+ _stp_allocated_net_memory,
+ _stp_allocated_memory - _stp_allocated_net_memory,
+ num_probes);
+#else
+ printk(KERN_DEBUG "%s: systemtap: %s, base: %p, memory: %lu+%lu+%u+%u data+text+ctx+net, probes: %d\n",
+ THIS_MODULE->name,
+ vstr,
+ THIS_MODULE->module_core,
+ (unsigned long) (THIS_MODULE->core_size - THIS_MODULE->core_text_size),
+ (unsigned long) THIS_MODULE->core_text_size,
+ ctx,
+ _stp_allocated_net_memory,
+ num_probes);
+#endif
+}
+
/** @} */
#endif /* _PRINT_C_ */
diff --git a/runtime/stack-i386.c b/runtime/stack-i386.c
index a80de048..3675fc97 100644
--- a/runtime/stack-i386.c
+++ b/runtime/stack-i386.c
@@ -1,6 +1,6 @@
/* -*- linux-c -*-
* i386 stack tracing functions
- * Copyright (C) 2005, 2006, 2007 Red Hat Inc.
+ * Copyright (C) 2005-2008 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
@@ -37,7 +37,7 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels)
#else
while (_stp_valid_stack_ptr(context, (unsigned long)stack)) {
addr = *stack++;
- _stp_func_print(addr, verbose);
+ _stp_func_print(addr, verbose, 1);
}
#endif
}
diff --git a/runtime/stack-x86_64.c b/runtime/stack-x86_64.c
index 16e3bf7c..186b2ad4 100644
--- a/runtime/stack-x86_64.c
+++ b/runtime/stack-x86_64.c
@@ -15,6 +15,6 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels)
while ((long)stack & (THREAD_SIZE-1)) {
addr = *stack++;
- _stp_func_print(addr, verbose);
+ _stp_func_print(addr, verbose, 1);
}
}
diff --git a/runtime/staprun/ChangeLog b/runtime/staprun/ChangeLog
index a7b00a9c..3f373863 100644
--- a/runtime/staprun/ChangeLog
+++ b/runtime/staprun/ChangeLog
@@ -1,3 +1,25 @@
+2008-01-14 Martin Hunt <hunt@redhat.com>
+
+ PR4037 and fixes to better synchronize staprun and stapio.
+ * symbols.c (send_data): Send header and data seperately, saving
+ a memcpy and avoiding any alignment issues.
+ (get_sections): Return -1 on error instead of just exiting
+ and leaving stapio hanging. Send data in proper format even if kernel
+ pointers are different size.
+ (send_module): Return -1 on error instead of just exiting
+ and leaving stapio hanging.
+ (do_module): Ditto.
+ (compar): Removed.
+ (do_kernel_symbols): Rewrite to be more robust. Return -1 on
+ error instead of just exiting and leaving stapio hanging.
+
+ * staprun_funcs.c (handle_symbols): Signal stapio if we error out.
+ Set kernel_ptr_size;
+
+ * staprun.h (kernel_ptr_size): Declare.
+
+ * mainloop.c (stp_main_loop): When ready, send STP_READY.
+
2008-01-12 Frank Ch. Eigler <fche@elastic.org>
PR 5603 horrible hack.
diff --git a/runtime/staprun/mainloop.c b/runtime/staprun/mainloop.c
index d8975d18..2e0c3c5c 100644
--- a/runtime/staprun/mainloop.c
+++ b/runtime/staprun/mainloop.c
@@ -7,7 +7,7 @@
* Public License (GPL); either version 2, or (at your option) any
* later version.
*
- * Copyright (C) 2005-2007 Red Hat Inc.
+ * Copyright (C) 2005-2008 Red Hat Inc.
*/
#include "staprun.h"
@@ -255,6 +255,7 @@ int stp_main_loop(void)
setup_main_signals(0);
dbug(2, "in main loop\n");
+ send_request(STP_READY, NULL, 0);
while (1) { /* handle messages from control channel */
nb = read(control_channel, recvbuf, sizeof(recvbuf));
diff --git a/runtime/staprun/staprun.h b/runtime/staprun/staprun.h
index c22cc4f3..1128fb4c 100644
--- a/runtime/staprun/staprun.h
+++ b/runtime/staprun/staprun.h
@@ -7,7 +7,7 @@
* Public License (GPL); either version 2, or (at your option) any
* later version.
*
- * Copyright (C) 2005-2007 Red Hat Inc.
+ * Copyright (C) 2005-2008 Red Hat Inc.
*/
#include <stdio.h>
@@ -119,7 +119,7 @@ int stp_main_loop(void);
int send_request(int type, void *data, int len);
void cleanup_and_exit (int);
int do_module(void *);
-void do_kernel_symbols(void);
+int do_kernel_symbols(void);
int init_ctl_channel(int);
void close_ctl_channel(void);
int init_relayfs(void);
@@ -156,6 +156,7 @@ int set_clexec(int fd);
extern int control_channel;
extern int ncpus;
extern int initialized;
+extern int kernel_ptr_size;
/* flags */
extern int verbose;
diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c
index 86a72985..ebf05b34 100644
--- a/runtime/staprun/staprun_funcs.c
+++ b/runtime/staprun/staprun_funcs.c
@@ -7,7 +7,7 @@
* Public License (GPL); either version 2, or (at your option) any
* later version.
*
- * Copyright (C) 2007 Red Hat Inc.
+ * Copyright (C) 2007-2008 Red Hat Inc.
*/
#include "staprun.h"
@@ -16,6 +16,8 @@
#include <grp.h>
#include <pwd.h>
+void cleanup(int rc);
+
void setup_staprun_signals(void)
{
struct sigaction a;
@@ -386,18 +388,20 @@ int check_permissions(void)
}
pthread_t symbol_thread_id = (pthread_t)0;
+int kernel_ptr_size = 0;
/* Symbol handling thread */
void *handle_symbols(void __attribute__((unused)) *arg)
{
ssize_t nb;
void *data;
- int type;
+ int32_t type;
char recvbuf[8192];
dbug(2, "waiting for symbol requests\n");
- while (1) { /* handle messages from control channel */
+ /* handle messages from control channel */
+ while (1) {
nb = read(control_channel, recvbuf, sizeof(recvbuf));
if (nb <= 0) {
if (errno != EINTR)
@@ -405,14 +409,15 @@ void *handle_symbols(void __attribute__((unused)) *arg)
continue;
}
- type = *(int *)recvbuf;
- data = (void *)(recvbuf + sizeof(int));
-
+ type = *(int32_t *)recvbuf;
+ data = (void *)(recvbuf + sizeof(int32_t));
+
switch (type) {
case STP_MODULE:
{
dbug(2, "STP_MODULES request received\n");
- do_module(data);
+ if (do_module(data) < 0)
+ goto done;
break;
}
case STP_SYMBOLS:
@@ -421,14 +426,15 @@ void *handle_symbols(void __attribute__((unused)) *arg)
dbug(2, "STP_SYMBOLS request received\n");
if (req->endian != 0x1234) {
err("ERROR: staprun is compiled with different endianess than the kernel!\n");
- exit(1);
+ goto done;
}
- if (req->ptr_size != sizeof(char *)) {
- err("ERROR: staprun is compiled with %d-bit pointers and the kernel uses %d-bit.\n",
- 8*(int)sizeof(char *), 8*req->ptr_size);
- exit(1);
+ kernel_ptr_size = req->ptr_size;
+ if (kernel_ptr_size != 4 && kernel_ptr_size != 8) {
+ err("ERROR: invalid kernel pointer size %d\n", kernel_ptr_size);
+ goto done;
}
- do_kernel_symbols();
+ if (do_kernel_symbols() < 0)
+ goto done;
break;
}
default:
@@ -436,6 +442,10 @@ void *handle_symbols(void __attribute__((unused)) *arg)
}
}
+done:
+ /* signal stapio we're done */
+ kill(0, SIGINT);
+
return NULL;
}
diff --git a/runtime/staprun/symbols.c b/runtime/staprun/symbols.c
index e4d96ee0..5a4855b3 100644
--- a/runtime/staprun/symbols.c
+++ b/runtime/staprun/symbols.c
@@ -1,7 +1,7 @@
/* -*- linux-c -*-
* Symbols and modules functions for staprun.
*
- * Copyright (C) 2006, 2007 Red Hat Inc.
+ * Copyright (C) 2006-2008 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
@@ -10,16 +10,19 @@
*/
#include "staprun.h"
-#include "../sym.h"
+/* send symbol data */
static int send_data(void *data, int len)
{
+ int32_t type = STP_SYMBOLS;
+ if (write(control_channel, &type, 4) <= 0)
+ return -1;
return write(control_channel, data, len);
}
/* Get the sections for a module. Put them in the supplied buffer */
/* in the following order: */
-/* [struct _stp_module][struct _stp_symbol sections ...][string data] */
+/* [struct _stp_msg_module][struct _stp_symbol sections ...][string data]*/
/* Return the total length of all the data. */
#define SECDIR "/sys/module/%s/sections"
@@ -30,33 +33,35 @@ static int get_sections(char *name, char *data_start, int datalen)
char buf[32], strdata_start[32768];
char *strdata=strdata_start, *data=data_start;
int fd, len, res;
- struct _stp_module *mod = (struct _stp_module *)data_start;
+ struct _stp_msg_module *mod = (struct _stp_msg_module *)data_start;
struct dirent *d;
DIR *secdir;
- struct _stp_symbol *sec;
+ void *sec;
+ int struct_symbol_size = kernel_ptr_size == 8 ? sizeof(struct _stp_symbol64) : sizeof(struct _stp_symbol32);
+ uint64_t sec_addr;
- /* start of data is a struct _stp_module */
- data += sizeof(struct _stp_module);
+ /* start of data is a struct _stp_msg_module */
+ data += sizeof(struct _stp_msg_module);
res = snprintf(dir, sizeof(dir), SECDIR, name);
if (res >= (int)sizeof(dir)) {
_err("Couldn't fit module \"%s\" into dir buffer.\n" \
"This should never happen. Please file a bug report.\n", name);
- exit(1);
+ return -1;
}
if ((secdir = opendir(dir)) == NULL)
return 0;
/* Initialize mod. */
- memset(mod, 0, sizeof(struct _stp_module));
+ memset(mod, 0, sizeof(struct _stp_msg_module));
/* Copy name in and check for overflow. */
strncpy(mod->name, name, STP_MODULE_NAME_LEN);
if (mod->name[STP_MODULE_NAME_LEN - 1] != '\0') {
_err("Couldn't fit module \"%s\" into mod->name buffer.\n" \
"This should never happen. Please file a bug report.\n", name);
- exit(1);
+ return -1;
}
while ((d = readdir(secdir))) {
@@ -68,7 +73,7 @@ static int get_sections(char *name, char *data_start, int datalen)
_err("Couldn't fit secname \"%s\" into filename buffer.\n" \
"This should never happen. Please file a bug report.\n", secname);
closedir(secdir);
- exit(1);
+ return -1;
}
/* filter out some non-useful stuff */
@@ -88,12 +93,19 @@ static int get_sections(char *name, char *data_start, int datalen)
if ((fd = open(filename,O_RDONLY)) >= 0) {
if (read(fd, buf, 32) > 0) {
/* create next section */
- sec = (struct _stp_symbol *)data;
- if (data - data_start + (int)sizeof(struct _stp_symbol) > datalen)
+ sec = data;
+ if (data - data_start + struct_symbol_size > datalen)
goto err1;
- data += sizeof(struct _stp_symbol);
- sec->addr = strtoul(buf,NULL,16);
- sec->symbol = (char *)(strdata - strdata_start);
+ data += struct_symbol_size;
+
+ sec_addr = (uint64_t)strtoull(buf,NULL,16);
+ if (kernel_ptr_size == 8) {
+ ((struct _stp_symbol64 *)sec)->addr = sec_addr;
+ ((struct _stp_symbol64 *)sec)->symbol = (uint64_t)(strdata - strdata_start);
+ } else {
+ ((struct _stp_symbol32 *)sec)->addr = (uint32_t)sec_addr;
+ ((struct _stp_symbol32 *)sec)->symbol = (uint32_t)(strdata - strdata_start);
+ }
mod->num_sections++;
/* now create string data for the
@@ -106,13 +118,13 @@ static int get_sections(char *name, char *data_start, int datalen)
/* These sections are used a lot so keep the values handy */
if (!strcmp(secname, ".data") || !strncmp(secname, ".rodata", 7)) {
- if (mod->data == 0 || sec->addr < mod->data)
- mod->data = sec->addr;
+ if (mod->data == 0 || sec_addr < mod->data)
+ mod->data = sec_addr;
}
if (!strcmp(secname, ".text"))
- mod->text = sec->addr;
+ mod->text = sec_addr;
if (!strcmp(secname, ".gnu.linkonce.this_module"))
- mod->module = sec->addr;
+ mod->module = sec_addr;
}
close(fd);
}
@@ -135,56 +147,55 @@ err1:
err0:
/* if this happens, something went seriously wrong. */
_err("Unexpected error. Overflowed buffers.\n");
- exit(1);
- return 0; /* not reached */
+ return -1;
}
#undef SECDIR
/*
* For modules, we send the name, section names, and offsets
*/
-static void send_module (char *mname)
+static int send_module (char *mname)
{
- char data[32768];
- int len = get_sections(mname, data, sizeof(data));
- if (len) {
- if (send_request(STP_MODULE, data, len) < 0) {
+ char data[65536];
+ int len;
+ *(int32_t *)data = STP_MODULE;
+ len = get_sections(mname, data + sizeof(int32_t),
+ sizeof(data) - sizeof(int32_t));
+ if (len > 0) {
+ if (write(control_channel, data, len + sizeof(int32_t)) <= 0) {
_err("Loading of module %s failed. Exiting...\n", mname);
- exit(1);
+ return -1;
}
}
+ return len;
}
/*
* Send either all modules, or a specific one.
+ * Returns:
+ * >=0 : OK
+ * -1 : serious error (exit)
*/
int do_module (void *data)
{
- struct _stp_module *mod = (struct _stp_module *)data;
+ struct _stp_msg_module *mod = (struct _stp_msg_module *)data;
if (mod->name[0] == 0) {
struct dirent *d;
DIR *moddir = opendir("/sys/module");
if (moddir) {
while ((d = readdir(moddir)))
- send_module(d->d_name);
+ if (send_module(d->d_name) < 0) {
+ closedir(moddir);
+ return -1;
+ }
closedir(moddir);
}
- send_request(STP_MODULE, data, 0);
- return 1;
+ send_request(STP_MODULE, data, 1);
+ return 0;
}
- send_module(mod->name);
- return 0;
-}
-
-static int compar(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;
+ return send_module(mod->name);
}
#define MAX_SYMBOLS 32*1024
@@ -194,29 +205,29 @@ static int compar(const void *p1, const void *p2)
* systemtap module. Ignore module symbols; the systemtap module
* can access them directly.
*/
-void do_kernel_symbols(void)
+int do_kernel_symbols(void)
{
FILE *kallsyms=NULL;
- char *sym_base=NULL, *data_base=NULL;
- char buf[256], *ptr, *name, *data, *dataptr, *datamax, type;
- unsigned long addr;
- struct _stp_symbol *syms;
- int num_syms, i = 0, max_syms= MAX_SYMBOLS;
- int data_basesize = MAX_SYMBOLS*32;
-
- sym_base = malloc(max_syms*sizeof(struct _stp_symbol)+sizeof(long));
+ char *name, *mod, *dataptr, *datamax, type, *data_base=NULL;
+ unsigned long long addr;
+ void *syms = NULL;
+ int ret, num_syms, i = 0, struct_symbol_size;
+ int max_syms= MAX_SYMBOLS, data_basesize = MAX_SYMBOLS*32;
+
+ if (kernel_ptr_size == 8)
+ struct_symbol_size = sizeof(struct _stp_symbol64);
+ else
+ struct_symbol_size = sizeof(struct _stp_symbol32);
+
+ syms = malloc(max_syms * struct_symbol_size);
data_base = malloc(data_basesize);
- if (data_base == NULL || sym_base == NULL) {
+ if (data_base == NULL || syms == NULL) {
_err("Failed to allocate memory for symbols\n");
goto err;
}
- *(int *)data_base = STP_SYMBOLS;
- dataptr = data = data_base + sizeof(long);
+ dataptr = data_base;
datamax = data_base + data_basesize;
- *(int *)sym_base = STP_SYMBOLS;
- syms = (struct _stp_symbol *)(sym_base + sizeof(long));
-
kallsyms = fopen ("/proc/kallsyms", "r");
if (!kallsyms) {
_perr("Fatal error: Unable to open /proc/kallsyms");
@@ -226,35 +237,28 @@ void do_kernel_symbols(void)
/* put empty string in data */
*dataptr++ = 0;
- while (fgets_unlocked(buf, 256, kallsyms) && dataptr < datamax) {
- addr = strtoul(buf, &ptr, 16);
- while (isspace(*ptr)) ptr++;
- type = *ptr++;
+ while ((ret = fscanf(kallsyms, "%llx %c %as [%as", &addr, &type, &name, &mod))>0
+ && dataptr < datamax) {
+ if (ret < 3)
+ continue;
+ if (ret > 3) {
+ /* ignore modules */
+ free(name);
+ free(mod);
+ /* modules are loaded above the kernel, so if we */
+ /* are getting modules, then we're done. */
+ break;
+ }
+
if (type == 't' || type == 'T' || type == 'A') {
- while (isspace(*ptr)) ptr++;
- name = ptr++;
- while (!isspace(*ptr)) ptr++;
- *ptr++ = 0;
- while (*ptr && *ptr != '[') ptr++;
- if (*ptr)
- continue; /* it was a module */
- syms[i].addr = addr;
- syms[i].symbol = (char *)(dataptr - data);
- while (*name) *dataptr++ = *name++;
- *dataptr++ = 0;
- i++;
- if (i >= max_syms) {
- char *s;
- max_syms *= 2;
- s = realloc(sym_base, max_syms*sizeof(struct _stp_symbol)+sizeof(long));
- if (s == NULL) {
- _err("Could not allocate enough space for symbols.\n");
- goto err;
- }
- syms = (struct _stp_symbol *)(s + sizeof(long));
- sym_base = s;
- }
- if (dataptr > datamax - 1024) {
+ if (kernel_ptr_size == 8) {
+ ((struct _stp_symbol64 *)syms)[i].addr = (uint64_t)addr;
+ ((struct _stp_symbol64 *)syms)[i].symbol = (uint64_t)(dataptr - data_base);
+ } else {
+ ((struct _stp_symbol32 *)syms)[i].addr = (uint32_t)addr;
+ ((struct _stp_symbol32 *)syms)[i].symbol = (uint32_t)(dataptr - data_base);
+ }
+ if (dataptr >= datamax - strlen(name)) {
char *db;
data_basesize *= 2;
db = realloc(data_base, data_basesize);
@@ -263,43 +267,55 @@ void do_kernel_symbols(void)
goto err;
}
dataptr = db + (dataptr - data_base);
- data = db + sizeof(long);
datamax = db + data_basesize;
data_base = db;
}
+ strcpy(dataptr, name);
+ dataptr += strlen(name) + 1;
+ free(name);
+ i++;
+ if (i >= max_syms) {
+ max_syms *= 2;
+ syms = realloc(syms, max_syms*struct_symbol_size);
+ if (syms == NULL) {
+ _err("Could not allocate enough space for symbols.\n");
+ goto err;
+ }
+ }
}
}
num_syms = i;
- qsort(syms, num_syms, sizeof(struct _stp_symbol), compar);
+ if (num_syms <= 0)
+ goto err;
/* send header */
- *(int *)buf = STP_SYMBOLS;
- *(int *)(buf+sizeof(long)) = num_syms;
- *(int *)(buf+sizeof(long)+sizeof(int)) = (unsigned)(dataptr - data);
- if (send_data(buf, 2*sizeof(int)+sizeof(long)) < 0)
+ struct _stp_msg_symbol_hdr smsh;
+ smsh.num_syms = num_syms;
+ smsh.sym_size = (uint32_t)(dataptr - data_base);
+ if (send_request(STP_SYMBOLS, &smsh, sizeof(smsh)) <= 0)
goto err;
/* send syms */
- if (send_data(sym_base, num_syms*sizeof(struct _stp_symbol)+sizeof(long)) < 0)
+ if (send_data(syms, num_syms*struct_symbol_size) < 0)
goto err;
/* send data */
- if (send_data(data_base, dataptr-data+sizeof(long)) < 0)
+ if (send_data(data_base, dataptr-data_base) < 0)
goto err;
free(data_base);
- free(sym_base);
+ free(syms);
fclose(kallsyms);
- return;
+ return 0;
err:
if (data_base)
free(data_base);
- if (sym_base)
- free(sym_base);
+ if (syms)
+ free(syms);
if (kallsyms)
fclose(kallsyms);
_err("Loading of symbols failed. Exiting...\n");
- exit(1);
+ return -1;
}
diff --git a/runtime/stat.c b/runtime/stat.c
index 3df1d063..298a6653 100644
--- a/runtime/stat.c
+++ b/runtime/stat.c
@@ -52,7 +52,7 @@
/** Stat struct for stat.c. Maps do not need this */
struct _Stat {
struct _Hist hist;
- /* per-cpu data. allocated with alloc_percpu() */
+ /* per-cpu data. allocated with _stp_alloc_percpu() */
stat *sd;
/* aggregated data */
stat *agg;
@@ -130,9 +130,9 @@ Stat _stp_stat_init (int type, ...)
return st;
exit2:
- kfree (sd);
+ _stp_kfree (sd);
exit1:
- kfree (st);
+ _stp_kfree (st);
return NULL;
}
@@ -144,9 +144,9 @@ exit1:
void _stp_stat_del (Stat st)
{
if (st) {
- free_percpu (st->sd);
- kfree (st->agg);
- kfree (st);
+ _stp_free_percpu (st->sd);
+ _stp_kfree (st->agg);
+ _stp_kfree (st);
}
}
diff --git a/runtime/sym.c b/runtime/sym.c
index c40f48db..56c93064 100644
--- a/runtime/sym.c
+++ b/runtime/sym.c
@@ -193,7 +193,7 @@ void _stp_symbol_print (unsigned long address)
_stp_printf ("%p", (int64_t)address);
if (name) {
- if (modname)
+ if (modname && *modname)
_stp_printf (" : %s+%#lx/%#lx [%s]", name, offset, size, modname);
else
_stp_printf (" : %s+%#lx/%#lx", name, offset, size);
@@ -202,22 +202,28 @@ void _stp_symbol_print (unsigned long address)
/* Like _stp_symbol_print, except only print if the address is a valid function address */
-void _stp_func_print (unsigned long address, int verbose)
+void _stp_func_print (unsigned long address, int verbose, int exact)
{
char *modname;
const char *name;
unsigned long offset, size;
+ char *exstr;
+
+ if (exact)
+ exstr = "";
+ else
+ exstr = " (inexact)";
name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL);
if (name) {
if (verbose) {
- if (modname)
- _stp_printf (" %p : %s+%#lx/%#lx [%s]\n",
- (int64_t)address, name, offset, size, modname);
+ if (modname && *modname)
+ _stp_printf (" %p : %s+%#lx/%#lx [%s]%s\n",
+ (int64_t)address, name, offset, size, modname, exstr);
else
- _stp_printf (" %p : %s+%#lx/%#lx\n",
- (int64_t)address, name, offset, size);
+ _stp_printf (" %p : %s+%#lx/%#lx%s\n",
+ (int64_t)address, name, offset, size, exstr);
} else
_stp_printf ("%p ", (int64_t)address);
}
diff --git a/runtime/time.c b/runtime/time.c
index 688427f4..52a2edbb 100644
--- a/runtime/time.c
+++ b/runtime/time.c
@@ -219,7 +219,7 @@ _stp_kill_time(void)
}
#endif
- free_percpu(stp_time);
+ _stp_free_percpu(stp_time);
}
}
@@ -229,10 +229,9 @@ _stp_init_time(void)
{
int ret = 0;
- stp_time = alloc_percpu(stp_time_t);
+ stp_time = _stp_alloc_percpu(sizeof(stp_time_t));
if (unlikely(stp_time == 0))
return -1;
- _stp_allocated_memory += sizeof(stp_time_t) * num_online_cpus();
stp_timer_reregister = 1;
ret = on_each_cpu(__stp_init_time, NULL, 0, 1);
diff --git a/runtime/transport/ChangeLog b/runtime/transport/ChangeLog
index 263a6bf8..e7bbabd8 100644
--- a/runtime/transport/ChangeLog
+++ b/runtime/transport/ChangeLog
@@ -1,3 +1,32 @@
+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();
+ * (*.c): Call stp malloc and free functions.
+
2007-11-09 Masami Hiramatsu <mhiramat@redhat.com>
PR3858
diff --git a/runtime/transport/control.c b/runtime/transport/control.c
index 7846572a..3179f507 100644
--- a/runtime/transport/control.c
+++ b/runtime/transport/control.c
@@ -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;
@@ -422,7 +433,7 @@ static int _stp_register_ctl_channel (void)
/* allocate buffers */
for (i = 0; i < STP_DEFAULT_BUFFERS; i++) {
- p = (struct list_head *)kmalloc(sizeof(struct _stp_buffer),STP_ALLOC_FLAGS);
+ p = (struct list_head *)_stp_kmalloc(sizeof(struct _stp_buffer));
// printk("allocated buffer at %lx\n", (long)p);
if (!p)
goto err0;
@@ -448,7 +459,7 @@ err0:
list_for_each_safe(p, tmp, &_stp_pool_q) {
list_del(p);
- kfree(p);
+ _stp_kfree(p);
}
errk ("Error creating systemtap debugfs entries.\n");
return -1;
@@ -464,15 +475,15 @@ static void _stp_unregister_ctl_channel (void)
/* free memory pools */
list_for_each_safe(p, tmp, &_stp_pool_q) {
list_del(p);
- kfree(p);
+ _stp_kfree(p);
}
list_for_each_safe(p, tmp, &_stp_sym_ready_q) {
list_del(p);
- kfree(p);
+ _stp_kfree(p);
}
list_for_each_safe(p, tmp, &_stp_ctl_ready_q) {
list_del(p);
- kfree(p);
+ _stp_kfree(p);
}
}
diff --git a/runtime/transport/procfs.c b/runtime/transport/procfs.c
index 069e379e..85e97d15 100644
--- a/runtime/transport/procfs.c
+++ b/runtime/transport/procfs.c
@@ -1,7 +1,7 @@
/* -*- linux-c -*-
*
* /proc transport and control
- * Copyright (C) 2005-2007 Red Hat Inc.
+ * Copyright (C) 2005-2008 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
@@ -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;
@@ -485,7 +493,7 @@ static int _stp_set_buffers(int num)
if (num > _stp_current_buffers) {
for (i = 0; i < num - _stp_current_buffers; i++) {
- p = (struct list_head *)kmalloc(sizeof(struct _stp_buffer),STP_ALLOC_FLAGS);
+ p = (struct list_head *)_stp_kmalloc(sizeof(struct _stp_buffer));
if (!p) {
_stp_current_buffers += i;
goto err;
@@ -501,7 +509,7 @@ static int _stp_set_buffers(int num)
p = _stp_pool_q.next;
list_del(p);
spin_unlock_irqrestore(&_stp_pool_lock, flags);
- kfree(p);
+ _stp_kfree(p);
}
}
_stp_current_buffers = num;
@@ -542,7 +550,7 @@ static int _stp_register_ctl_channel (void)
/* allocate buffers */
for (i = 0; i < STP_DEFAULT_BUFFERS; i++) {
- p = (struct list_head *)kmalloc(sizeof(struct _stp_buffer),STP_ALLOC_FLAGS);
+ p = (struct list_head *)_stp_kmalloc(sizeof(struct _stp_buffer));
// printk("allocated buffer at %lx\n", (long)p);
if (!p)
goto err0;
@@ -593,7 +601,7 @@ err2:
err1:
#ifdef STP_BULKMODE
for (de = _stp_proc_root->subdir; de; de = de->next)
- kfree (de->data);
+ _stp_kfree (de->data);
for_each_cpu(j) {
if (j == i)
break;
@@ -607,7 +615,7 @@ err1:
err0:
list_for_each_safe(p, tmp, &_stp_pool_q) {
list_del(p);
- kfree(p);
+ _stp_kfree(p);
}
errk ("Error creating systemtap /proc entries.\n");
@@ -624,7 +632,7 @@ static void _stp_unregister_ctl_channel (void)
struct proc_dir_entry *de;
kbug("unregistering procfs\n");
for (de = _stp_proc_root->subdir; de; de = de->next)
- kfree (de->data);
+ _stp_kfree (de->data);
for_each_cpu(i) {
sprintf(buf, "%d", i);
@@ -640,15 +648,15 @@ static void _stp_unregister_ctl_channel (void)
/* free memory pools */
list_for_each_safe(p, tmp, &_stp_pool_q) {
list_del(p);
- kfree(p);
+ _stp_kfree(p);
}
list_for_each_safe(p, tmp, &_stp_sym_ready_q) {
list_del(p);
- kfree(p);
+ _stp_kfree(p);
}
list_for_each_safe(p, tmp, &_stp_ctl_ready_q) {
list_del(p);
- kfree(p);
+ _stp_kfree(p);
}
}
diff --git a/runtime/transport/relayfs.c b/runtime/transport/relayfs.c
index 2c7ca754..375c8e59 100644
--- a/runtime/transport/relayfs.c
+++ b/runtime/transport/relayfs.c
@@ -118,7 +118,7 @@ err:
_stp_remove_relay_dir(utt->dir);
if (utt->utt_tree_root)
_stp_remove_relay_root(utt->utt_tree_root);
- kfree(utt);
+ _stp_kfree(utt);
return NULL;
}
@@ -173,7 +173,7 @@ int utt_trace_remove(struct utt_trace *utt)
_stp_remove_relay_dir(utt->dir);
if (utt->utt_tree_root)
_stp_remove_relay_root(utt->utt_tree_root);
- kfree(utt);
+ _stp_kfree(utt);
}
return 0;
}
diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c
index 1d930183..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,16 +84,20 @@ 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)
- vfree(mod->symbols);
- else
- kfree(mod->symbols);
- kfree(mod);
+ 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,21 +111,27 @@ 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)
- vfree(mod->symbols);
+ _stp_vfree(mod->symbols);
else
- kfree(mod->symbols);
+ _stp_kfree(mod->symbols);
+ mod->symbols = NULL;
+ }
+ if (mod->symbol_data) {
if (mod->allocated & 2)
- vfree(mod->symbol_data);
+ _stp_vfree(mod->symbol_data);
else
- kfree(mod->symbol_data);
- }
- if (mod->sections)
- kfree(mod->sections);
+ _stp_kfree(mod->symbol_data);
+ mod->symbol_data = NULL;
+ }
+ if (mod->sections) {
+ _stp_kfree(mod->sections);
+ mod->sections = NULL;
+ }
/* free module memory */
- kfree(mod);
+ _stp_kfree(mod);
}
/* Delete a module and free its memory. */
@@ -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))) {
- 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) {
- 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 2904cf2f..6b90ee64 100644
--- a/runtime/transport/transport.c
+++ b/runtime/transport/transport.c
@@ -2,7 +2,7 @@
* transport.c - stp transport functions
*
* Copyright (C) IBM Corporation, 2005
- * Copyright (C) Red Hat Inc, 2005-2007
+ * Copyright (C) Red Hat Inc, 2005-2008
* Copyright (C) Intel Corporation, 2006
*
* This file is part of systemtap, and is free software. You can
@@ -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);
@@ -215,6 +218,7 @@ void _stp_transport_close()
_stp_free_modules();
_stp_kill_time();
_stp_print_cleanup(); /* free print buffers */
+ _stp_mem_debug_done();
kbug("---- CLOSED ----\n");
}
@@ -287,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
diff --git a/runtime/transport/utt.c b/runtime/transport/utt.c
index ac2e1513..182c1178 100644
--- a/runtime/transport/utt.c
+++ b/runtime/transport/utt.c
@@ -88,7 +88,7 @@ void utt_trace_cleanup(struct utt_trace *utt)
if (utt->dropped_file)
debugfs_remove(utt->dropped_file);
utt_remove_tree(utt);
- kfree(utt);
+ _stp_kfree(utt);
}
int utt_trace_remove(struct utt_trace *utt)
@@ -207,7 +207,7 @@ struct utt_trace *utt_trace_setup(struct utt_trace_setup *utts)
goto err;
ret = -ENOMEM;
- utt = kzalloc(sizeof(*utt), GFP_KERNEL);
+ utt = _stp_kzalloc(sizeof(*utt));
if (!utt)
goto err;
@@ -251,7 +251,7 @@ err:
debugfs_remove(utt->dropped_file);
if (utt->rchan)
relay_close(utt->rchan);
- kfree(utt);
+ _stp_kfree(utt);
}
if (dir)
utt_remove_tree(utt);
diff --git a/stapfuncs.5.in b/stapfuncs.5.in
index 3802117a..85a00b37 100644
--- a/stapfuncs.5.in
+++ b/stapfuncs.5.in
@@ -444,6 +444,29 @@ Convert from host to network byte order, 32-bit.
htons:long (x:long)
Convert from host to network byte order, 16-bit.
+.SS SIGNAL
+.TP
+get_sa_flags:long (act:long)
+Returns the numeric value of sa_flags.
+.TP
+get_sa_handler:long (act:long)
+Returns the numeric value of sa_handler.
+.TP
+sigset_mask_str:string (mask:long)
+Returns the string representation of the sigset sa_mask.
+.TP
+is_sig_blocked:long (task:long, sig:long)
+Returns 1 if the signal is currently blocked, or 0 if it is not.
+.TP
+sa_flags_str:string (sa_flags:long)
+Returns the string representation of sa_flags.
+.TP
+sa_handler_str(handler)
+Returns the string representation of sa_handler. If it is not SIG_DFL, SIG_IGN
+or SIG_ERR, it will return the address of the handler.
+.TP
+signal_str(num)
+Returns the string representation of the given signal number.
.SH FILES
.nh
diff --git a/tapset/ChangeLog b/tapset/ChangeLog
index 5519ef58..a7f8fdf8 100644
--- a/tapset/ChangeLog
+++ b/tapset/ChangeLog
@@ -1,3 +1,16 @@
+2008-01-16 Eugene Teo <eteo@redhat.com>
+
+ * signal.stp (get_sa_flags, get_sa_handler): New functions to
+ return addresses of sa_flags and sa_handler of struct k_sigaction.
+ (sigset_mask_str): New function. Returns a string containing the
+ set of signals to be blocked when executing the signal handler.
+ (is_sig_blocked): New function. Checks task_struct->blocked signal
+ mask for signals that are currently blocked.
+ (signal_str): New function. Translates a signal number.
+ (sa_flags_str): New function. Translates the sa_flags.
+ (sa_handler_str): New function. Returns the signal action or handler
+ associated to the signal.
+
2008-1-4 Masami Hiramatsu <mhiramat@redhat.com>
* aux_syscalls.stp (_stp_fork_list): Check kernel version for new
diff --git a/tapset/signal.stp b/tapset/signal.stp
index f472f370..ec947eb7 100644
--- a/tapset/signal.stp
+++ b/tapset/signal.stp
@@ -1,6 +1,7 @@
// Signal tapset
// Copyright (C) 2006 IBM Corp.
// Copyright (C) 2006 Intel Corporation.
+// Copyright (C) 2008 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
@@ -505,3 +506,165 @@ probe signal.flush = kernel.function("flush_signals")
sig_pid = $t->pid
pid_name = kernel_string($t->comm)
}
+
+function get_sa_flags:long (act:long) %{ /* pure */
+ struct k_sigaction *act = (struct k_sigaction *)((long)THIS->act);
+ THIS->__retvalue = kread(&act->sa.sa_flags);
+ CATCH_DEREF_FAULT();
+%}
+
+function get_sa_handler:long (act:long) %{ /* pure */
+ struct k_sigaction *act = (struct k_sigaction *)((long)THIS->act);
+ THIS->__retvalue = (long)kread(&act->sa.sa_handler);
+ CATCH_DEREF_FAULT();
+%}
+
+/*
+ * sa_mask contains the set of signals to be blocked when executing the
+ * signal handler. This function returns a string, delimited by ",".
+ *
+ * struct task_struct {
+ * [...]
+ * struct signal_struct *signal;
+ * struct sighand_struct *sighand;
+ * [...]
+ * struct sighand_struct {
+ * atomic_t count;
+ * struct k_sigaction action[_NSIG];
+ * [...]
+ * struct k_sigaction {
+ * struct sigaction sa;
+ * };
+ *
+ * struct sigaction {
+ * [...]
+ * sigset_t sa_mask;
+ * };
+ */
+function sigset_mask_str:string (mask:long) %{ /* pure */
+ int i, len;
+ char *str = THIS->__retvalue, tmp[5];
+ for (i = 1; i < _NSIG; ++i, THIS->mask >>=1)
+ if (THIS->mask & 1) {
+ sprintf(tmp, "%u,", i);
+ strlcat(str, tmp, MAXSTRINGLEN);
+ }
+ len = strlen(str);
+ if (len) str[len - 1] = '\0';
+%}
+
+/*
+ * task_struct->blocked signal mask contains the set of signals that are
+ * currently blocked.
+ *
+ * struct task_struct {
+ * [...]
+ * sigset_t blocked, real_blocked;
+ */
+function is_sig_blocked:long (task:long, sig:long) %{ /* pure */
+ int i;
+ sigset_t blocked;
+ struct task_struct *p = (struct task_struct *)((long)THIS->task);
+ for (i = 0; i < _NSIG_WORDS; ++i)
+ blocked.sig[i] = kread(&p->blocked.sig[i]);
+ THIS->__retvalue = sigismember(&blocked, THIS->sig);
+ CATCH_DEREF_FAULT();
+%}
+
+function sa_flags_str:string (sa_flags:long) %{ /* pure */
+ int len;
+ char *str = THIS->__retvalue;
+ if (THIS->sa_flags & 0x00000001u) strlcat(str, "NOCLDSTOP|", MAXSTRINGLEN);
+ if (THIS->sa_flags & 0x00000002u) strlcat(str, "NOCLDWAIT|", MAXSTRINGLEN);
+ if (THIS->sa_flags & 0x00000004u) strlcat(str, "SIGINFO|", MAXSTRINGLEN);
+ if (THIS->sa_flags & 0x08000000u) strlcat(str, "ONSTACK|", MAXSTRINGLEN);
+ if (THIS->sa_flags & 0x10000000u) strlcat(str, "RESTART|", MAXSTRINGLEN);
+ if (THIS->sa_flags & 0x40000000u) strlcat(str, "NODEFER|", MAXSTRINGLEN);
+ if (THIS->sa_flags & 0x80000000u) strlcat(str, "RESETHAND|", MAXSTRINGLEN);
+ if (THIS->sa_flags & 0x04000000) strlcat(str, "RESTORER|", MAXSTRINGLEN);
+ len = strlen(str);
+ if (len) str[len - 1] = '\0';
+%}
+
+function sa_handler_str(handler) {
+ if (handler == 0) return "default"; /* SIG_DFL */
+ if (handler == 1) return "ignored"; /* SIG_IGN */
+ if (handler == -1) return "error"; /* SIG_ERR */
+ return sprintf("%p", handler); /* userspace address */
+}
+
+/*
+ * Signals start from 1 not 0.
+ */
+function signal_str(num) {
+ return __sig[num]
+}
+
+global __sig[64]
+
+probe begin(-1) {
+ __sig[1] = "HUP"
+ __sig[2] = "INT"
+ __sig[3] = "QUIT"
+ __sig[4] = "ILL"
+ __sig[5] = "TRAP"
+ __sig[6] = "ABRT" /* or IOT */
+ __sig[7] = "BUS"
+ __sig[8] = "FPE"
+ __sig[9] = "KILL"
+ __sig[10] = "USR1"
+ __sig[11] = "SEGV"
+ __sig[12] = "USR2"
+ __sig[13] = "PIPE"
+ __sig[14] = "ALRM"
+ __sig[15] = "TERM"
+ __sig[16] = "STKFLT"
+ __sig[17] = "CHLD" /* or CLD */
+ __sig[18] = "CONT"
+ __sig[19] = "STOP"
+ __sig[20] = "TSTP"
+ __sig[21] = "TTIN"
+ __sig[22] = "TTOU"
+ __sig[23] = "URG"
+ __sig[24] = "XCPU"
+ __sig[25] = "XFSZ"
+ __sig[26] = "VTALRM"
+ __sig[27] = "PROF"
+ __sig[28] = "WINCH"
+ __sig[29] = "IO/POLL"
+ __sig[30] = "PWR"
+ __sig[31] = "SYS" /* or UNUSED */
+ __sig[32] = "RTMIN"
+ __sig[33] = "RTMIN+1"
+ __sig[34] = "RTMIN+2"
+ __sig[35] = "RTMIN+3"
+ __sig[36] = "RTMIN+4"
+ __sig[37] = "RTMIN+5"
+ __sig[38] = "RTMIN+6"
+ __sig[39] = "RTMIN+7"
+ __sig[40] = "RTMIN+8"
+ __sig[41] = "RTMIN+9"
+ __sig[42] = "RTMIN+10"
+ __sig[43] = "RTMIN+11"
+ __sig[44] = "RTMIN+12"
+ __sig[45] = "RTMIN+13"
+ __sig[46] = "RTMIN+14"
+ __sig[47] = "RTMIN+15"
+ __sig[48] = "RTMIN+16"
+ __sig[49] = "RTMIN+17"
+ __sig[50] = "RTMIN+18"
+ __sig[51] = "RTMIN+19"
+ __sig[52] = "RTMIN+20"
+ __sig[53] = "RTMIN+21"
+ __sig[54] = "RTMIN+22"
+ __sig[55] = "RTMIN+23"
+ __sig[56] = "RTMIN+24"
+ __sig[57] = "RTMIN+25"
+ __sig[58] = "RTMIN+26"
+ __sig[59] = "RTMIN+27"
+ __sig[60] = "RTMIN+28"
+ __sig[61] = "RTMIN+29"
+ __sig[62] = "RTMIN+30"
+ __sig[63] = "RTMIN+31"
+ __sig[64] = "RTMIN+32"
+}
diff --git a/tapsets.cxx b/tapsets.cxx
index ebc07ba3..84187960 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -1343,14 +1343,15 @@ struct dwflpp
dwfl_assert ("dwfl_addrmodule", mod == NULL);
int n = dwfl_module_relocations (mod);
dwfl_assert ("dwfl_module_relocations", n < 0);
- if (n > 0)
- {
- int i = dwfl_module_relocate_address (mod, &address);
- dwfl_assert ("dwfl_module_relocate_address", i < 0);
- const char *modname = dwfl_module_info (mod, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL);
- dwfl_assert ("dwfl_module_info", modname == NULL);
- const char *secname = dwfl_module_relocation_info (mod, i, NULL);
+ int i = dwfl_module_relocate_address (mod, &address);
+ dwfl_assert ("dwfl_module_relocate_address", i < 0);
+ const char *modname = dwfl_module_info (mod, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL);
+ dwfl_assert ("dwfl_module_info", modname == NULL);
+ const char *secname = dwfl_module_relocation_info (mod, i, NULL);
+
+ if (n > 0 && !(n == 1 && secname == NULL))
+ {
dwfl_assert ("dwfl_module_relocation_info", secname == NULL);
if (n > 1 || secname[0] != '\0')
{
@@ -2137,6 +2138,7 @@ struct dwarf_query : public base_query
int line,
Dwarf_Die *scope_die,
Dwarf_Addr addr);
+ string get_blacklist_section(Dwarf_Addr addr);
set<string> blacklisted_probes;
set<string> blacklisted_return_probes;
@@ -2551,6 +2553,34 @@ dwarf_query::blacklisted_p(const string& funcname,
return false;
}
+string dwarf_query::get_blacklist_section(Dwarf_Addr addr)
+{
+ Dwarf_Addr baseaddr;
+ string blacklist_section;
+ Elf* elf = dwfl_module_getelf (dw.module, & baseaddr);
+ Dwarf_Addr offset = addr - baseaddr;
+ if (elf)
+ {
+ Elf_Scn* scn = 0;
+ size_t shstrndx;
+ dw.dwfl_assert ("getshstrndx", elf_getshstrndx (elf, &shstrndx));
+ while ((scn = elf_nextscn (elf, scn)) != NULL)
+ {
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+ if (! shdr) continue; // XXX error?
+
+ GElf_Addr start = shdr->sh_addr;
+ GElf_Addr end = start + shdr->sh_size;
+ if (! (offset >= start && offset < end))
+ continue;
+
+ blacklist_section = elf_strptr (elf, shstrndx, shdr->sh_name);
+ break;
+ }
+ }
+ return blacklist_section;
+}
void
@@ -2577,43 +2607,13 @@ dwarf_query::add_probe_point(const string& funcname,
if (r_s)
reloc_section = r_s;
blacklist_section = reloc_section;
+
+ if(reloc_section == "" && dwfl_module_relocations (dw.module) == 1)
+ blacklist_section = this->get_blacklist_section(addr);
}
else
{
- // This is not a relocatable module, so addr is all set. To
- // find the section name, must do this the long way - scan
- // through elf section headers.
- Dwarf_Addr baseaddr;
- Elf* elf = dwfl_module_getelf (dw.module, & baseaddr);
- Dwarf_Addr offset = addr - baseaddr;
- // NB: this offset does not end up as reloc_addr, since the latter is
- // only computed differently if load-time relocation is needed. For
- // non-relocatable modules, this is not the case.
- if (elf)
- {
- // Iterate through section headers to find which one
- // contains the given offset.
- Elf_Scn* scn = 0;
- size_t shstrndx;
- dw.dwfl_assert ("getshstrndx", elf_getshstrndx (elf, &shstrndx));
- while ((scn = elf_nextscn (elf, scn)) != NULL)
- {
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- if (! shdr) continue; // XXX error?
-
- // check for address inclusion
- GElf_Addr start = shdr->sh_addr;
- GElf_Addr end = start + shdr->sh_size;
- if (! (offset >= start && offset < end))
- continue;
-
- // check for section name
- blacklist_section = elf_strptr (elf, shstrndx, shdr->sh_name);
- break;
- }
- }
-
+ blacklist_section = this->get_blacklist_section(addr);
reloc_section = "";
}
@@ -4800,6 +4800,25 @@ procfs_var_expanding_copy_visitor::visit_target_symbol (target_symbol* e)
throw semantic_error ("invalid target symbol for procfs probe, $value expected",
e->tok);
+ if (e->components.size() > 0)
+ {
+ switch (e->components[0].first)
+ {
+ case target_symbol::comp_literal_array_index:
+ throw semantic_error("procfs target variable '$value' may not be used as array",
+ e->tok);
+ break;
+ case target_symbol::comp_struct_member:
+ throw semantic_error("procfs target variable '$value' may not be used as a structure",
+ e->tok);
+ break;
+ default:
+ throw semantic_error ("invalid use of procfs target variable '$value'",
+ e->tok);
+ break;
+ }
+ }
+
bool lvalue = is_active_lvalue(e);
if (write_probe && lvalue)
throw semantic_error("procfs $value variable is read-only in a procfs write probe", e->tok);
@@ -5044,6 +5063,24 @@ mark_var_expanding_copy_visitor::visit_target_symbol (target_symbol* e)
if (is_active_lvalue (e))
throw semantic_error("write to marker parameter not permitted", e->tok);
+ if (e->components.size() > 0)
+ {
+ switch (e->components[0].first)
+ {
+ case target_symbol::comp_literal_array_index:
+ throw semantic_error("marker argument may not be used as array",
+ e->tok);
+ break;
+ case target_symbol::comp_struct_member:
+ throw semantic_error("marker argument may not be used as a structure",
+ e->tok);
+ break;
+ default:
+ throw semantic_error ("invalid marker argument use", e->tok);
+ break;
+ }
+ }
+
// Remember that we've seen a target variable.
target_symbol_seen = true;
@@ -5100,7 +5137,7 @@ mark_derived_probe::mark_derived_probe (systemtap_session &s,
this->locations.push_back (pp);
if (cond)
- add_condition (cond);
+ add_condition (cond);
insert_condition_statement ();
// expand the signature string
@@ -5845,6 +5882,25 @@ perfmon_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e)
if (e->base_name != "$counter")
throw semantic_error ("target variables not available to perfmon probes");
+ if (e->components.size() > 0)
+ {
+ switch (e->components[0].first)
+ {
+ case target_symbol::comp_literal_array_index:
+ throw semantic_error("perfmon probe '$counter' variable may not be used as array",
+ e->tok);
+ break;
+ case target_symbol::comp_struct_member:
+ throw semantic_error("perfmon probe '$counter' variable may not be used as a structure",
+ e->tok);
+ break;
+ default:
+ throw semantic_error ("invalid use of perfmon probe '$counter' variable",
+ e->tok);
+ break;
+ }
+ }
+
ec->code = "THIS->__retvalue = _pfm_pmd_x[" +
lex_cast<string>(counter_number) + "].reg_num;";
ec->code += "/* pure */";
diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog
index d8439450..6dd0d8de 100644
--- a/testsuite/ChangeLog
+++ b/testsuite/ChangeLog
@@ -1,3 +1,25 @@
+2008-01-17 David Smith <dsmith@redhat.com>
+
+ * semko/procfs11.stp: Added test for invalid use of procfs probe
+ '$value' target variable.
+ * semko/procfs12.stp: Ditto.
+
+2008-01-16 David Smith <dsmith@redhat.com>
+
+ PR 5608.
+ * systemtap.base/marker.exp: Added 2 tests for treating marker
+ arguments incorrectly.
+
+2008-01-16 Eugene Teo <eteo@redhat.com>
+
+ * buildok/signal-embedded.stp: Add all new embedded C functions
+ in signal.
+
+2008-01-14 Frank Ch. Eigler <fche@elastic.org>
+
+ PR 4935.
+ * systemtap.base/onoffprobe.*: Toughen test.
+
2008-01-12 Frank Ch. Eigler <fche@elastic.org>
* lib/systemtap.exp (get_system_info): Look for $builddir/SNAPSHOT too.
diff --git a/testsuite/buildok/signal-embedded.stp b/testsuite/buildok/signal-embedded.stp
index 5a0d9d8b..24e218e9 100755
--- a/testsuite/buildok/signal-embedded.stp
+++ b/testsuite/buildok/signal-embedded.stp
@@ -2,5 +2,10 @@
probe begin {
print (get_sigset(0))
+ print (get_sa_flags(0))
+ print (get_sa_handler(0))
+ print (sigset_mask_str(0))
+ print (is_sig_blocked(0, 0))
+ print (sa_flags_str(0))
}
diff --git a/testsuite/semko/procfs11.stp b/testsuite/semko/procfs11.stp
new file mode 100755
index 00000000..719346fb
--- /dev/null
+++ b/testsuite/semko/procfs11.stp
@@ -0,0 +1,4 @@
+#! stap -p2
+
+# use $value as a structure pointer in a procfs probe
+probe procfs.write { print($value->foo) }
diff --git a/testsuite/semko/procfs12.stp b/testsuite/semko/procfs12.stp
new file mode 100755
index 00000000..c8af619b
--- /dev/null
+++ b/testsuite/semko/procfs12.stp
@@ -0,0 +1,4 @@
+#! stap -p2
+
+# use $value as an array in a procfs probe
+probe procfs.write { print($value[0]) }
diff --git a/testsuite/systemtap.base/marker.exp b/testsuite/systemtap.base/marker.exp
index 01d1ed54..bfa3b02d 100644
--- a/testsuite/systemtap.base/marker.exp
+++ b/testsuite/systemtap.base/marker.exp
@@ -11,7 +11,7 @@
proc stap_compile { TEST_NAME compile script args } {
set cmd [concat {stap -v -p4 -e} $script $args]
- #puts "running $cmd"
+ puts "running $cmd"
eval spawn $cmd
set compile_errors 0
expect {
@@ -47,9 +47,13 @@ proc stap_compile { TEST_NAME compile script args } {
set kernel_markers_found 0
set kernel_marker_names {}
+set num_marker_found 0
+set num_marker_name ""
+
set kernel_script {"probe kernel.mark(\"%s\") { }"}
set kernel_script_arg {"probe kernel.mark(\"%s\") { print(%s) }"}
set kernel_script_arg2 {"probe kernel.mark(\"%s\") { %s = 0 }"}
+set kernel_script_arg3 {"probe kernel.mark(\"%s\") { print(\$arg1%s) }"}
# Try to read in the marker list from the Module.markers file.
set uname [exec /bin/uname -r]
@@ -59,9 +63,17 @@ if {! [catch {open $path RDONLY} fl]} {
while {[gets $fl s] >= 0} {
# This regexp only picks up markers that contain arguments.
# This helps ensure that K_MARKER04 passes correctly.
- if [regexp {^([^ \t]+)\t[^ \t]+.*%.+$} $s match name] {
+ if [regexp {^([^ \t]+)\t[^ \t]+.*(%.+)$} $s match name fmt] {
set kernel_markers_found 1
lappend kernel_marker_names $name
+
+ # Look for a marker whose first argument is numeric
+ # (either '%d', '%u', or '%p'). If we find such a marker,
+ # we can run K_MARKER09 and K_MARKER10.
+ if {$num_marker_found == 0 && [regexp {^%[dup]} $fmt]} {
+ set num_marker_found 1
+ set num_marker_name $name
+ }
}
}
catch {close $fl}
@@ -156,3 +168,27 @@ if {$kernel_markers_found == 0} {
[lindex $kernel_marker_names 0] {\$arg1}]
stap_compile $TEST_NAME 0 $script
}
+
+set TEST_NAME "K_MARKER09"
+if {$kernel_markers_found == 0} {
+ untested "$TEST_NAME : no kernel markers present"
+} elseif {$num_marker_found == 0} {
+ untested "$TEST_NAME : no kernel marker found with a numeric first argument"
+} else {
+ # Try compiling a script that treats its first marker argument
+ # as a structure (which isn't allowed).
+ set script [format $kernel_script_arg3 $num_marker_name "->foo"]
+ stap_compile $TEST_NAME 0 $script
+}
+
+set TEST_NAME "K_MARKER10"
+if {$kernel_markers_found == 0} {
+ untested "$TEST_NAME : no kernel markers present"
+} elseif {$num_marker_found == 0} {
+ untested "$TEST_NAME : no kernel marker found with a numeric first argument"
+} else {
+ # Try compiling a script that treats its first marker argument
+ # like an array (which isn't allowed).
+ set script [format $kernel_script_arg3 $num_marker_name {\[0\]}]
+ stap_compile $TEST_NAME 0 $script
+}
diff --git a/testsuite/systemtap.base/onoffprobe.exp b/testsuite/systemtap.base/onoffprobe.exp
index 41e107d7..b86de4ea 100644
--- a/testsuite/systemtap.base/onoffprobe.exp
+++ b/testsuite/systemtap.base/onoffprobe.exp
@@ -4,54 +4,37 @@ if {![installtest_p]} { untested $test; return }
spawn stap $srcdir/$subdir/$test.stp -m $test
set pid $spawn_id
set ok 0
+
+proc advance {} {
+ global test
+ global expect_out
+ global ok
+ pass "$test $expect_out(1,string)"
+ incr ok
+ exec echo $ok > /proc/systemtap/$test/switch
+ exec echo dummy > /dev/null
+ exp_continue
+}
+
expect {
-timeout 240
- "begin probed\r\n" {
- if {$ok == 0} {
- incr ok
- pass "conditional begin probe"
- exec echo 1 > /proc/systemtap/$test/switch
- exec echo "dummy" > /dev/null
- exp_continue;
- }
- }
- "function return probed\r\n" {
- if {$ok == 1} {
- incr ok
- pass "conditional dwarf probe (return)"
- exec echo 2 > /proc/systemtap/$test/switch
- exec echo "dummy" > /dev/null
- exp_continue;
- }
- }
- "function entry probed\r\n" {
- if {$ok == 2} {
- incr ok
- pass "conditional dwarf probe (entry)"
- exec echo 3 > /proc/systemtap/$test/switch
- exp_continue;
- }
- }
- "timer probed\r\n" {
- if {$ok == 3} {
- incr ok
- pass "conditional timer probe"
- exec echo 4 > /proc/systemtap/$test/switch
- exp_continue;
- }
- }
- "profile probed\r\n" {
- if {$ok == 4} {
- incr ok
- pass "conditional profile probe"
- }
+ -re "(begin1 probed)\r\n" { advance }
+ -re "^(function return probed)\r\n" { advance }
+ -re "^(function entry probed)\r\n" { advance }
+ -re "^(timer probed)\r\n" { advance }
+ -re "^(profile probed)\r\n" { advance }
+ -re "^(alias\.one\.a and alias\.one and alias\.\* probed)\r\n" { advance }
+ -re "^(alias\.one\.b and alias\.one and alias\.\* probed)\r\n" { advance }
+ -re "^(alias\.two and alias\.\* probed)\r\n" {
+ pass "$test $expect_out(1,string)"
+ incr ok
}
- timeout { fail "$test (timeout)" }
- eof { }
+ timeout { fail "$test (timeout)" }
+ eof { }
}
send "\003"
#FIXME does not handle case of hanging pfaults.stp correctly
wait
exec rm -f $test.ko
-if {$ok != 5} {fail "conditional probes ($ok)"}
+if {$ok != 8} {fail "conditional probes ($ok)"}
diff --git a/testsuite/systemtap.base/onoffprobe.stp b/testsuite/systemtap.base/onoffprobe.stp
index 11968540..f7169039 100644
--- a/testsuite/systemtap.base/onoffprobe.stp
+++ b/testsuite/systemtap.base/onoffprobe.stp
@@ -1,34 +1,45 @@
-global switch=0
+global switch=-1
#begin probe
+probe begin if (switch==-1) {
+ log("begin1 probed");
+}
+
probe begin if (switch==0) {
- log("begin probed\n");
+ log("begin2 probed");
}
#dwarf probe (return)
probe kernel.function("sys_write").return if (switch == 1) {
- log("function return probed\n")
+ log("function return probed")
switch = 0
}
#dwarf probe (entry)
probe kernel.function("sys_write") if (switch == 2) {
- log("function entry probed\n")
+ log("function entry probed")
switch = 0
}
#timer probe
probe timer.s(1) if (switch == 3) {
- log("timer probed\n")
+ log("timer probed")
switch = 0
}
#profile probe
probe timer.profile if (switch == 4) {
- log("profile probed\n")
+ log("profile probed")
switch = 0
}
+# aliasess
+probe alias.one.a = timer.s(2) if (switch == 5) { print("alias.one.a and") }
+probe alias.one.b = timer.s(3) if (switch == 6) { print("alias.one.b and") }
+probe alias.one = alias.one.* if (switch >= 5 && switch < 7) { print(" alias.one and") }
+probe alias.two = timer.s(4) if (switch == 7) { print("alias.two and") }
+probe alias.* if (switch) { log(" alias.* probed") }
+
probe procfs("switch").write {
switch = strtol($value, 10)
}
diff --git a/translate.cxx b/translate.cxx
index 27b28d5f..7f42ceec 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -1,5 +1,5 @@
// translation pass
-// Copyright (C) 2005-2007 Red Hat Inc.
+// Copyright (C) 2005-2008 Red Hat Inc.
// Copyright (C) 2005-2007 Intel Corporation.
//
// This file is part of systemtap, and is free software. You can
@@ -1148,21 +1148,13 @@ c_unparser::emit_module_init ()
// Print a message to the kernel log about this module. This is
// intended to help debug problems with systemtap modules.
- o->newline() << "printk (KERN_DEBUG \"%s: "
- << "systemtap: " << VERSION << "/" << dwfl_version (NULL)
- << ", base: %p"
- << ", memory: %lu+%lu+%lu+%lu+%lu data+text+ctx+io+glob"
- << ", probes: " << session->probes.size()
- << "\\n\""
- // printk arguments
- << ", THIS_MODULE->name"
- << ", THIS_MODULE->module_core"
- << ", (unsigned long) (THIS_MODULE->core_size - THIS_MODULE->core_text_size)"
- << ", (unsigned long) THIS_MODULE->core_text_size"
- << ", (unsigned long) (num_online_cpus() * sizeof(struct context))"
- << ", (unsigned long) _stp_allocated_net_memory"
- << ", (unsigned long) _stp_allocated_memory"
- << ");";
+
+ o->newline() << "_stp_print_kernel_info("
+ << "\"" << VERSION
+ << "/" << dwfl_version (NULL) << "\""
+ << ", (num_online_cpus() * sizeof(struct context))"
+ << ", " << session->probes.size()
+ << ");";
// Run all probe registrations. This actually runs begin probes.
@@ -1298,6 +1290,7 @@ c_unparser::emit_module_exit ()
o->newline() << "_stp_printf (\"probe %s (%s), hits: %lld, cycles: %lldmin/%lldavg/%lldmax\\n\",";
o->newline() << "probe_point, decl_location, (long long) stats->count, (long long) stats->min, (long long) avg, (long long) stats->max);";
o->newline(-1) << "}";
+ o->newline() << "_stp_stat_del (time_" << p->name << ");";
o->newline(-1) << "}";
}
}