From 2cda5f46cba978e19590efd7fee0b3075f8eb8df Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 23 May 2008 20:35:55 -0700 Subject: Add prototypes for using the 2.6.26 probe_kernel_* functions. For now, the autoconf for the new code is disabled, because it shows poorer performance than our existing dereferencing functions. This is probably because ours get inlined and optimized. The code is being committed so that we may re-evaluate its usefulness in the future. This addresses bugzilla 6432. --- ChangeLog | 12 +++- buildrun.cxx | 6 ++ runtime/ChangeLog | 8 +++ runtime/autoconf-probe-kernel.c | 7 +++ runtime/loc2c-runtime.h | 125 +++++++++++++++++++++++++++++----------- 5 files changed, 120 insertions(+), 38 deletions(-) create mode 100644 runtime/autoconf-probe-kernel.c diff --git a/ChangeLog b/ChangeLog index 0db1ca55..cb786d0e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2008-05-27 Josh Stone + + PR 6432 + * buildrun.cxx (compile_pass): Add the autoconf test for probe_kernel_* + functions, but leave it #if-0'ed for now. + 2008-05-23 Jim Keniston PR 4311, cont. Address powerpc dwarfless test failures. @@ -6,9 +12,9 @@ that map to sys_ni_syscall. 2008-05-23 Srinivasa DS - PR 6429: Inerim fix to avoid compilation error of systemtap module - * runtime/transport/symbols.c: added definitions of struct - module_sect_attr, struct module_sect_attrs for 2.6.25 above kernels. + PR 6429: Inerim fix to avoid compilation error of systemtap module + * runtime/transport/symbols.c: added definitions of struct + module_sect_attr, struct module_sect_attrs for 2.6.25 above kernels. 2008-05-22 Wenji Huang diff --git a/buildrun.cxx b/buildrun.cxx index 76efe7c0..a39f2b63 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -96,6 +96,12 @@ compile_pass (systemtap_session& s) o << module_cflags << " += $(call stap_check_build, $(SYSTEMTAP_RUNTIME)/autoconf-nameidata.c, -DSTAPCONF_NAMEIDATA_CLEANUP,)" << endl; o << module_cflags << " += $(call stap_check_build, $(SYSTEMTAP_RUNTIME)/autoconf-unregister-kprobes.c, -DSTAPCONF_UNREGISTER_KPROBES,)" << endl; o << module_cflags << " += $(call stap_check_build, $(SYSTEMTAP_RUNTIME)/autoconf-module-nsections.c, -DSTAPCONF_MODULE_NSECTIONS,)" << endl; +#if 0 + /* NB: For now, the performance hit of probe_kernel_read/write (vs. our + * homegrown safe-access functions) is deemed undesireable, so we'll skip + * this autoconf. */ + o << module_cflags << " += $(call stap_check_build, $(SYSTEMTAP_RUNTIME)/autoconf-probe-kernel.c, -DSTAPCONF_PROBE_KERNEL,)" << endl; +#endif for (unsigned i=0; i + + PR 6432 + * loc2c-runtime.h (kread, kwrite, deref, store_deref): Add + architecture-neutral implementations, using probe_kernel_* + facilites (controlled by autoconf). + * autoconf-probe-kernel.c: test for above. + 2008-05-16 David Smith PR 6499. diff --git a/runtime/autoconf-probe-kernel.c b/runtime/autoconf-probe-kernel.c new file mode 100644 index 00000000..93fbaae6 --- /dev/null +++ b/runtime/autoconf-probe-kernel.c @@ -0,0 +1,7 @@ +#include + +void probe_kernel(void *dst, void *src, size_t size) +{ + (void)probe_kernel_read(dst, src, size); + (void)probe_kernel_write(dst, src, size); +} diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h index 66fd1e43..a7472691 100644 --- a/runtime/loc2c-runtime.h +++ b/runtime/loc2c-runtime.h @@ -9,6 +9,7 @@ * later version. */ +#include #include #define intptr_t long #define uintptr_t unsigned long @@ -31,9 +32,6 @@ << (sizeof (base) * 8 - (higherbits) - (nbits)))) -/* These operations are target-specific. */ -#include - /* Given a DWARF register number, fetch its intptr_t (long) value from the probe context, or store a new value into the probe context. @@ -173,6 +171,61 @@ #endif + +/* NB: this autoconf is always disabled, pending further performance eval. */ +#if defined STAPCONF_PROBE_KERNEL + +/* Kernel 2.6.26 adds probe_kernel_{read,write}, which lets us write + * architecture-neutral implementations of kread, kwrite, deref, and + * store_deref. + * + * NB: deref and store_deref shouldn't be used with 64-bit values on 32-bit + * platforms, because they will lose data in the conversion to intptr_t. We + * generally want to encourage using kread and kwrite instead. + */ + +#define kread(ptr) ({ \ + typeof(*(ptr)) _v; \ + if (probe_kernel_read((void *)&_v, (void *)(ptr), sizeof(*(ptr)))) \ + DEREF_FAULT(ptr); \ + _v; \ + }) + +#define kwrite(ptr, value) ({ \ + typeof(*(ptr)) _v; \ + _v = (typeof(*(ptr)))(value); \ + if (probe_kernel_write((void *)(ptr), (void *)&_v, sizeof(*(ptr)))) \ + STORE_DEREF_FAULT(ptr); \ + }) + +#define deref(size, addr) ({ \ + intptr_t _i; \ + switch (size) { \ + case 1: _i = kread((u8 *)(addr)); break; \ + case 2: _i = kread((u16 *)(addr)); break; \ + case 4: _i = kread((u32 *)(addr)); break; \ + case 8: _i = kread((u64 *)(addr)); break; \ + default: __deref_bad(); \ + /* uninitialized _i should also be caught by -Werror */ \ + } \ + _i; \ + }) + +#define store_deref(size, addr, value) ({ \ + switch (size) { \ + case 1: kwrite((u8 *)(addr), (value)); break; \ + case 2: kwrite((u16 *)(addr), (value)); break; \ + case 4: kwrite((u32 *)(addr), (value)); break; \ + case 8: kwrite((u64 *)(addr), (value)); break; \ + default: __store_deref_bad(); \ + } \ + }) + +extern void __deref_bad(void); +extern void __store_deref_bad(void); + +#else /* !STAPCONF_PROBE_KERNEL */ + #if defined __i386__ #define deref(size, addr) \ @@ -614,38 +667,6 @@ #endif /* (s390) || (s390x) */ -#define deref_string(dst, addr, maxbytes) \ - ({ \ - uintptr_t _addr; \ - size_t _len; \ - unsigned char _c; \ - char *_d = (dst); \ - for (_len = (maxbytes), _addr = (uintptr_t)(addr); \ - _len > 1 && (_c = deref (1, _addr)) != '\0'; \ - --_len, ++_addr) \ - if (_d) \ - *_d++ = _c; \ - if (_d) \ - *_d = '\0'; \ - (dst); \ - }) - -#define deref_buffer(dst, addr, numbytes) \ - ({ \ - uintptr_t _addr; \ - size_t _len; \ - unsigned char _c; \ - char *_d = (dst); \ - for (_len = (numbytes), _addr = (uintptr_t)(addr); \ - _len >= 1; \ - --_len, ++_addr) { \ - _c = deref (1, _addr); \ - if (_d) \ - *_d++ = _c; \ - } \ - (dst); \ - }) - #if defined __i386__ @@ -678,6 +699,40 @@ #endif +#endif /* STAPCONF_PROBE_KERNEL */ + +#define deref_string(dst, addr, maxbytes) \ + ({ \ + uintptr_t _addr; \ + size_t _len; \ + unsigned char _c; \ + char *_d = (dst); \ + for (_len = (maxbytes), _addr = (uintptr_t)(addr); \ + _len > 1 && (_c = deref (1, _addr)) != '\0'; \ + --_len, ++_addr) \ + if (_d) \ + *_d++ = _c; \ + if (_d) \ + *_d = '\0'; \ + (dst); \ + }) + +#define deref_buffer(dst, addr, numbytes) \ + ({ \ + uintptr_t _addr; \ + size_t _len; \ + unsigned char _c; \ + char *_d = (dst); \ + for (_len = (numbytes), _addr = (uintptr_t)(addr); \ + _len >= 1; \ + --_len, ++_addr) { \ + _c = deref (1, _addr); \ + if (_d) \ + *_d++ = _c; \ + } \ + (dst); \ + }) + #define CATCH_DEREF_FAULT() \ if (0) { \ deref_fault: ; \ -- cgit