summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/autoconf-asm-syscall.c2
-rw-r--r--runtime/loc2c-runtime.h17
-rw-r--r--runtime/map-gen.c291
-rw-r--r--runtime/pmap-gen.c343
-rw-r--r--runtime/runtime.h19
-rw-r--r--runtime/stack.c8
-rw-r--r--runtime/staprun/common.c9
-rw-r--r--runtime/staprun/relay.c19
-rw-r--r--runtime/staprun/relay_old.c22
-rw-r--r--runtime/staprun/staprun_funcs.c15
-rw-r--r--runtime/sym.c140
-rw-r--r--runtime/sym.h1
-rw-r--r--runtime/syscall.h298
-rw-r--r--runtime/task_finder.c508
-rw-r--r--runtime/task_finder_vma.c110
-rw-r--r--runtime/unwind.c2
-rw-r--r--runtime/uprobes/.gitignore7
17 files changed, 1291 insertions, 520 deletions
diff --git a/runtime/autoconf-asm-syscall.c b/runtime/autoconf-asm-syscall.c
new file mode 100644
index 00000000..bf7a273f
--- /dev/null
+++ b/runtime/autoconf-asm-syscall.c
@@ -0,0 +1,2 @@
+#include <asm/syscall.h>
+
diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h
index 16ddb950..620e1615 100644
--- a/runtime/loc2c-runtime.h
+++ b/runtime/loc2c-runtime.h
@@ -29,11 +29,12 @@
& (((__typeof (base)) 1 << (nbits)) - 1))
#define store_bitfield(target, base, higherbits, nbits) \
- target = (target \
- &~ ((((__typeof (base)) 1 << (nbits)) - 1) \
- << (sizeof (base) * 8 - (higherbits) - (nbits))) \
- | ((__typeof (base)) (base) \
- << (sizeof (base) * 8 - (higherbits) - (nbits))))
+ target = ((target \
+ &~ ((((__typeof (target)) 1 << (nbits)) - 1) \
+ << (sizeof (target) * 8 - (higherbits) - (nbits)))) \
+ | ((((__typeof (target)) (base)) \
+ & (((__typeof (target)) 1 << (nbits)) - 1)) \
+ << (sizeof (target) * 8 - (higherbits) - (nbits))))
/* Given a DWARF register number, fetch its intptr_t (long) value from the
@@ -62,6 +63,10 @@
must work right for kernel addresses, and can use whatever existing
machine-specific kernel macros are convenient. */
+#if STP_SKIP_BADVARS
+#define DEREF_FAULT(addr) ({0; })
+#define STORE_DEREF_FAULT(addr) ({0; })
+#else
#define DEREF_FAULT(addr) ({ \
snprintf(c->error_buffer, sizeof(c->error_buffer), \
"kernel read fault at 0x%p (%s)", (void *)(intptr_t)(addr), #addr); \
@@ -75,7 +80,7 @@
c->last_error = c->error_buffer; \
goto deref_fault; \
})
-
+#endif
#if defined (STAPCONF_X86_UNIREGS) && defined (__i386__)
diff --git a/runtime/map-gen.c b/runtime/map-gen.c
index c4bdf2c7..fdb75089 100644
--- a/runtime/map-gen.c
+++ b/runtime/map-gen.c
@@ -26,6 +26,14 @@
#define JOIN5x(a,b,c,d,e,f) a##_##b##c##d##e##f
#define JOIN6(a,b,c,d,e,f,g) JOIN6x(a,b,c,d,e,f,g)
#define JOIN6x(a,b,c,d,e,f,g) a##_##b##c##d##e##f##g
+#define JOIN7(a,b,c,d,e,f,g,h) JOIN7x(a,b,c,d,e,f,g,h)
+#define JOIN7x(a,b,c,d,e,f,g,h) a##_##b##c##d##e##f##g##h
+#define JOIN8(a,b,c,d,e,f,g,h,i) JOIN8x(a,b,c,d,e,f,g,h,i)
+#define JOIN8x(a,b,c,d,e,f,g,h,i) a##_##b##c##d##e##f##g##h##i
+#define JOIN9(a,b,c,d,e,f,g,h,i,j) JOIN9x(a,b,c,d,e,f,g,h,i,j)
+#define JOIN9x(a,b,c,d,e,f,g,h,i,j) a##_##b##c##d##e##f##g##h##i##j
+#define JOIN10(a,b,c,d,e,f,g,h,i,j,k) JOIN10x(a,b,c,d,e,f,g,h,i,j,k)
+#define JOIN10x(a,b,c,d,e,f,g,h,i,j,k) a##_##b##c##d##e##f##g##h##i##j##k
#include "map.h"
@@ -162,6 +170,113 @@
#define KEY5_HASH JOIN(KEY5NAME,hash)
#endif /* defined(KEY5_TYPE) */
+#if defined (KEY6_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 6
+#if KEY6_TYPE == STRING
+#define KEY6TYPE char*
+#define KEY6NAME str
+#define KEY6N s
+#define KEY6STOR char key6[MAP_STRING_LENGTH]
+#define KEY6CPY(m) str_copy(m->key6, key6)
+#else
+#define KEY6TYPE int64_t
+#define KEY6NAME int64
+#define KEY6N i
+#define KEY6STOR int64_t key6
+#define KEY6CPY(m) m->key6=key6
+#endif
+#define KEY6_EQ_P JOIN(KEY6NAME,eq_p)
+#define KEY6_HASH JOIN(KEY6NAME,hash)
+#endif /* defined(KEY6_TYPE) */
+
+#if defined (KEY7_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 7
+#if KEY7_TYPE == STRING
+#define KEY7TYPE char*
+#define KEY7NAME str
+#define KEY7N s
+#define KEY7STOR char key7[MAP_STRING_LENGTH]
+#define KEY7CPY(m) str_copy(m->key7, key7)
+#else
+#define KEY7TYPE int64_t
+#define KEY7NAME int64
+#define KEY7N i
+#define KEY7STOR int64_t key7
+#define KEY7CPY(m) m->key7=key7
+#endif
+#define KEY7_EQ_P JOIN(KEY7NAME,eq_p)
+#define KEY7_HASH JOIN(KEY7NAME,hash)
+#endif /* defined(KEY7_TYPE) */
+
+#if defined (KEY7_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 7
+#if KEY7_TYPE == STRING
+#define KEY7TYPE char*
+#define KEY7NAME str
+#define KEY7N s
+#define KEY7STOR char key7[MAP_STRING_LENGTH]
+#define KEY7CPY(m) str_copy(m->key7, key7)
+#else
+#define KEY7TYPE int64_t
+#define KEY7NAME int64
+#define KEY7N i
+#define KEY7STOR int64_t key7
+#define KEY7CPY(m) m->key7=key7
+#endif
+#define KEY7_EQ_P JOIN(KEY7NAME,eq_p)
+#define KEY7_HASH JOIN(KEY7NAME,hash)
+#endif /* defined(KEY7_TYPE) */
+
+#if defined (KEY8_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 8
+#if KEY8_TYPE == STRING
+#define KEY8TYPE char*
+#define KEY8NAME str
+#define KEY8N s
+#define KEY8STOR char key8[MAP_STRING_LENGTH]
+#define KEY8CPY(m) str_copy(m->key8, key8)
+#else
+#define KEY8TYPE int64_t
+#define KEY8NAME int64
+#define KEY8N i
+#define KEY8STOR int64_t key8
+#define KEY8CPY(m) m->key8=key8
+#endif
+#define KEY8_EQ_P JOIN(KEY8NAME,eq_p)
+#define KEY8_HASH JOIN(KEY8NAME,hash)
+#endif /* defined(KEY8_TYPE) */
+
+#if defined (KEY9_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 9
+#if KEY9_TYPE == STRING
+#define KEY9TYPE char*
+#define KEY9NAME str
+#define KEY9N s
+#define KEY9STOR char key9[MAP_STRING_LENGTH]
+#define KEY9CPY(m) str_copy(m->key9, key9)
+#else
+#define KEY9TYPE int64_t
+#define KEY9NAME int64
+#define KEY9N i
+#define KEY9STOR int64_t key9
+#define KEY9CPY(m) m->key9=key9
+#endif
+#define KEY9_EQ_P JOIN(KEY9NAME,eq_p)
+#define KEY9_HASH JOIN(KEY9NAME,hash)
+#endif /* defined(KEY9_TYPE) */
+
+/* Not so many, cowboy! */
+#if defined (KEY10_TYPE)
+#error "excessive key arity == too many array indexes"
+#endif
+
+
+
#if KEY_ARITY == 1
#define KEYSYM(x) JOIN2(x,KEY1N,VALN)
#define ALLKEYS(x) x##1
@@ -187,6 +302,26 @@
#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5
#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5
#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);}
+#elif KEY_ARITY == 6
+#define KEYSYM(x) JOIN7(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);}
+#elif KEY_ARITY == 7
+#define KEYSYM(x) JOIN8(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,KEY7N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6, x##7
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6, KEY7TYPE x##7
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);KEY7CPY(m);}
+#elif KEY_ARITY == 8
+#define KEYSYM(x) JOIN9(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,KEY7N,KEY8N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6, x##7, x##8
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6, KEY7TYPE x##7, KEY8TYPE x##8
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);KEY7CPY(m);KEY8CPY(m);}
+#elif KEY_ARITY == 9
+#define KEYSYM(x) JOIN10(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,KEY7N,KEY8N,KEY9N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6, x##7, x##8, x##9
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6, KEY7TYPE x##7, KEY8TYPE x##8, KEY9TYPE x##9
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);KEY7CPY(m);KEY8CPY(m);KEY9CPY(m);}
#endif
/* */
@@ -208,6 +343,18 @@ struct KEYSYM(map_node) {
KEY4STOR;
#if KEY_ARITY > 4
KEY5STOR;
+#if KEY_ARITY > 5
+ KEY6STOR;
+#if KEY_ARITY > 6
+ KEY7STOR;
+#if KEY_ARITY > 7
+ KEY8STOR;
+#if KEY_ARITY > 8
+ KEY9STOR;
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -266,6 +413,34 @@ static key_data KEYSYM(map_get_key) (struct map_node *mn, int n, int *type)
if (type)
*type = type_to_enum(KEY5TYPE);
break;
+#if KEY_ARITY > 5
+ case 6:
+ ptr = (key_data)m->key6;
+ if (type)
+ *type = type_to_enum(KEY6TYPE);
+ break;
+#if KEY_ARITY > 6
+ case 7:
+ ptr = (key_data)m->key7;
+ if (type)
+ *type = type_to_enum(KEY7TYPE);
+ break;
+#if KEY_ARITY > 7
+ case 8:
+ ptr = (key_data)m->key8;
+ if (type)
+ *type = type_to_enum(KEY8TYPE);
+ break;
+#if KEY_ARITY > 8
+ case 9:
+ ptr = (key_data)m->key9;
+ if (type)
+ *type = type_to_enum(KEY9TYPE);
+ break;
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -309,6 +484,34 @@ static unsigned int KEYSYM(keycheck) (ALLKEYSD(key))
if (key5 == NULL)
return 0;
#endif
+
+#if KEY_ARITY > 5
+#if KEY6_TYPE == STRING
+ if (key6 == NULL)
+ return 0;
+#endif
+
+#if KEY_ARITY > 6
+#if KEY7_TYPE == STRING
+ if (key7 == NULL)
+ return 0;
+#endif
+
+#if KEY_ARITY > 7
+#if KEY8_TYPE == STRING
+ if (key8 == NULL)
+ return 0;
+#endif
+
+#if KEY_ARITY > 8
+#if KEY9_TYPE == STRING
+ if (key9 == NULL)
+ return 0;
+#endif
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -327,6 +530,18 @@ static unsigned int KEYSYM(hash) (ALLKEYSD(key))
hash ^= KEY4_HASH(key4);
#if KEY_ARITY > 4
hash ^= KEY5_HASH(key5);
+#if KEY_ARITY > 5
+ hash ^= KEY6_HASH(key6);
+#if KEY_ARITY > 6
+ hash ^= KEY7_HASH(key7);
+#if KEY_ARITY > 7
+ hash ^= KEY8_HASH(key8);
+#if KEY_ARITY > 8
+ hash ^= KEY9_HASH(key9);
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -411,6 +626,18 @@ static int KEYSYM(__stp_map_set) (MAP map, ALLKEYSD(key), VSTYPE val, int add)
&& KEY4_EQ_P(n->key4, key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n->key5, key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n->key6, key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n->key7, key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n->key8, key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n->key9, key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -462,6 +689,18 @@ static VALTYPE KEYSYM(_stp_map_get) (MAP map, ALLKEYSD(key))
&& KEY4_EQ_P(n->key4, key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n->key5, key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n->key6, key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n->key7, key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n->key8, key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n->key9, key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -498,6 +737,18 @@ static int KEYSYM(_stp_map_del) (MAP map, ALLKEYSD(key))
&& KEY4_EQ_P(n->key4, key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n->key5, key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n->key6, key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n->key7, key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n->key8, key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n->key9, key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -535,6 +786,18 @@ static int KEYSYM(_stp_map_exists) (MAP map, ALLKEYSD(key))
&& KEY4_EQ_P(n->key4, key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n->key5, key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n->key6, key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n->key7, key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n->key8, key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n->key9, key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -582,6 +845,34 @@ static int KEYSYM(_stp_map_exists) (MAP map, ALLKEYSD(key))
#undef KEY5STOR
#undef KEY5CPY
+#undef KEY6NAME
+#undef KEY6N
+#undef KEY6TYPE
+#undef KEY6_TYPE
+#undef KEY6STOR
+#undef KEY6CPY
+
+#undef KEY7NAME
+#undef KEY7N
+#undef KEY7TYPE
+#undef KEY7_TYPE
+#undef KEY7STOR
+#undef KEY7CPY
+
+#undef KEY8NAME
+#undef KEY8N
+#undef KEY8TYPE
+#undef KEY8_TYPE
+#undef KEY8STOR
+#undef KEY8CPY
+
+#undef KEY9NAME
+#undef KEY9N
+#undef KEY9TYPE
+#undef KEY9_TYPE
+#undef KEY9STOR
+#undef KEY9CPY
+
#undef KEY_ARITY
#undef ALLKEYS
#undef ALLKEYSD
diff --git a/runtime/pmap-gen.c b/runtime/pmap-gen.c
index 86c3dc42..c95adc6b 100644
--- a/runtime/pmap-gen.c
+++ b/runtime/pmap-gen.c
@@ -26,6 +26,14 @@
#define JOIN5x(a,b,c,d,e,f) a##_##b##c##d##e##f
#define JOIN6(a,b,c,d,e,f,g) JOIN6x(a,b,c,d,e,f,g)
#define JOIN6x(a,b,c,d,e,f,g) a##_##b##c##d##e##f##g
+#define JOIN7(a,b,c,d,e,f,g,h) JOIN7x(a,b,c,d,e,f,g,h)
+#define JOIN7x(a,b,c,d,e,f,g,h) a##_##b##c##d##e##f##g##h
+#define JOIN8(a,b,c,d,e,f,g,h,i) JOIN8x(a,b,c,d,e,f,g,h,i)
+#define JOIN8x(a,b,c,d,e,f,g,h,i) a##_##b##c##d##e##f##g##h##i
+#define JOIN9(a,b,c,d,e,f,g,h,i,j) JOIN9x(a,b,c,d,e,f,g,h,i,j)
+#define JOIN9x(a,b,c,d,e,f,g,h,i,j) a##_##b##c##d##e##f##g##h##i##j
+#define JOIN10(a,b,c,d,e,f,g,h,i,j,k) JOIN10x(a,b,c,d,e,f,g,h,i,j,k)
+#define JOIN10x(a,b,c,d,e,f,g,h,i,j,k) a##_##b##c##d##e##f##g##h##i##j##k
#include "map.h"
@@ -162,6 +170,113 @@
#define KEY5_HASH JOIN(KEY5NAME,hash)
#endif /* defined(KEY5_TYPE) */
+#if defined (KEY6_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 6
+#if KEY6_TYPE == STRING
+#define KEY6TYPE char*
+#define KEY6NAME str
+#define KEY6N s
+#define KEY6STOR char key6[MAP_STRING_LENGTH]
+#define KEY6CPY(m) str_copy(m->key6, key6)
+#else
+#define KEY6TYPE int64_t
+#define KEY6NAME int64
+#define KEY6N i
+#define KEY6STOR int64_t key6
+#define KEY6CPY(m) m->key6=key6
+#endif
+#define KEY6_EQ_P JOIN(KEY6NAME,eq_p)
+#define KEY6_HASH JOIN(KEY6NAME,hash)
+#endif /* defined(KEY6_TYPE) */
+
+#if defined (KEY7_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 7
+#if KEY7_TYPE == STRING
+#define KEY7TYPE char*
+#define KEY7NAME str
+#define KEY7N s
+#define KEY7STOR char key7[MAP_STRING_LENGTH]
+#define KEY7CPY(m) str_copy(m->key7, key7)
+#else
+#define KEY7TYPE int64_t
+#define KEY7NAME int64
+#define KEY7N i
+#define KEY7STOR int64_t key7
+#define KEY7CPY(m) m->key7=key7
+#endif
+#define KEY7_EQ_P JOIN(KEY7NAME,eq_p)
+#define KEY7_HASH JOIN(KEY7NAME,hash)
+#endif /* defined(KEY7_TYPE) */
+
+#if defined (KEY7_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 7
+#if KEY7_TYPE == STRING
+#define KEY7TYPE char*
+#define KEY7NAME str
+#define KEY7N s
+#define KEY7STOR char key7[MAP_STRING_LENGTH]
+#define KEY7CPY(m) str_copy(m->key7, key7)
+#else
+#define KEY7TYPE int64_t
+#define KEY7NAME int64
+#define KEY7N i
+#define KEY7STOR int64_t key7
+#define KEY7CPY(m) m->key7=key7
+#endif
+#define KEY7_EQ_P JOIN(KEY7NAME,eq_p)
+#define KEY7_HASH JOIN(KEY7NAME,hash)
+#endif /* defined(KEY7_TYPE) */
+
+#if defined (KEY8_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 8
+#if KEY8_TYPE == STRING
+#define KEY8TYPE char*
+#define KEY8NAME str
+#define KEY8N s
+#define KEY8STOR char key8[MAP_STRING_LENGTH]
+#define KEY8CPY(m) str_copy(m->key8, key8)
+#else
+#define KEY8TYPE int64_t
+#define KEY8NAME int64
+#define KEY8N i
+#define KEY8STOR int64_t key8
+#define KEY8CPY(m) m->key8=key8
+#endif
+#define KEY8_EQ_P JOIN(KEY8NAME,eq_p)
+#define KEY8_HASH JOIN(KEY8NAME,hash)
+#endif /* defined(KEY8_TYPE) */
+
+#if defined (KEY9_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 9
+#if KEY9_TYPE == STRING
+#define KEY9TYPE char*
+#define KEY9NAME str
+#define KEY9N s
+#define KEY9STOR char key9[MAP_STRING_LENGTH]
+#define KEY9CPY(m) str_copy(m->key9, key9)
+#else
+#define KEY9TYPE int64_t
+#define KEY9NAME int64
+#define KEY9N i
+#define KEY9STOR int64_t key9
+#define KEY9CPY(m) m->key9=key9
+#endif
+#define KEY9_EQ_P JOIN(KEY9NAME,eq_p)
+#define KEY9_HASH JOIN(KEY9NAME,hash)
+#endif /* defined(KEY9_TYPE) */
+
+/* Not so many, cowboy! */
+#if defined (KEY10_TYPE)
+#error "excessive key arity == too many array indexes"
+#endif
+
+
+
#if KEY_ARITY == 1
#define KEYSYM(x) JOIN2(x,KEY1N,VALN)
#define ALLKEYS(x) x##1
@@ -187,6 +302,26 @@
#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5
#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5
#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);}
+#elif KEY_ARITY == 6
+#define KEYSYM(x) JOIN7(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);}
+#elif KEY_ARITY == 7
+#define KEYSYM(x) JOIN8(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,KEY7N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6, x##7
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6, KEY7TYPE x##7
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);KEY7CPY(m);}
+#elif KEY_ARITY == 8
+#define KEYSYM(x) JOIN9(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,KEY7N,KEY8N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6, x##7, x##8
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6, KEY7TYPE x##7, KEY8TYPE x##8
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);KEY7CPY(m);KEY8CPY(m);}
+#elif KEY_ARITY == 9
+#define KEYSYM(x) JOIN10(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,KEY7N,KEY8N,KEY9N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6, x##7, x##8, x##9
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6, KEY7TYPE x##7, KEY8TYPE x##8, KEY9TYPE x##9
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);KEY7CPY(m);KEY8CPY(m);KEY9CPY(m);}
#endif
/* */
@@ -208,6 +343,18 @@ struct KEYSYM(pmap_node) {
KEY4STOR;
#if KEY_ARITY > 4
KEY5STOR;
+#if KEY_ARITY > 5
+ KEY6STOR;
+#if KEY_ARITY > 6
+ KEY7STOR;
+#if KEY_ARITY > 7
+ KEY8STOR;
+#if KEY_ARITY > 8
+ KEY9STOR;
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -238,6 +385,18 @@ static int KEYSYM(pmap_key_cmp) (struct map_node *m1, struct map_node *m2)
&& KEY4_EQ_P(n1->key4, n2->key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n1->key5, n2->key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n1->key6, n2->key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n1->key7, n2->key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n1->key8, n2->key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n1->key9, n2->key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -282,6 +441,34 @@ static void KEYSYM(pmap_copy_keys) (struct map_node *m1, struct map_node *m2)
#else
dst->key5 = src->key5;
#endif
+#if KEY_ARITY > 5
+#if KEY6_TYPE == STRING
+ str_copy (dst->key6, src->key6);
+#else
+ dst->key6 = src->key6;
+#endif
+#if KEY_ARITY > 6
+#if KEY7_TYPE == STRING
+ str_copy (dst->key7, src->key7);
+#else
+ dst->key7 = src->key7;
+#endif
+#if KEY_ARITY > 7
+#if KEY8_TYPE == STRING
+ str_copy (dst->key8, src->key8);
+#else
+ dst->key8 = src->key8;
+#endif
+#if KEY_ARITY > 8
+#if KEY9_TYPE == STRING
+ str_copy (dst->key9, src->key9);
+#else
+ dst->key9 = src->key9;
+#endif
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -330,6 +517,34 @@ static key_data KEYSYM(pmap_get_key) (struct map_node *mn, int n, int *type)
if (type)
*type = type_to_enum(KEY5TYPE);
break;
+#if KEY_ARITY > 5
+ case 6:
+ ptr = (key_data)m->key6;
+ if (type)
+ *type = type_to_enum(KEY6TYPE);
+ break;
+#if KEY_ARITY > 6
+ case 7:
+ ptr = (key_data)m->key7;
+ if (type)
+ *type = type_to_enum(KEY7TYPE);
+ break;
+#if KEY_ARITY > 7
+ case 8:
+ ptr = (key_data)m->key8;
+ if (type)
+ *type = type_to_enum(KEY8TYPE);
+ break;
+#if KEY_ARITY > 8
+ case 9:
+ ptr = (key_data)m->key9;
+ if (type)
+ *type = type_to_enum(KEY9TYPE);
+ break;
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -373,6 +588,34 @@ static unsigned int KEYSYM(pkeycheck) (ALLKEYSD(key))
if (key5 == NULL)
return 0;
#endif
+
+#if KEY_ARITY > 5
+#if KEY6_TYPE == STRING
+ if (key6 == NULL)
+ return 0;
+#endif
+
+#if KEY_ARITY > 6
+#if KEY7_TYPE == STRING
+ if (key7 == NULL)
+ return 0;
+#endif
+
+#if KEY_ARITY > 7
+#if KEY8_TYPE == STRING
+ if (key8 == NULL)
+ return 0;
+#endif
+
+#if KEY_ARITY > 8
+#if KEY9_TYPE == STRING
+ if (key9 == NULL)
+ return 0;
+#endif
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -391,6 +634,18 @@ static unsigned int KEYSYM(phash) (ALLKEYSD(key))
hash ^= KEY4_HASH(key4);
#if KEY_ARITY > 4
hash ^= KEY5_HASH(key5);
+#if KEY_ARITY > 5
+ hash ^= KEY6_HASH(key6);
+#if KEY_ARITY > 6
+ hash ^= KEY7_HASH(key7);
+#if KEY_ARITY > 7
+ hash ^= KEY8_HASH(key8);
+#if KEY_ARITY > 8
+ hash ^= KEY9_HASH(key9);
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -504,6 +759,18 @@ static int KEYSYM(__stp_pmap_set) (MAP map, ALLKEYSD(key), VSTYPE val, int add)
&& KEY4_EQ_P(n->key4, key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n->key5, key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n->key6, key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n->key7, key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n->key8, key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n->key9, key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -587,6 +854,18 @@ static VALTYPE KEYSYM(_stp_pmap_get_cpu) (PMAP pmap, ALLKEYSD(key))
&& KEY4_EQ_P(n->key4, key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n->key5, key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n->key6, key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n->key7, key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n->key8, key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n->key9, key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -637,6 +916,18 @@ static VALTYPE KEYSYM(_stp_pmap_get) (PMAP pmap, ALLKEYSD(key))
&& KEY4_EQ_P(n->key4, key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n->key5, key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n->key6, key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n->key7, key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n->key8, key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n->key9, key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -669,6 +960,18 @@ static VALTYPE KEYSYM(_stp_pmap_get) (PMAP pmap, ALLKEYSD(key))
&& KEY4_EQ_P(n->key4, key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n->key5, key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n->key6, key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n->key7, key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n->key8, key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n->key9, key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -723,6 +1026,18 @@ static int KEYSYM(__stp_pmap_del) (MAP map, ALLKEYSD(key))
&& KEY4_EQ_P(n->key4, key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n->key5, key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n->key6, key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n->key7, key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n->key8, key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n->key9, key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -788,6 +1103,34 @@ static int KEYSYM(_stp_pmap_del) (PMAP pmap, ALLKEYSD(key))
#undef KEY5STOR
#undef KEY5CPY
+#undef KEY6NAME
+#undef KEY6N
+#undef KEY6TYPE
+#undef KEY6_TYPE
+#undef KEY6STOR
+#undef KEY6CPY
+
+#undef KEY7NAME
+#undef KEY7N
+#undef KEY7TYPE
+#undef KEY7_TYPE
+#undef KEY7STOR
+#undef KEY7CPY
+
+#undef KEY8NAME
+#undef KEY8N
+#undef KEY8TYPE
+#undef KEY8_TYPE
+#undef KEY8STOR
+#undef KEY8CPY
+
+#undef KEY9NAME
+#undef KEY9N
+#undef KEY9TYPE
+#undef KEY9_TYPE
+#undef KEY9STOR
+#undef KEY9CPY
+
#undef KEY_ARITY
#undef ALLKEYS
#undef ALLKEYSD
diff --git a/runtime/runtime.h b/runtime/runtime.h
index fc5d454f..c2e927cc 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -66,6 +66,13 @@ static struct
#define MAXTRACE 20
#endif
+/* dwarf unwinder only tested so far on i386 and x86_64. */
+#if (defined(__i386__) || defined(__x86_64__))
+#ifndef STP_USE_DWARF_UNWINDER
+#define STP_USE_DWARF_UNWINDER
+#endif
+#endif
+
#ifdef CONFIG_FRAME_POINTER
/* Just because frame pointers are available does not mean we can trust them. */
#ifndef STP_USE_DWARF_UNWINDER
@@ -73,19 +80,17 @@ static struct
#endif
#endif
-/* dwarf unwinder only tested so far on i386 and x86_64,
- but globally disabled for now */
-#if 0
-// !defined(STP_USE_FRAME_BUFFER) && (defined(__i386__) || defined(__x86_64__))
-#define STP_USE_DWARF_UNWINDER
-#endif
-
#include "alloc.c"
#include "print.c"
#include "string.c"
#include "io.c"
#include "arith.c"
#include "copy.c"
+#include "regs.c"
+#include "regs-ia64.c"
+
+#include "task_finder.c"
+
#include "sym.c"
#ifdef STP_PERFMON
#include "perf.c"
diff --git a/runtime/stack.c b/runtime/stack.c
index f6b1cd08..68fb9b1f 100644
--- a/runtime/stack.c
+++ b/runtime/stack.c
@@ -97,6 +97,12 @@ static void _stp_stack_print_fallback(unsigned long stack, int verbose, int leve
&print_data);
}
#endif
+
+// Without KPROBES very little works atm.
+// But this file is unconditionally imported, while these two functions are only
+// used through context-unwind.stp.
+#if defined (CONFIG_KPROBES)
+
/** Prints the stack backtrace
* @param regs A pointer to the struct pt_regs.
*/
@@ -141,6 +147,8 @@ static void _stp_stack_snprint(char *str, int size, struct pt_regs *regs, int ve
pb->len = 0;
}
+#endif /* CONFIG_KPROBES */
+
/** Prints the user stack backtrace
* @param str string
* @returns Same string as was input with trace info appended,
diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c
index 8200ec9d..26b166c2 100644
--- a/runtime/staprun/common.c
+++ b/runtime/staprun/common.c
@@ -82,7 +82,7 @@ int stap_strfloctime(char *buf, size_t max, const char *fmt, time_t t)
num = tm.tm_year % 100;
goto numbering02;
case 'C':
- num = ((tm.tm_year + 1900 - 1) / 100) + 1;
+ num = ((tm.tm_year + 1900) / 100);
goto numbering;
case 'm':
num = tm.tm_mon + 1;
@@ -107,7 +107,7 @@ int stap_strfloctime(char *buf, size_t max, const char *fmt, time_t t)
if (num == 0) num = 12;
goto numbering02;
case 'j':
- ret = snprintf(c, end - c, "%03d", tm.tm_yday);
+ ret = snprintf(c, end - c, "%03d", tm.tm_yday + 1);
if (ret < 0) return ret;
c += ret;
break;
@@ -117,7 +117,10 @@ int stap_strfloctime(char *buf, size_t max, const char *fmt, time_t t)
case 'l':
num = tm.tm_hour % 12;
if (num == 0) num = 12;
- goto numbering;
+ ret = snprintf(c, end - c, "%2d", num);
+ if (ret < 0) return ret;
+ c += ret;
+ break;
case 'M':
num = tm.tm_min;
goto numbering02;
diff --git a/runtime/staprun/relay.c b/runtime/staprun/relay.c
index 50f295b5..b9796241 100644
--- a/runtime/staprun/relay.c
+++ b/runtime/staprun/relay.c
@@ -185,7 +185,7 @@ static void *reader_thread(void *data)
dbug(3, "cpu=%d poll=%d errno=%d\n", cpu, rc, errno);
if (errno != EINTR) {
_perr("poll error");
- return(NULL);
+ goto error_out;
}
}
while ((rc = read(relay_fd[cpu], buf, sizeof(buf))) > 0) {
@@ -198,17 +198,24 @@ static void *reader_thread(void *data)
remove_file = 1;
if (open_outfile(fnum, cpu, remove_file) < 0) {
perr("Couldn't open file for cpu %d, exiting.", cpu);
- return(NULL);
+ goto error_out;
}
- wsize = 0;
+ wsize = rc;
}
if (write(out_fd[cpu], buf, rc) != rc) {
- perr("Couldn't write to output %d for cpu %d, exiting.", out_fd[cpu], cpu);
- return(NULL);
+ if (errno != EPIPE)
+ perr("Couldn't write to output %d for cpu %d, exiting.", out_fd[cpu], cpu);
+ goto error_out;
}
}
} while (!stop_threads);
- dbug(3, "exiting thread %d\n", cpu);
+ dbug(3, "exiting thread for cpu %d\n", cpu);
+ return(NULL);
+
+error_out:
+ /* Signal the main thread that we need to quit */
+ kill(getpid(), SIGTERM);
+ dbug(2, "exiting thread for cpu %d after error\n", cpu);
return(NULL);
}
diff --git a/runtime/staprun/relay_old.c b/runtime/staprun/relay_old.c
index ef8fd0da..33d2daf3 100644
--- a/runtime/staprun/relay_old.c
+++ b/runtime/staprun/relay_old.c
@@ -239,14 +239,15 @@ static int process_subbufs(struct _stp_buf_info *info,
scb->rmfile = 1;
if (open_oldoutfile(scb->fnum, cpu, scb->rmfile) < 0) {
perr("Couldn't open file for cpu %d, exiting.", cpu);
- exit(1);
+ return -1;
}
- scb->wsize = 0;
+ scb->wsize = len;
}
if (len) {
if (fwrite_unlocked (subbuf_ptr, len, 1, percpu_tmpfile[cpu]) != 1) {
- _perr("Couldn't write to output file for cpu %d, exiting:", cpu);
- exit(1);
+ if (errno != EPIPE)
+ _perr("Couldn't write to output file for cpu %d, exiting:", cpu);
+ return -1;
}
}
subbufs_consumed++;
@@ -281,14 +282,17 @@ static void *reader_thread(void *data)
if (rc < 0) {
if (errno != EINTR) {
_perr("poll error");
- exit(1);
+ break;
}
err("WARNING: poll warning: %s\n", strerror(errno));
rc = 0;
}
rc = read(proc_fd[cpu], &status[cpu].info, sizeof(struct _stp_buf_info));
- subbufs_consumed = process_subbufs(&status[cpu].info, &scb);
+ rc = process_subbufs(&status[cpu].info, &scb);
+ if (rc < 0)
+ break;
+ subbufs_consumed = rc;
if (subbufs_consumed) {
if (subbufs_consumed > status[cpu].max_backlog)
status[cpu].max_backlog = subbufs_consumed;
@@ -301,6 +305,10 @@ static void *reader_thread(void *data)
if (status[cpu].info.flushing)
pthread_exit(NULL);
} while (1);
+
+ /* Signal the main thread that we need to quit */
+ kill(getpid(), SIGTERM);
+ pthread_exit(NULL);
}
/**
@@ -320,7 +328,7 @@ int write_realtime_data(void *data, ssize_t nb)
perr("Couldn't open file, exiting.");
return -1;
}
- global_scb.wsize = 0;
+ global_scb.wsize = nb;
}
bw = write(out_fd[0], data, nb);
if (bw >= 0 && bw != nb) {
diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c
index e94e5d13..49b37988 100644
--- a/runtime/staprun/staprun_funcs.c
+++ b/runtime/staprun/staprun_funcs.c
@@ -316,8 +316,21 @@ int check_permissions(void)
int path_check = 0;
/* If we're root, we can do anything. */
- if (getuid() == 0)
+ if (getuid() == 0) {
+ /* ... like overriding the real UID */
+ const char *env_id = getenv("SYSTEMTAP_REAL_UID");
+ if (env_id && setreuid(atoi(env_id), -1))
+ err("WARNING: couldn't set staprun UID to '%s': %s",
+ env_id, strerror(errno));
+
+ /* ... or overriding the real GID */
+ env_id = getenv("SYSTEMTAP_REAL_GID");
+ if (env_id && setregid(atoi(env_id), -1))
+ err("WARNING: couldn't set staprun GID to '%s': %s",
+ env_id, strerror(errno));
+
return 1;
+ }
/* Lookup the gid for group "stapdev" */
errno = 0;
diff --git a/runtime/sym.c b/runtime/sym.c
index 1d88a862..f6f97ac2 100644
--- a/runtime/sym.c
+++ b/runtime/sym.c
@@ -13,6 +13,7 @@
#define _STP_SYM_C_
#include "string.c"
+#include "task_finder_vma.c"
/** @file sym.c
* @addtogroup sym Symbolic Functions
@@ -20,6 +21,62 @@
* @{
*/
+static void _stp_sym_init(void)
+{
+ static int initialized = 0;
+ if (! initialized) {
+ __stp_tf_vma_initialize();
+ initialized = 1;
+ }
+}
+
+/* Callback that needs to be registered (in tapsets.cxx for
+ emit_module_init) for every user task path or pid for which we
+ might need symbols or unwind info. */
+static int _stp_tf_mmap_cb(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ char *path,
+ unsigned long addr,
+ unsigned long length,
+ unsigned long offset,
+ unsigned long vm_flags)
+{
+ int i;
+ struct _stp_module *module = NULL;
+
+#ifdef DEBUG_TASK_FINDER_VMA
+ _stp_dbug(__FUNCTION__, __LINE__,
+ "mmap_cb: tsk %d:%d path %s, addr 0x%08lx, length 0x%08lx, offset 0x%lx, flags 0x%lx\n",
+ tsk->pid, tsk->tgid, path, addr, length, offset, vm_flags);
+#endif
+ if (path != NULL) {
+ for (i = 0; i < _stp_num_modules; i++) {
+ if (strcmp(path, _stp_modules[i]->path) == 0)
+ {
+#ifdef DEBUG_TASK_FINDER_VMA
+ _stp_dbug(__FUNCTION__, __LINE__,
+ "vm_cb: matched path %s to module\n",
+ path);
+#endif
+ module = _stp_modules[i];
+ break;
+ }
+ }
+ }
+ stap_add_vma_map_info(tsk->group_leader, addr, addr + length, offset,
+ module);
+ return 0;
+}
+
+static int _stp_tf_munmap_cb(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ unsigned long addr,
+ unsigned long length)
+{
+ stap_remove_vma_map_info(tsk->group_leader, addr, addr + length, 0);
+ return 0;
+}
+
/* XXX: this needs to be address-space-specific. */
static unsigned long _stp_module_relocate(const char *module, const char *section, unsigned long offset)
{
@@ -71,35 +128,54 @@ static unsigned long _stp_module_relocate(const char *module, const char *sectio
return 0;
}
-
-/* Return module owner and fills in closest section of the address
- if found, return NULL otherwise.
+/* Return module owner and, if sec != NULL, fills in closest section
+ of the address if found, return NULL otherwise.
XXX: needs to be address-space-specific. */
static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr,
+ struct task_struct *task,
struct _stp_section **sec)
{
- struct _stp_module *m = NULL;
+ void *user = NULL;
unsigned midx = 0;
- unsigned long closest_section_offset = ~0;
+
+ // Try vma matching first if task given.
+ if (task)
+ {
+ unsigned long vm_start = 0;
+ if (stap_find_vma_map_info(task->group_leader, addr,
+ &vm_start, NULL,
+ NULL, &user) == 0)
+ if (user != NULL)
+ {
+ struct _stp_module *m = (struct _stp_module *)user;
+ if (sec)
+ *sec = &m->sections[0]; // XXX check actual section and relocate
+ dbug_sym(1, "found section %s in module %s at 0x%lx\n",
+ m->sections[0].name, m->name, vm_start);
+ if (strcmp(".dynamic", m->sections[0].name) == 0)
+ m->sections[0].addr = vm_start; // cheat...
+ return m;
+ }
+ }
+
for (midx = 0; midx < _stp_num_modules; midx++)
{
unsigned secidx;
for (secidx = 0; secidx < _stp_modules[midx]->num_sections; secidx++)
{
- unsigned long this_section_addr;
- unsigned long this_section_offset;
- this_section_addr = _stp_modules[midx]->sections[secidx].addr;
- if (addr < this_section_addr) continue;
- this_section_offset = addr - this_section_addr;
- if (this_section_offset < closest_section_offset)
- {
- closest_section_offset = this_section_offset;
- m = _stp_modules[midx];
- *sec = & m->sections[secidx];
+ unsigned long sec_addr;
+ unsigned long sec_size;
+ sec_addr = _stp_modules[midx]->sections[secidx].addr;
+ sec_size = _stp_modules[midx]->sections[secidx].size;
+ if (addr >= sec_addr && addr < sec_addr + sec_size)
+ {
+ if (sec)
+ *sec = & _stp_modules[midx]->sections[secidx];
+ return _stp_modules[midx];
}
}
}
- return m;
+ return NULL;
}
@@ -108,14 +184,15 @@ static const char *_stp_kallsyms_lookup(unsigned long addr, unsigned long *symbo
unsigned long *offset,
const char **modname,
/* char ** secname? */
- char *namebuf)
+ char *namebuf,
+ struct task_struct *task)
{
struct _stp_module *m = NULL;
struct _stp_section *sec = NULL;
struct _stp_symbol *s = NULL;
unsigned end, begin = 0;
- m = _stp_mod_sec_lookup(addr, &sec);
+ m = _stp_mod_sec_lookup(addr, task, &sec);
if (unlikely (m == NULL || sec == NULL))
return NULL;
@@ -240,7 +317,7 @@ static void _stp_symbol_print(unsigned long address)
const char *name;
unsigned long offset, size;
- name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL);
+ name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, NULL);
_stp_printf("%p", (int64_t) address);
@@ -265,7 +342,7 @@ static int _stp_func_print(unsigned long address, int verbose, int exact)
else
exstr = " (inexact)";
- name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL);
+ name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, NULL);
if (name) {
if (verbose) {
@@ -281,16 +358,29 @@ static int _stp_func_print(unsigned long address, int verbose, int exact)
return 0;
}
-static void _stp_symbol_snprint(char *str, size_t len, unsigned long address)
+/** Puts symbolic information of an address in a string.
+ * @param src The string to fill in.
+ * @param len The length of the given src string.
+ * @param address The address to lookup.
+ * @param add_mod Whether to include module name information if found.
+ */
+
+static void _stp_symbol_snprint(char *str, size_t len, unsigned long address,
+ struct task_struct *task, int add_mod)
{
const char *modname;
const char *name;
unsigned long offset, size;
- name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL);
- if (name)
- strlcpy(str, name, len);
- else
+ name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL,
+ task);
+ if (name) {
+ if (add_mod && modname && *modname)
+ _stp_snprintf(str, len, "%s %s+%#lx/%#lx",
+ name, modname, offset, size);
+ else
+ strlcpy(str, name, len);
+ } else
_stp_snprintf(str, len, "%p", (int64_t) address);
}
diff --git a/runtime/sym.h b/runtime/sym.h
index 586b10ca..80c334fb 100644
--- a/runtime/sym.h
+++ b/runtime/sym.h
@@ -18,6 +18,7 @@ struct _stp_symbol {
struct _stp_section {
const char *name;
unsigned long addr; /* XXX: belongs in per-address-space tables */
+ unsigned long size; /* length of the address space module covers. */
struct _stp_symbol *symbols; /* ordered by address */
unsigned num_symbols;
};
diff --git a/runtime/syscall.h b/runtime/syscall.h
index ae451070..6d22ba83 100644
--- a/runtime/syscall.h
+++ b/runtime/syscall.h
@@ -1,5 +1,6 @@
-/* syscall defines and inlines
- * Copyright (C) 2008 Red Hat Inc.
+/*
+ * syscall defines and inlines
+ * Copyright (C) 2008-2009 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
@@ -89,9 +90,17 @@
#error "Unimplemented architecture"
#endif
+#ifdef STAPCONF_ASM_SYSCALL_H
+
+/* If the system has asm/syscall.h, use defines from it. */
+#include <asm/syscall.h>
+
+#else /* !STAPCONF_ASM_SYSCALL_H */
+
+/* If the system doesn't have asm/syscall.h, use our defines. */
#if defined(__i386__) || defined(__x86_64__)
-static inline unsigned long
-__stp_user_syscall_nr(struct pt_regs *regs)
+static inline long
+syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
{
#if defined(STAPCONF_X86_UNIREGS)
return regs->orig_ax;
@@ -104,37 +113,37 @@ __stp_user_syscall_nr(struct pt_regs *regs)
#endif
#if defined(__powerpc__)
-static inline unsigned long
-__stp_user_syscall_nr(struct pt_regs *regs)
+static inline long
+syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
{
return regs->gpr[0];
}
#endif
#if defined(__ia64__)
-static inline unsigned long
-__stp_user_syscall_nr(struct pt_regs *regs)
+static inline long
+syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
{
return regs->r15;
}
#endif
#if defined(__s390__) || defined(__s390x__)
-static inline unsigned long
-__stp_user_syscall_nr(struct pt_regs *regs)
+static inline long
+syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
{
- // might need to be 'orig_gpr2'
+ // might need to be 'orig_gpr2'
return regs->gprs[2];
}
#endif
#if defined(__i386__) || defined(__x86_64__)
-static inline long *
-__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
+static inline long
+syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
{
#ifdef CONFIG_IA32_EMULATION
// This code works, but isn't what we need. Since
-// __stp_user_syscall_arg() doesn't sign-extend, a value passed in as
+// syscall_get_syscall_arg() doesn't sign-extend, a value passed in as
// an argument and then returned won't compare correctly anymore. So,
// for now, disable this code.
# if 0
@@ -145,158 +154,233 @@ __stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
# endif
#endif
#if defined(STAPCONF_X86_UNIREGS)
- return &regs->ax;
+ return regs->ax;
#elif defined(__x86_64__)
- return &regs->rax;
+ return regs->rax;
#elif defined (__i386__)
- return &regs->eax;
+ return regs->eax;
#endif
}
#endif
#if defined(__powerpc__)
-static inline long *
-__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
+static inline long
+syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
{
- return &regs->gpr[3];
+ return regs->gpr[3];
}
#endif
#if defined(__ia64__)
-static inline long *
-__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
+static inline long
+syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
{
- return &regs->r8;
+ return regs->r8;
}
#endif
#if defined(__s390__) || defined(__s390x__)
-static inline long *
-__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
+static inline long
+syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
{
- return &regs->gprs[2];
+ return regs->gprs[2];
}
#endif
#if defined(__i386__) || defined(__x86_64__)
-static inline long *
-__stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
- unsigned int n)
+static inline void
+syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
+ unsigned int i, unsigned int n, unsigned long *args)
{
-#if defined(__i386__)
- if (n > 5) {
- _stp_error("syscall arg > 5");
- return NULL;
+ if (i + n > 6) {
+ _stp_error("invalid syscall arg request");
+ return;
}
+#if defined(__i386__)
#if defined(STAPCONF_X86_UNIREGS)
- return &regs->bx + n;
+ memcpy(args, &regs->bx + i, n * sizeof(args[0]));
#else
- return &regs->ebx + n;
+ memcpy(args, &regs->ebx + i, n * sizeof(args[0]));
#endif
#elif defined(__x86_64__)
#ifdef CONFIG_IA32_EMULATION
- if (test_tsk_thread_flag(task, TIF_IA32))
- switch (n) {
+ if (test_tsk_thread_flag(task, TIF_IA32)) {
+ switch (i) {
#if defined(STAPCONF_X86_UNIREGS)
- case 0: return &regs->bx;
- case 1: return &regs->cx;
- case 2: return &regs->dx;
- case 3: return &regs->si;
- case 4: return &regs->di;
- case 5: return &regs->bp;
+ case 0:
+ if (!n--) break;
+ *args++ = regs->bx;
+ case 1:
+ if (!n--) break;
+ *args++ = regs->cx;
+ case 2:
+ if (!n--) break;
+ *args++ = regs->dx;
+ case 3:
+ if (!n--) break;
+ *args++ = regs->si;
+ case 4:
+ if (!n--) break;
+ *args++ = regs->di;
+ case 5:
+ if (!n--) break;
+ *args++ = regs->bp;
#else
- case 0: return &regs->rbx;
- case 1: return &regs->rcx;
- case 2: return &regs->rdx;
- case 3: return &regs->rsi;
- case 4: return &regs->rdi;
- case 5: return &regs->rbp;
+ case 0:
+ if (!n--) break;
+ *args++ = regs->rbx;
+ case 1:
+ if (!n--) break;
+ *args++ = regs->rcx;
+ case 2:
+ if (!n--) break;
+ *args++ = regs->rdx;
+ case 3:
+ if (!n--) break;
+ *args++ = regs->rsi;
+ case 4:
+ if (!n--) break;
+ *args++ = regs->rdi;
+ case 5:
+ if (!n--) break;
+ *args++ = regs->rbp;
#endif
- default:
- _stp_error("syscall arg > 5");
- return NULL;
}
+ return;
+ }
#endif /* CONFIG_IA32_EMULATION */
- switch (n) {
+ switch (i) {
#if defined(STAPCONF_X86_UNIREGS)
- case 0: return &regs->di;
- case 1: return &regs->si;
- case 2: return &regs->dx;
- case 3: return &regs->r10;
- case 4: return &regs->r8;
- case 5: return &regs->r9;
+ case 0:
+ if (!n--) break;
+ *args++ = regs->di;
+ case 1:
+ if (!n--) break;
+ *args++ = regs->si;
+ case 2:
+ if (!n--) break;
+ *args++ = regs->dx;
+ case 3:
+ if (!n--) break;
+ *args++ = regs->r10;
+ case 4:
+ if (!n--) break;
+ *args++ = regs->r8;
+ case 5:
+ if (!n--) break;
+ *args++ = regs->r9;
#else
- case 0: return &regs->rdi;
- case 1: return &regs->rsi;
- case 2: return &regs->rdx;
- case 3: return &regs->r10;
- case 4: return &regs->r8;
- case 5: return &regs->r9;
+ case 0:
+ if (!n--) break;
+ *args++ = regs->rdi;
+ case 1:
+ if (!n--) break;
+ *args++ = regs->rsi;
+ case 2:
+ if (!n--) break;
+ *args++ = regs->rdx;
+ case 3:
+ if (!n--) break;
+ *args++ = regs->r10;
+ case 4:
+ if (!n--) break;
+ *args++ = regs->r8;
+ case 5:
+ if (!n--) break;
+ *args++ = regs->r9;
#endif
- default:
- _stp_error("syscall arg > 5");
- return NULL;
}
#endif /* CONFIG_X86_32 */
+ return;
}
#endif
#if defined(__powerpc__)
-static inline long *
-__stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
- unsigned int n)
+static inline void
+syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
+ unsigned int i, unsigned int n, unsigned long *args)
{
- switch (n) {
- case 0: return &regs->gpr[3];
- case 1: return &regs->gpr[4];
- case 2: return &regs->gpr[5];
- case 3: return &regs->gpr[6];
- case 4: return &regs->gpr[7];
- case 5: return &regs->gpr[8];
- default:
- _stp_error("syscall arg > 5");
- return NULL;
+ if (i + n > 6) {
+ _stp_error("invalid syscall arg request");
+ return;
}
+ memcpy(args, &regs->gpr[3 + i], n * sizeof(args[0]));
}
#endif
#if defined(__ia64__)
-#define __stp_user_syscall_arg(task, regs, n) \
- ____stp_user_syscall_arg(task, regs, n, &c->unwaddr)
+#define syscall_get_arguments(task, regs, i, n, args) \
+ __ia64_syscall_get_arguments(task, regs, i, n, args, &c->unwaddr)
-static inline long *
-____stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
- unsigned int n, unsigned long **cache)
+static inline void
+__ia64_syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
+ unsigned int i, unsigned int n,
+ unsigned long *args, unsigned long **cache)
{
- if (n > 5) {
- _stp_error("syscall arg > 5");
- return NULL;
+ if (i + n > 6) {
+ _stp_error("invalid syscall arg request");
+ return;
+ }
+ switch (i) {
+ case 0:
+ if (!n--) break;
+ *args++ = *__ia64_fetch_register(i + 32, regs, cache);
+ case 1:
+ if (!n--) break;
+ *args++ = *__ia64_fetch_register(i + 33, regs, cache);
+ case 2:
+ if (!n--) break;
+ *args++ = *__ia64_fetch_register(i + 34, regs, cache);
+ case 3:
+ if (!n--) break;
+ *args++ = *__ia64_fetch_register(i + 35, regs, cache);
+ case 4:
+ if (!n--) break;
+ *args++ = *__ia64_fetch_register(i + 36, regs, cache);
+ case 5:
+ if (!n--) break;
+ *args++ = *__ia64_fetch_register(i + 37, regs, cache);
}
- return __ia64_fetch_register(n + 32, regs, cache);
}
#endif
#if defined(__s390__) || defined(__s390x__)
-static inline long *
-__stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
- unsigned int n)
+static inline void
+syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
+ unsigned int i, unsigned int n, unsigned long *args)
{
- /* If we were returning a value, we could check for TIF_31BIT
- * here and cast the value with '(u32)' to make sure it got
- * down to 32bits. But, since we're returning an address,
- * there isn't much we can do. */
- switch (n) {
- case 0: return &regs->orig_gpr2;
- case 1: return &regs->gprs[3];
- case 2: return &regs->gprs[4];
- case 3: return &regs->gprs[5];
- case 4: return &regs->gprs[6];
- case 5: return &regs->args[0];
- default:
- _stp_error("syscall arg > 5");
- return NULL;
+ unsigned long mask = -1UL;
+
+ if (i + n > 6) {
+ _stp_error("invalid syscall arg request");
+ return;
+ }
+#ifdef CONFIG_COMPAT
+ if (test_tsk_thread_flag(task, TIF_31BIT))
+ mask = 0xffffffff;
+#endif
+ switch (i) {
+ case 0:
+ if (!n--) break;
+ *args++ = regs->orig_gpr2 & mask;
+ case 1:
+ if (!n--) break;
+ *args++ = regs->gprs[3] & mask;
+ case 2:
+ if (!n--) break;
+ *args++ = regs->gprs[4] & mask;
+ case 3:
+ if (!n--) break;
+ *args++ = regs->gprs[5] & mask;
+ case 4:
+ if (!n--) break;
+ *args++ = regs->gprs[6] & mask;
+ case 5:
+ if (!n--) break;
+ *args++ = regs->args[0] & mask;
}
}
#endif
+#endif /* !STAPCONF_ASM_SYSCALL_H */
#endif /* _SYSCALL_H_ */
diff --git a/runtime/task_finder.c b/runtime/task_finder.c
index 7949a81f..fa6c296e 100644
--- a/runtime/task_finder.c
+++ b/runtime/task_finder.c
@@ -2,8 +2,9 @@
#define TASK_FINDER_C
#if ! defined(CONFIG_UTRACE)
-#error "Need CONFIG_UTRACE!"
-#endif
+/* Dummy definitions for use in sym.c */
+struct stap_task_finder_target { };
+#else
#include <linux/utrace.h>
@@ -18,7 +19,6 @@
#include "syscall.h"
#include "utrace_compatibility.h"
-#include "task_finder_vma.c"
static LIST_HEAD(__stp_task_finder_list);
@@ -62,46 +62,26 @@ typedef int (*stap_task_finder_callback)(struct stap_task_finder_target *tgt,
int register_p,
int process_p);
-typedef int (*stap_task_finder_vm_callback)(struct stap_task_finder_target *tgt,
- struct task_struct *tsk,
- int map_p, char *vm_path,
- unsigned long vm_start,
- unsigned long vm_end,
- unsigned long vm_pgoff);
-
-static int __stp_tf_vm_cb(struct stap_task_finder_target *tgt,
- struct task_struct *tsk,
- int map_p, char *vm_path,
- unsigned long vm_start,
- unsigned long vm_end,
- unsigned long vm_pgoff)
-{
- int i;
-#ifdef DEBUG_TASK_FINDER_VMA
- _stp_dbug(__FUNCTION__, __LINE__,
- "vm_cb: tsk %d:%d path %s, start 0x%08lx, end 0x%08lx, offset 0x%lx\n",
- tsk->pid, map_p, vm_path, vm_start, vm_end, vm_pgoff);
-#endif
- if (map_p) {
- struct _stp_module *module = NULL;
- if (vm_path != NULL)
- for (i = 0; i < _stp_num_modules; i++)
- if (strcmp(vm_path, _stp_modules[i]->path) == 0)
- {
-#ifdef DEBUG_TASK_FINDER_VMA
- _stp_dbug(__FUNCTION__, __LINE__,
- "vm_cb: matched path %s to module\n", vm_path);
-#endif
- module = _stp_modules[i];
- break;
- }
- stap_add_vma_map_info(tsk, vm_start, vm_end, vm_pgoff, module);
- }
- else {
- stap_remove_vma_map_info(tsk, vm_start, vm_end, vm_pgoff);
- }
- return 0;
-}
+typedef int
+(*stap_task_finder_mmap_callback)(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ char *path,
+ unsigned long addr,
+ unsigned long length,
+ unsigned long offset,
+ unsigned long vm_flags);
+typedef int
+(*stap_task_finder_munmap_callback)(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ unsigned long addr,
+ unsigned long length);
+
+typedef int
+(*stap_task_finder_mprotect_callback)(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ unsigned long addr,
+ unsigned long length,
+ int prot);
struct stap_task_finder_target {
/* private: */
@@ -110,14 +90,18 @@ struct stap_task_finder_target {
struct list_head callback_list;
struct utrace_engine_ops ops;
unsigned engine_attached:1;
- unsigned vm_events:1;
+ unsigned mmap_events:1;
+ unsigned munmap_events:1;
+ unsigned mprotect_events:1;
size_t pathlen;
/* public: */
const char *pathname;
pid_t pid;
stap_task_finder_callback callback;
- stap_task_finder_vm_callback vm_callback;
+ stap_task_finder_mmap_callback mmap_callback;
+ stap_task_finder_munmap_callback munmap_callback;
+ stap_task_finder_mprotect_callback mprotect_callback;
};
#ifdef UTRACE_ORIG_VERSION
@@ -145,19 +129,6 @@ __stp_utrace_task_finder_target_quiesce(enum utrace_resume_action action,
#ifdef UTRACE_ORIG_VERSION
static u32
-__stp_utrace_task_finder_target_syscall_entry(struct utrace_attached_engine *engine,
- struct task_struct *tsk,
- struct pt_regs *regs);
-#else
-static u32
-__stp_utrace_task_finder_target_syscall_entry(enum utrace_resume_action action,
- struct utrace_attached_engine *engine,
- struct task_struct *tsk,
- struct pt_regs *regs);
-#endif
-
-#ifdef UTRACE_ORIG_VERSION
-static u32
__stp_utrace_task_finder_target_syscall_exit(struct utrace_attached_engine *engine,
struct task_struct *tsk,
struct pt_regs *regs);
@@ -189,12 +160,12 @@ stap_register_task_finder_target(struct stap_task_finder_target *new_tgt)
// Make sure everything is initialized properly.
new_tgt->engine_attached = 0;
- new_tgt->vm_events = 0;
+ new_tgt->mmap_events = 0;
+ new_tgt->munmap_events = 0;
+ new_tgt->mprotect_events = 0;
memset(&new_tgt->ops, 0, sizeof(new_tgt->ops));
new_tgt->ops.report_death = &__stp_utrace_task_finder_target_death;
new_tgt->ops.report_quiesce = &__stp_utrace_task_finder_target_quiesce;
- new_tgt->ops.report_syscall_entry = \
- &__stp_utrace_task_finder_target_syscall_entry;
new_tgt->ops.report_syscall_exit = \
&__stp_utrace_task_finder_target_syscall_exit;
@@ -208,7 +179,7 @@ stap_register_task_finder_target(struct stap_task_finder_target *new_tgt)
&& strcmp(tgt->pathname, new_tgt->pathname) == 0)
/* pid-based target (a specific pid or all
* pids) */
- || (new_tgt->pathlen == 0
+ || (new_tgt->pathlen == 0 && tgt->pathlen == 0
&& tgt->pid == new_tgt->pid))) {
found_node = 1;
break;
@@ -226,9 +197,13 @@ stap_register_task_finder_target(struct stap_task_finder_target *new_tgt)
// Add this target to the callback list for this task.
list_add_tail(&new_tgt->callback_list, &tgt->callback_list_head);
- // If the new target has a vm_callback, remember this.
- if (new_tgt->vm_callback != NULL)
- tgt->vm_events = 1;
+ // If the new target has any m* callbacks, remember this.
+ if (new_tgt->mmap_callback != NULL)
+ tgt->mmap_events = 1;
+ if (new_tgt->munmap_callback != NULL)
+ tgt->munmap_events = 1;
+ if (new_tgt->mprotect_callback != NULL)
+ tgt->mprotect_events = 1;
return 0;
}
@@ -411,15 +386,14 @@ __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen)
/*
* __STP_TASK_BASE_EVENTS: base events for stap_task_finder_target's
- * without vm_callback's
+ * without map callback's
*
* __STP_TASK_VM_BASE_EVENTS: base events for
- * stap_task_finder_target's with vm_callback's
+ * stap_task_finder_target's with map callback's
*/
#define __STP_TASK_BASE_EVENTS (UTRACE_EVENT(DEATH))
#define __STP_TASK_VM_BASE_EVENTS (__STP_TASK_BASE_EVENTS \
- | UTRACE_EVENT(SYSCALL_ENTRY)\
| UTRACE_EVENT(SYSCALL_EXIT))
/*
@@ -431,8 +405,10 @@ __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen)
#define __STP_ATTACHED_TASK_EVENTS (__STP_TASK_BASE_EVENTS \
| UTRACE_EVENT(QUIESCE))
-#define __STP_ATTACHED_TASK_BASE_EVENTS(tgt) \
- ((tgt)->vm_events ? __STP_TASK_VM_BASE_EVENTS : __STP_TASK_BASE_EVENTS)
+#define __STP_ATTACHED_TASK_BASE_EVENTS(tgt) \
+ (((tgt)->mmap_events || (tgt)->munmap_events \
+ || (tgt)->mprotect_events) \
+ ? __STP_TASK_VM_BASE_EVENTS : __STP_TASK_BASE_EVENTS)
static int
__stp_utrace_attach(struct task_struct *tsk,
@@ -548,11 +524,113 @@ __stp_call_callbacks(struct stap_task_finder_target *tgt,
}
}
+static void
+__stp_call_mmap_callbacks(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk, char *path,
+ unsigned long addr, unsigned long length,
+ unsigned long offset, unsigned long vm_flags)
+{
+ struct list_head *cb_node;
+ int rc;
+
+ if (tgt == NULL || tsk == NULL)
+ return;
+
+#ifdef DEBUG_TASK_FINDER_VMA
+ _stp_dbug(__FUNCTION__, __LINE__,
+ "pid %d, a/l/o/p/path 0x%lx 0x%lx 0x%lx %c%c%c%c %s\n",
+ tsk->pid, addr, length, offset,
+ vm_flags & VM_READ ? 'r' : '-',
+ vm_flags & VM_WRITE ? 'w' : '-',
+ vm_flags & VM_EXEC ? 'x' : '-',
+ vm_flags & VM_MAYSHARE ? 's' : 'p',
+ path);
+#endif
+ list_for_each(cb_node, &tgt->callback_list_head) {
+ struct stap_task_finder_target *cb_tgt;
+
+ cb_tgt = list_entry(cb_node, struct stap_task_finder_target,
+ callback_list);
+ if (cb_tgt == NULL || cb_tgt->mmap_callback == NULL)
+ continue;
+
+ rc = cb_tgt->mmap_callback(cb_tgt, tsk, path, addr, length,
+ offset, vm_flags);
+ if (rc != 0) {
+ _stp_error("mmap callback for %d failed: %d",
+ (int)tsk->pid, rc);
+ }
+ }
+}
+
+static void
+__stp_call_mmap_callbacks_with_vma(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ struct vm_area_struct *vma)
+{
+ char *mmpath_buf;
+ char *mmpath;
+ int rc;
+
+ // Allocate space for a path
+ mmpath_buf = _stp_kmalloc(PATH_MAX);
+ if (mmpath_buf == NULL) {
+ _stp_error("Unable to allocate space for path");
+ return;
+ }
+
+ // Grab the path associated with this vma.
+#ifdef STAPCONF_DPATH_PATH
+ mmpath = d_path(&(vma->vm_file->f_path), mmpath_buf, PATH_MAX);
+#else
+ mmpath = d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt,
+ mmpath_buf, PATH_MAX);
+#endif
+ if (mmpath == NULL || IS_ERR(mmpath)) {
+ rc = -PTR_ERR(mmpath);
+ _stp_error("Unable to get path (error %d) for pid %d",
+ rc, (int)tsk->pid);
+ }
+ else {
+ __stp_call_mmap_callbacks(tgt, tsk, mmpath, vma->vm_start,
+ vma->vm_end - vma->vm_start,
+ (vma->vm_pgoff << PAGE_SHIFT),
+ vma->vm_flags);
+ }
+ _stp_kfree(mmpath_buf);
+}
+
+static inline void
+__stp_call_munmap_callbacks(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk, unsigned long addr,
+ unsigned long length)
+{
+ struct list_head *cb_node;
+ int rc;
+
+ if (tgt == NULL || tsk == NULL)
+ return;
+
+ list_for_each(cb_node, &tgt->callback_list_head) {
+ struct stap_task_finder_target *cb_tgt;
+
+ cb_tgt = list_entry(cb_node, struct stap_task_finder_target,
+ callback_list);
+ if (cb_tgt == NULL || cb_tgt->munmap_callback == NULL)
+ continue;
+
+ rc = cb_tgt->munmap_callback(cb_tgt, tsk, addr, length);
+ if (rc != 0) {
+ _stp_error("munmap callback for %d failed: %d",
+ (int)tsk->pid, rc);
+ }
+ }
+}
+
static inline void
-__stp_call_vm_callbacks(struct stap_task_finder_target *tgt,
- struct task_struct *tsk, int map_p, char *vm_path,
- unsigned long vm_start, unsigned long vm_end,
- unsigned long vm_pgoff)
+__stp_call_mprotect_callbacks(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk, unsigned long addr,
+ unsigned long length, int prot)
{
struct list_head *cb_node;
int rc;
@@ -565,13 +643,13 @@ __stp_call_vm_callbacks(struct stap_task_finder_target *tgt,
cb_tgt = list_entry(cb_node, struct stap_task_finder_target,
callback_list);
- if (cb_tgt == NULL || cb_tgt->vm_callback == NULL)
+ if (cb_tgt == NULL || cb_tgt->mprotect_callback == NULL)
continue;
- rc = cb_tgt->vm_callback(cb_tgt, tsk, map_p, vm_path,
- vm_start, vm_end, vm_pgoff);
+ rc = cb_tgt->mprotect_callback(cb_tgt, tsk, addr, length,
+ prot);
if (rc != 0) {
- _stp_error("vm callback for %d failed: %d",
+ _stp_error("mprotect callback for %d failed: %d",
(int)tsk->pid, rc);
}
}
@@ -898,16 +976,16 @@ __stp_utrace_task_finder_target_quiesce(enum utrace_resume_action action,
__stp_call_callbacks(tgt, tsk, 1, (tsk->pid == tsk->tgid));
/* If this is just a thread other than the thread group leader,
- don't bother inform vm_callback clients about its memory map,
+ don't bother inform map callback clients about its memory map,
since they will simply duplicate each other. */
- if (tgt->vm_events == 1 && tsk->tgid == tsk->pid) {
+ if (tgt->mmap_events == 1 && tsk->tgid == tsk->pid) {
struct mm_struct *mm;
char *mmpath_buf;
char *mmpath;
struct vm_area_struct *vma;
int rc;
- /* Call the vm_callback for every vma associated with
+ /* Call the mmap_callback for every vma associated with
* a file. */
mm = get_task_mm(tsk);
if (! mm)
@@ -934,12 +1012,13 @@ __stp_utrace_task_finder_target_quiesce(enum utrace_resume_action action,
mmpath_buf, PATH_MAX);
#endif
if (mmpath) {
- __stp_call_vm_callbacks(tgt, tsk, 1,
- mmpath,
- vma->vm_start,
- vma->vm_end,
- (vma->vm_pgoff
- << PAGE_SHIFT));
+ __stp_call_mmap_callbacks(tgt, tsk,
+ mmpath,
+ vma->vm_start,
+ vma->vm_end - vma->vm_start,
+ (vma->vm_pgoff
+ << PAGE_SHIFT),
+ vma->vm_flags);
}
else {
_stp_dbug(__FUNCTION__, __LINE__,
@@ -974,112 +1053,6 @@ __stp_find_file_based_vma(struct mm_struct *mm, unsigned long addr)
#ifdef UTRACE_ORIG_VERSION
static u32
-__stp_utrace_task_finder_target_syscall_entry(struct utrace_attached_engine *engine,
- struct task_struct *tsk,
- struct pt_regs *regs)
-#else
-static u32
-__stp_utrace_task_finder_target_syscall_entry(enum utrace_resume_action action,
- struct utrace_attached_engine *engine,
- struct task_struct *tsk,
- struct pt_regs *regs)
-#endif
-{
- struct stap_task_finder_target *tgt = engine->data;
- unsigned long syscall_no;
- struct mm_struct *mm;
- struct vm_area_struct *vma;
- unsigned long *arg0_addr, arg0;
- int rc;
-#if defined(__ia64__)
- struct { unsigned long *unwaddr; } _c = {.unwaddr = NULL}, *c = &_c;
-#endif
-
- if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) {
- debug_task_finder_detach();
- return UTRACE_DETACH;
- }
-
- if (tgt == NULL || tgt->vm_events == 0)
- return UTRACE_RESUME;
-
- // See if syscall is one we're interested in.
- //
- // FIXME: do we need to handle mremap()?
- syscall_no = __stp_user_syscall_nr(regs);
- if (syscall_no != MMAP_SYSCALL_NO(tsk)
- && syscall_no != MMAP2_SYSCALL_NO(tsk)
- && syscall_no != MPROTECT_SYSCALL_NO(tsk)
- && syscall_no != MUNMAP_SYSCALL_NO(tsk))
- return UTRACE_RESUME;
-
- __stp_tf_handler_start();
-
- // We need the first syscall argument to see what address
- // we're operating on.
- arg0_addr = __stp_user_syscall_arg(tsk, regs, 0);
- if ((rc = __stp_get_user(arg0, arg0_addr)) != 0) {
- _stp_error("couldn't read syscall arg 0 for pid %d: %d",
- tsk->pid, rc);
- }
- else if (arg0 != (unsigned long)NULL) {
- mm = get_task_mm(tsk);
- if (mm) {
- down_read(&mm->mmap_sem);
-
- // If we can find a matching vma associated
- // with a file, save off its details.
- vma = __stp_find_file_based_vma(mm, arg0);
- if (vma != NULL) {
- __stp_tf_add_vma(tsk, arg0, vma);
- }
-
- up_read(&mm->mmap_sem);
- mmput(mm);
- }
- }
- __stp_tf_handler_end();
- return UTRACE_RESUME;
-}
-
-static void
-__stp_call_vm_callbacks_with_vma(struct stap_task_finder_target *tgt,
- struct task_struct *tsk,
- struct vm_area_struct *vma)
-{
- char *mmpath_buf;
- char *mmpath;
- int rc;
-
- // Allocate space for a path
- mmpath_buf = _stp_kmalloc(PATH_MAX);
- if (mmpath_buf == NULL) {
- _stp_error("Unable to allocate space for path");
- return;
- }
-
- // Grab the path associated with this vma.
-#ifdef STAPCONF_DPATH_PATH
- mmpath = d_path(&(vma->vm_file->f_path), mmpath_buf, PATH_MAX);
-#else
- mmpath = d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt,
- mmpath_buf, PATH_MAX);
-#endif
- if (mmpath == NULL || IS_ERR(mmpath)) {
- rc = -PTR_ERR(mmpath);
- _stp_error("Unable to get path (error %d) for pid %d",
- rc, (int)tsk->pid);
- }
- else {
- __stp_call_vm_callbacks(tgt, tsk, 1, mmpath,
- vma->vm_start, vma->vm_end,
- (vma->vm_pgoff << PAGE_SHIFT));
- }
- _stp_kfree(mmpath_buf);
-}
-
-#ifdef UTRACE_ORIG_VERSION
-static u32
__stp_utrace_task_finder_target_syscall_exit(struct utrace_attached_engine *engine,
struct task_struct *tsk,
struct pt_regs *regs)
@@ -1092,13 +1065,12 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
#endif
{
struct stap_task_finder_target *tgt = engine->data;
- unsigned long syscall_no;
- unsigned long *rv_addr, rv;
- unsigned long *arg0_addr, arg0;
+ long syscall_no;
+ unsigned long rv;
+ unsigned long args[3];
int rc;
struct mm_struct *mm;
struct vm_area_struct *vma;
- struct __stp_tf_vma_entry *entry = NULL;
#if defined(__ia64__)
struct { unsigned long *unwaddr; } _c = {.unwaddr = NULL}, *c = &_c;
#endif
@@ -1108,35 +1080,35 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
return UTRACE_DETACH;
}
- if (tgt == NULL || tgt->vm_events == 0)
+ if (tgt == NULL)
return UTRACE_RESUME;
// See if syscall is one we're interested in.
//
// FIXME: do we need to handle mremap()?
- syscall_no = __stp_user_syscall_nr(regs);
+ syscall_no = syscall_get_nr(tsk, regs);
if (syscall_no != MMAP_SYSCALL_NO(tsk)
&& syscall_no != MMAP2_SYSCALL_NO(tsk)
&& syscall_no != MPROTECT_SYSCALL_NO(tsk)
&& syscall_no != MUNMAP_SYSCALL_NO(tsk))
return UTRACE_RESUME;
- // Get return value
- rv_addr = __stp_user_syscall_return_value(tsk, regs);
- if ((rc = __stp_get_user(rv, rv_addr)) != 0) {
- _stp_error("couldn't read syscall return value for pid %d: %d",
- tsk->pid, rc);
+ // The syscall is one we're interested in, but do we have a
+ // handler for it?
+ if (((syscall_no == MMAP_SYSCALL_NO(tsk)
+ || syscall_no == MMAP2_SYSCALL_NO(tsk)) && tgt->mmap_events == 0)
+ || (syscall_no == MPROTECT_SYSCALL_NO(tsk)
+ && tgt->mprotect_events == 0)
+ || (syscall_no == MUNMAP_SYSCALL_NO(tsk)
+ && tgt->munmap_events == 0))
return UTRACE_RESUME;
- }
+
+ // Get return value
+ rv = syscall_get_return_value(tsk, regs);
// We need the first syscall argument to see what address we
// were operating on.
- arg0_addr = __stp_user_syscall_arg(tsk, regs, 0);
- if ((rc = __stp_get_user(arg0, arg0_addr)) != 0) {
- _stp_error("couldn't read syscall arg 0 for pid %d: %d",
- tsk->pid, rc);
- return UTRACE_RESUME;
- }
+ syscall_get_arguments(tsk, regs, 0, 1, args);
#ifdef DEBUG_TASK_FINDER_VMA
_stp_dbug(__FUNCTION__, __LINE__,
@@ -1147,109 +1119,45 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
: ((syscall_no == MPROTECT_SYSCALL_NO(tsk)) ? "mprotect"
: ((syscall_no == MUNMAP_SYSCALL_NO(tsk)) ? "munmap"
: "UNKNOWN")))),
- arg0, rv);
+ args[0], rv);
#endif
__stp_tf_handler_start();
- // Try to find the vma info we might have saved.
- if (arg0 != (unsigned long)NULL)
- entry = __stp_tf_get_vma_entry(tsk, arg0);
+ if (syscall_no == MUNMAP_SYSCALL_NO(tsk)) {
+ // We need the 2nd syscall argument for the length.
+ syscall_get_arguments(tsk, regs, 1, 1, &args[1]);
+ // Call the callbacks
+ __stp_call_munmap_callbacks(tgt, tsk, args[0], args[1]);
+ }
+ else if (syscall_no == MMAP_SYSCALL_NO(tsk)
+ || syscall_no == MMAP2_SYSCALL_NO(tsk)) {
- // If entry is NULL, this means we didn't find a file based
- // vma to store in the syscall_entry routine. This could mean
- // we just created a new vma.
- if (entry == NULL) {
mm = get_task_mm(tsk);
if (mm) {
down_read(&mm->mmap_sem);
vma = __stp_find_file_based_vma(mm, rv);
- if (vma != NULL) {
- __stp_call_vm_callbacks_with_vma(tgt, tsk, vma);
- }
- up_read(&mm->mmap_sem);
- mmput(mm);
- }
- }
- // If we found saved vma information, try to match it up with
- // what currently exists.
- else {
-#ifdef DEBUG_TASK_FINDER_VMA
- _stp_dbug(__FUNCTION__, __LINE__,
- "** found stored vma 0x%lx/0x%lx/0x%lx!\n",
- entry->vm_start, entry->vm_end, entry->vm_pgoff);
-#endif
- mm = get_task_mm(tsk);
- if (mm) {
- down_read(&mm->mmap_sem);
- vma = __stp_find_file_based_vma(mm, entry->vm_start);
-
- // We couldn't find the vma at all. The
- // original vma was deleted.
- if (vma == NULL) {
- // FIXME: We'll need to figure out to
- // retrieve the path of a deleted
- // vma.
-
- __stp_call_vm_callbacks(tgt, tsk, 0, NULL,
- entry->vm_start,
- entry->vm_end,
- (entry->vm_pgoff
- << PAGE_SHIFT));
- }
- // If nothing has changed, there is no
- // need to call the callback.
- else if (vma->vm_start == entry->vm_start
- && vma->vm_end == entry->vm_end
- && vma->vm_pgoff == entry->vm_pgoff) {
- // do nothing
+ // Call the callbacks
+ if (vma) {
+ __stp_call_mmap_callbacks_with_vma(tgt, tsk,
+ vma);
}
- // The original vma has been changed. It is
- // possible that calling mprotect (e.g.) split
- // up an existing vma into 2 or 3 new vma's
- // (assuming it protected a portion of the
- // original vma at the beginning, middle, or
- // end). Try to determine what happened.
- else {
- unsigned long tmp;
-
- // First report that the original vma
- // is gone.
- //
- // FIXME: We'll need to figure out to
- // retrieve the path of a deleted
- // vma.
- __stp_call_vm_callbacks(tgt, tsk, 0, NULL,
- entry->vm_start,
- entry->vm_end,
- (entry->vm_pgoff
- << PAGE_SHIFT));
-
- // Now find all the new vma's that
- // made up the original vma's address
- // space and call the callback on each
- // new vma.
- tmp = entry->vm_start;
- while (((vma = __stp_find_file_based_vma(mm,
- tmp))
- != NULL)
- && vma->vm_end <= entry->vm_end) {
- __stp_call_vm_callbacks_with_vma(tgt,
- tsk,
- vma);
- if (vma->vm_end >= entry->vm_end)
- break;
- tmp = vma->vm_end;
- }
- }
up_read(&mm->mmap_sem);
mmput(mm);
}
+ }
+ else {
+ // We need the 2nd syscall argument for the length and
+ // the 3rd argument for the protection.
+ syscall_get_arguments(tsk, regs, 1, 2, &args[1]);
- // Cleanup by deleting the saved vma info.
- __stp_tf_remove_vma_entry(entry);
+ // Call the callbacks
+ __stp_call_mprotect_callbacks(tgt, tsk, args[0], args[1],
+ args[2]);
}
+
+syscall_exit_done:
__stp_tf_handler_end();
return UTRACE_RESUME;
}
@@ -1274,8 +1182,6 @@ stap_start_task_finder(void)
return ENOMEM;
}
- __stp_tf_vma_initialize();
-
atomic_set(&__stp_task_finder_state, __STP_TF_RUNNING);
rcu_read_lock();
@@ -1391,5 +1297,5 @@ stap_stop_task_finder(void)
debug_task_finder_report();
}
-
+#endif /* defined(CONFIG_UTRACE) */
#endif /* TASK_FINDER_C */
diff --git a/runtime/task_finder_vma.c b/runtime/task_finder_vma.c
index 83b206e5..ed9c6f4f 100644
--- a/runtime/task_finder_vma.c
+++ b/runtime/task_finder_vma.c
@@ -1,13 +1,19 @@
#include <linux/list.h>
#include <linux/jhash.h>
-#include <linux/mutex.h>
+#include <linux/spinlock.h>
// When handling memcpy() syscall tracing to notice memory map
// changes, we need to cache memcpy() entry parameter values for
// processing at memcpy() exit.
-// __stp_tf_vma_mutex protects the hash table.
-static DEFINE_MUTEX(__stp_tf_vma_mutex);
+// __stp_tf_vma_lock protects the hash table.
+// Documentation/spinlocks.txt suggest we can be a bit more clever
+// if we guarantee that in interrupt context we only read, not write
+// the datastructures. We should never change the hash table or the
+// contents in interrupt context (which should only ever call
+// stap_find_vma_map_info for getting stored vma info). So we might
+// want to look into that if this seems a bottleneck.
+static DEFINE_RWLOCK(__stp_tf_vma_lock);
#define __STP_TF_HASH_BITS 4
#define __STP_TF_TABLE_SIZE (1 << __STP_TF_HASH_BITS)
@@ -26,8 +32,8 @@ struct __stp_tf_vma_entry {
unsigned long vm_pgoff;
// Is that enough? Should we store a dcookie for vm_file?
- // Module that this vma entry is mapped from, if any.
- struct _stp_module *module;
+ // User data (possibly stp_module)
+ void *user;
};
static struct __stp_tf_vma_entry
@@ -40,23 +46,24 @@ static struct hlist_head __stp_tf_vma_table[__STP_TF_TABLE_SIZE];
static struct hlist_head __stp_tf_vma_map[__STP_TF_TABLE_SIZE];
// __stp_tf_vma_initialize(): Initialize the free list. Grabs the
-// mutex.
+// spinlock.
static void
__stp_tf_vma_initialize(void)
{
int i;
struct hlist_head *head = &__stp_tf_vma_free_list[0];
- mutex_lock(&__stp_tf_vma_mutex);
+ unsigned long flags;
+ write_lock_irqsave(&__stp_tf_vma_lock, flags);
for (i = 0; i < TASK_FINDER_VMA_ENTRY_ITEMS; i++) {
hlist_add_head(&__stp_tf_vma_free_list_items[i].hlist, head);
}
- mutex_unlock(&__stp_tf_vma_mutex);
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
}
// __stp_tf_vma_get_free_entry(): Returns an entry from the free list
-// or NULL. The __stp_tf_vma_mutex must be locked before calling this
+// or NULL. The __stp_tf_vma_lock must be write locked before calling this
// function.
static struct __stp_tf_vma_entry *
__stp_tf_vma_get_free_entry(void)
@@ -77,7 +84,7 @@ __stp_tf_vma_get_free_entry(void)
// __stp_tf_vma_put_free_entry(): Puts an entry back on the free
-// list. The __stp_tf_vma_mutex must be locked before calling this
+// list. The __stp_tf_vma_lock must be write locked before calling this
// function.
static void
__stp_tf_vma_put_free_entry(struct __stp_tf_vma_entry *entry)
@@ -101,7 +108,7 @@ __stp_tf_vma_hash(struct task_struct *tsk, unsigned long addr)
// Get vma_entry if the vma is present in the vma hash table.
-// Returns NULL if not present.
+// Returns NULL if not present. Takes a read lock on __stp_tf_vma_lock.
static struct __stp_tf_vma_entry *
__stp_tf_get_vma_entry(struct task_struct *tsk, unsigned long addr)
{
@@ -109,20 +116,22 @@ __stp_tf_get_vma_entry(struct task_struct *tsk, unsigned long addr)
struct hlist_node *node;
struct __stp_tf_vma_entry *entry;
- mutex_lock(&__stp_tf_vma_mutex);
+ unsigned long flags;
+ read_lock_irqsave(&__stp_tf_vma_lock, flags);
head = &__stp_tf_vma_table[__stp_tf_vma_hash(tsk, addr)];
hlist_for_each_entry(entry, node, head, hlist) {
if (tsk->pid == entry->pid
&& addr == entry->addr) {
- mutex_unlock(&__stp_tf_vma_mutex);
+ read_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return entry;
}
}
- mutex_unlock(&__stp_tf_vma_mutex);
+ read_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return NULL;
}
// Add the vma info to the vma hash table.
+// Takes a write lock on __stp_tf_vma_lock.
static int
__stp_tf_add_vma(struct task_struct *tsk, unsigned long addr,
struct vm_area_struct *vma)
@@ -131,7 +140,8 @@ __stp_tf_add_vma(struct task_struct *tsk, unsigned long addr,
struct hlist_node *node;
struct __stp_tf_vma_entry *entry;
- mutex_lock(&__stp_tf_vma_mutex);
+ unsigned long flags;
+ write_lock_irqsave(&__stp_tf_vma_lock, flags);
head = &__stp_tf_vma_table[__stp_tf_vma_hash(tsk, addr)];
hlist_for_each_entry(entry, node, head, hlist) {
if (tsk->pid == entry->pid
@@ -141,7 +151,7 @@ __stp_tf_add_vma(struct task_struct *tsk, unsigned long addr,
"vma (pid: %d, vm_start: 0x%lx) present?\n",
tsk->pid, vma->vm_start);
#endif
- mutex_unlock(&__stp_tf_vma_mutex);
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return -EBUSY; /* Already there */
}
}
@@ -149,7 +159,7 @@ __stp_tf_add_vma(struct task_struct *tsk, unsigned long addr,
// Get an element from the free list.
entry = __stp_tf_vma_get_free_entry();
if (!entry) {
- mutex_unlock(&__stp_tf_vma_mutex);
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return -ENOMEM;
}
entry->pid = tsk->pid;
@@ -158,11 +168,12 @@ __stp_tf_add_vma(struct task_struct *tsk, unsigned long addr,
entry->vm_end = vma->vm_end;
entry->vm_pgoff = vma->vm_pgoff;
hlist_add_head(&entry->hlist, head);
- mutex_unlock(&__stp_tf_vma_mutex);
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return 0;
}
// Remove the vma entry from the vma hash table.
+// Takes a write lock on __stp_tf_vma_lock.
static int
__stp_tf_remove_vma_entry(struct __stp_tf_vma_entry *entry)
{
@@ -171,10 +182,11 @@ __stp_tf_remove_vma_entry(struct __stp_tf_vma_entry *entry)
int found = 0;
if (entry != NULL) {
- mutex_lock(&__stp_tf_vma_mutex);
+ unsigned long flags;
+ write_lock_irqsave(&__stp_tf_vma_lock, flags);
hlist_del(&entry->hlist);
__stp_tf_vma_put_free_entry(entry);
- mutex_unlock(&__stp_tf_vma_mutex);
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
}
return 0;
}
@@ -189,7 +201,7 @@ __stp_tf_vma_map_hash(struct task_struct *tsk)
}
// Get vma_entry if the vma is present in the vma map hash table.
-// Returns NULL if not present. The __stp_tf_vma_mutex must be locked
+// Returns NULL if not present. The __stp_tf_vma_lock must be read locked
// before calling this function.
static struct __stp_tf_vma_entry *
__stp_tf_get_vma_map_entry_internal(struct task_struct *tsk,
@@ -214,13 +226,16 @@ __stp_tf_get_vma_map_entry_internal(struct task_struct *tsk,
static int
stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start,
unsigned long vm_end, unsigned long vm_pgoff,
- struct _stp_module *module)
+ void *user)
{
struct hlist_head *head;
struct hlist_node *node;
struct __stp_tf_vma_entry *entry;
- mutex_lock(&__stp_tf_vma_mutex);
+ unsigned long flags;
+ // Take a write lock, since we are most likely going to write
+ // after reading.
+ write_lock_irqsave(&__stp_tf_vma_lock, flags);
entry = __stp_tf_get_vma_map_entry_internal(tsk, vm_start);
if (entry != NULL) {
#if 0
@@ -228,14 +243,14 @@ stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start,
"vma (pid: %d, vm_start: 0x%lx) present?\n",
tsk->pid, entry->vm_start);
#endif
- mutex_unlock(&__stp_tf_vma_mutex);
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return -EBUSY; /* Already there */
}
// Get an element from the free list.
entry = __stp_tf_vma_get_free_entry();
if (!entry) {
- mutex_unlock(&__stp_tf_vma_mutex);
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return -ENOMEM;
}
@@ -245,11 +260,11 @@ stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start,
entry->vm_start = vm_start;
entry->vm_end = vm_end;
entry->vm_pgoff = vm_pgoff;
- entry->module = module;
+ entry->user = user;
head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)];
hlist_add_head(&entry->hlist, head);
- mutex_unlock(&__stp_tf_vma_mutex);
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return 0;
}
@@ -263,23 +278,26 @@ stap_remove_vma_map_info(struct task_struct *tsk, unsigned long vm_start,
struct hlist_node *node;
struct __stp_tf_vma_entry *entry;
- mutex_lock(&__stp_tf_vma_mutex);
+ // Take a write lock since we are most likely going to delete
+ // after reading.
+ unsigned long flags;
+ write_lock_irqsave(&__stp_tf_vma_lock, flags);
entry = __stp_tf_get_vma_map_entry_internal(tsk, vm_start);
if (entry != NULL) {
hlist_del(&entry->hlist);
__stp_tf_vma_put_free_entry(entry);
}
- mutex_unlock(&__stp_tf_vma_mutex);
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return 0;
}
// Finds vma info if the vma is present in the vma map hash table.
-// Returns ESRCH if not present. The __stp_tf_vma_mutex must *not* be
+// Returns ESRCH if not present. The __stp_tf_vma_lock must *not* be
// locked before calling this function.
static int
stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr,
unsigned long *vm_start, unsigned long *vm_end,
- unsigned long *vm_pgoff)
+ unsigned long *vm_pgoff, void **user)
{
struct hlist_head *head;
struct hlist_node *node;
@@ -287,7 +305,8 @@ stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr,
struct __stp_tf_vma_entry *found_entry = NULL;
int rc = ESRCH;
- mutex_lock(&__stp_tf_vma_mutex);
+ unsigned long flags;
+ read_lock_irqsave(&__stp_tf_vma_lock, flags);
head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)];
hlist_for_each_entry(entry, node, head, hlist) {
if (tsk->pid == entry->pid
@@ -304,31 +323,10 @@ stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr,
*vm_end = found_entry->vm_end;
if (vm_pgoff != NULL)
*vm_pgoff = found_entry->vm_pgoff;
+ if (user != NULL)
+ *user = found_entry->user;
rc = 0;
}
- mutex_unlock(&__stp_tf_vma_mutex);
+ read_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return rc;
}
-
-// Get vma_entry of the address (vm_start/vm_end) if the vma is
-// present in the vma hash table containing.
-// Returns NULL if not present.
-static struct __stp_tf_vma_entry *
-__stp_tf_get_vma_entry_addr(struct task_struct *tsk, unsigned long addr)
-{
- struct hlist_head *head;
- struct hlist_node *node;
- struct __stp_tf_vma_entry *entry;
-
- mutex_lock(&__stp_tf_vma_mutex);
- head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)];
- hlist_for_each_entry(entry, node, head, hlist) {
- if (tsk->pid == entry->pid
- && addr >= entry->vm_start && addr < entry->vm_end) {
- mutex_unlock(&__stp_tf_vma_mutex);
- return entry;
- }
- }
- mutex_unlock(&__stp_tf_vma_mutex);
- return NULL;
-}
diff --git a/runtime/unwind.c b/runtime/unwind.c
index 9c704e28..f7b19def 100644
--- a/runtime/unwind.c
+++ b/runtime/unwind.c
@@ -581,7 +581,7 @@ static int unwind(struct unwind_frame_info *frame)
if (UNW_PC(frame) == 0)
return -EINVAL;
- m = _stp_mod_sec_lookup (pc, &s);
+ m = _stp_mod_sec_lookup (pc, current, &s);
if (unlikely(m == NULL)) {
dbug_unwind(1, "No module found for pc=%lx", pc);
return -EINVAL;
diff --git a/runtime/uprobes/.gitignore b/runtime/uprobes/.gitignore
new file mode 100644
index 00000000..c8172c41
--- /dev/null
+++ b/runtime/uprobes/.gitignore
@@ -0,0 +1,7 @@
+/*.o
+/*.cmd
+/.tmp_versions
+/Module.*
+/modules.order
+/uprobes.ko
+/uprobes.mod.c