summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/ChangeLog5
-rw-r--r--runtime/loc2c-runtime.h44
-rw-r--r--testsuite/ChangeLog5
-rw-r--r--testsuite/systemtap.base/deref.stp143
4 files changed, 119 insertions, 78 deletions
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index bee42c6d..30a64d62 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,8 @@
+2007-01-22 Josh Stone <joshua.i.stone@intel.com>
+
+ * loc2c-runtime.h (kread, kwrite): Tweaks to work better with
+ reading and writing pointer values.
+
2007-01-22 Martin Hunt <hunt@redhat.com>
* map-gen.c (_stp_map_exists): New. Check for membership only.
diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h
index 4617f697..ce6d04b7 100644
--- a/runtime/loc2c-runtime.h
+++ b/runtime/loc2c-runtime.h
@@ -468,27 +468,25 @@
/* x86 can't do 8-byte put/get_user_asm, so we have to split it */
#define kread(ptr) \
- ({ \
- typeof(*(ptr)) _r; \
- if (sizeof(*(ptr)) == 8) { \
- union { u64 q; u32 l[2]; } _q; \
- _q.l[0] = (u32) deref(4, &((u32 *)(ptr))[0]); \
- _q.l[1] = (u32) deref(4, &((u32 *)(ptr))[1]); \
- _r = (typeof(*(ptr))) _q.q; \
- } else \
- _r = (typeof(*(ptr))) deref(sizeof(*(ptr)), (ptr)); \
- _r; \
+ ({ \
+ union { typeof(*(ptr)) v; u32 l[2]; } _kr; \
+ if (sizeof(*(ptr)) == 8) { \
+ _kr.l[0] = (u32) deref(4, &((u32 *)(ptr))[0]); \
+ _kr.l[1] = (u32) deref(4, &((u32 *)(ptr))[1]); \
+ } else \
+ _kr.v = (typeof(*(ptr))) deref(sizeof(*(ptr)), (ptr)); \
+ _kr.v; \
})
-#define kwrite(ptr, value) \
- ({ \
- if (sizeof(*(ptr)) == 8) { \
- union { u64 q; u32 l[2]; } _q; \
- _q.q = (u64)(typeof(*(ptr)))(value); \
- store_deref(4, &((u32 *)(ptr))[0], _q.l[0]); \
- store_deref(4, &((u32 *)(ptr))[1], _q.l[1]); \
- } else \
- store_deref(sizeof(*(ptr)), (ptr), (typeof(*(ptr)))(value)); \
+#define kwrite(ptr, value) \
+ ({ \
+ if (sizeof(*(ptr)) == 8) { \
+ union { typeof(*(ptr)) v; u32 l[2]; } _kw; \
+ _kw.v = (typeof(*(ptr)))(value); \
+ store_deref(4, &((u32 *)(ptr))[0], _kw.l[0]); \
+ store_deref(4, &((u32 *)(ptr))[1], _kw.l[1]); \
+ } else \
+ store_deref(sizeof(*(ptr)), (ptr), (long)(typeof(*(ptr)))(value)); \
})
#else
@@ -496,6 +494,12 @@
#define kread(ptr) \
( (typeof(*(ptr))) deref(sizeof(*(ptr)), (ptr)) )
#define kwrite(ptr, value) \
- ( store_deref(sizeof(*(ptr)), (ptr), (typeof(*(ptr)))(value)) )
+ ( store_deref(sizeof(*(ptr)), (ptr), (long)(typeof(*(ptr)))(value)) )
#endif
+
+#define CATCH_DEREF_FAULT() \
+ if (0) { \
+deref_fault: \
+ CONTEXT->last_error = "pointer dereference fault"; \
+ }
diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog
index b26c4132..e34d66f2 100644
--- a/testsuite/ChangeLog
+++ b/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2007-01-22 Josh Stone <joshua.i.stone@intel.com>
+
+ * systemtap.base/deref.stp: Rewrite test, and now also check the ability
+ to read/write pointers.
+
2007-01-22 Frank Ch. Eigler <fche@redhat.com>
* config/unix.exp: New file as a master load_lib repository.
diff --git a/testsuite/systemtap.base/deref.stp b/testsuite/systemtap.base/deref.stp
index d17fcac8..d2399589 100644
--- a/testsuite/systemtap.base/deref.stp
+++ b/testsuite/systemtap.base/deref.stp
@@ -7,69 +7,96 @@
probe begin { log("systemtap starting probe") }
probe end { log("systemtap ending probe") }
+probe end(1) {
+ log_test("kread u8", kread_u8())
+ log_test("kread u16", kread_u16())
+ log_test("kread u32", kread_u32())
+ log_test("kread u64", kread_u64())
+ log_test("kread ptr", kread_ptr())
+
+ log_test("kwrite u8", kwrite_u8())
+ log_test("kwrite u16", kwrite_u16())
+ log_test("kwrite u32", kwrite_u32())
+ log_test("kwrite u64", kwrite_u64())
+ log_test("kwrite ptr", kwrite_ptr())
+}
+
+function log_test(test:string, result:long) {
+ if (result)
+ log("systemtap test success")
+ else
+ printf("systemtap test failure - %s\n", test)
+}
-function call_kread:long(val:long) %{
- if ((uint64_t)THIS->val < 0x100ULL) {
- uint8_t local8 = (uint8_t)THIS->val;
- THIS->__retvalue = kread(&local8);
- } else if ((uint64_t)THIS->val < 0x10000ULL) {
- uint16_t local16 = (uint16_t)THIS->val;
- THIS->__retvalue = kread(&local16);
- } else if ((uint64_t)THIS->val < 0x100000000ULL) {
- uint32_t local32 = (uint32_t)THIS->val;
- THIS->__retvalue = kread(&local32);
- } else {
- uint64_t local64 = (uint64_t)THIS->val;
- THIS->__retvalue = kread(&local64);
- }
- if (0) {
-deref_fault:
- CONTEXT->last_error = "pointer dereference error";
- }
+function kread_u8:long() %{
+ uint8_t local = 0x42;
+ THIS->__retvalue = (local == kread(&local));
+ CATCH_DEREF_FAULT();
%}
-function call_kwrite:long(val:long) %{
- if ((uint64_t)THIS->val < 0x100ULL) {
- uint8_t local8;
- kwrite(&local8, THIS->val);
- THIS->__retvalue = local8;
- } else if ((uint64_t)THIS->val < 0x10000ULL) {
- uint16_t local16;
- kwrite(&local16, THIS->val);
- THIS->__retvalue = local16;
- } else if ((uint64_t)THIS->val < 0x100000000ULL) {
- uint32_t local32;
- kwrite(&local32, THIS->val);
- THIS->__retvalue = local32;
- } else {
- uint64_t local64;
- kwrite(&local64, THIS->val);
- THIS->__retvalue = local64;
- }
- if (0) {
-deref_fault:
- CONTEXT->last_error = "pointer dereference error";
- }
+function kread_u16:long() %{
+ uint16_t local = 0xBEEF;
+ THIS->__retvalue = (local == kread(&local));
+ CATCH_DEREF_FAULT();
%}
-function check_deref(val) {
- deref = call_kread(val)
- if (deref == val)
- log("systemtap test success")
- else
- printf("systemtap test failure - kread %#x != %#x\n", deref, val)
+function kread_u32:long() %{
+ uint32_t local = 0xDEADBEEF;
+ THIS->__retvalue = (local == kread(&local));
+ CATCH_DEREF_FAULT();
+%}
- deref = call_kwrite(val)
- if (deref == val)
- log("systemtap test success")
- else
- printf("systemtap test failure - kwrite %#x != %#x\n", deref, val)
-}
+function kread_u64:long() %{
+ uint64_t local = 0xDEADBEEFBAADF00DLL;
+ THIS->__retvalue = (local == kread(&local));
+ CATCH_DEREF_FAULT();
+%}
-probe end(1) {
- check_deref(0xDEADBEEFBAADF00D)
- check_deref(0xDEADBEEF)
- check_deref(0xBEEF)
- check_deref(0x42)
-}
+function kread_ptr:long() %{
+ struct task_struct *local = current;
+ THIS->__retvalue = (local == kread(&local));
+ CATCH_DEREF_FAULT();
+%}
+
+// NB: kwrite uses system macros with inline asm, with this comment:
+//
+// Tell gcc we read from memory instead of writing: this is because we do not
+// write to any memory gcc knows about, so there are no aliasing issues.
+//
+// In this test I'm writing to memory that gcc *does* know about, thus we need
+// the memory marked volatile to force gcc to re-read it.
+function kwrite_u8:long() %{
+ volatile uint8_t local = 0;
+ kwrite(&local, 0x42);
+ THIS->__retvalue = (local == 0x42);
+ CATCH_DEREF_FAULT();
+%}
+
+function kwrite_u16:long() %{
+ volatile uint16_t local = 0;
+ kwrite(&local, 0xBEEF);
+ THIS->__retvalue = (local == 0xBEEF);
+ CATCH_DEREF_FAULT();
+%}
+
+function kwrite_u32:long() %{
+ volatile uint32_t local = 0;
+ kwrite(&local, 0xDEADBEEF);
+ THIS->__retvalue = (local == 0xDEADBEEF);
+ CATCH_DEREF_FAULT();
+%}
+
+function kwrite_u64:long() %{
+ volatile uint64_t local = 0;
+ kwrite(&local, 0xDEADBEEFBAADF00DLL);
+ THIS->__retvalue = (local == 0xDEADBEEFBAADF00DLL);
+ CATCH_DEREF_FAULT();
+%}
+
+function kwrite_ptr:long() %{
+ struct task_struct * volatile local = NULL;
+ kwrite(&local, current);
+ THIS->__retvalue = (local == current);
+ CATCH_DEREF_FAULT();
+%}