diff options
-rw-r--r-- | runtime/ChangeLog | 5 | ||||
-rw-r--r-- | runtime/loc2c-runtime.h | 44 | ||||
-rw-r--r-- | testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | testsuite/systemtap.base/deref.stp | 143 |
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(); +%} |