]> sourceware.org Git - systemtap.git/commitdiff
PR14179: Split up loc2c-runtime.h for linux|dyninst
authorJosh Stone <jistone@redhat.com>
Thu, 4 Oct 2012 23:19:10 +0000 (16:19 -0700)
committerJosh Stone <jistone@redhat.com>
Thu, 4 Oct 2012 23:19:10 +0000 (16:19 -0700)
* runtime/loc2c-runtime.h: Remove deref functions and special register
  handling from this shared base, and rename k_dwarf_register_N to
  pt_dwarf_register_N to be more neutral.
* runtime/linux/loc2c-runtime.h: Move the deref functions and special
  register handling here.  Nothing new, just transplanted.
* runtime/dyninst/loc2c-runtime.h: Add deref and register functions.
* runtime/dyninst/copy.c (__copy_from_user, __copy_to_user): Move from
  linux_def.h, since these are custom implementations, not kernel copies.
  (_stp_strncpy_from_user, _stp_copy_from_user): New implementations.

runtime/dyninst/copy.c
runtime/dyninst/linux_defs.h
runtime/dyninst/loc2c-runtime.h
runtime/dyninst/runtime.h
runtime/linux/loc2c-runtime.h [new file with mode: 0644]
runtime/loc2c-runtime.h
testsuite/systemtap.pass1-4/buildok-dyninst.exp

index d08649093a7c54dfca673b7dd3d04011c23ff166..968dd695c81f43f96d7b8fe4944a07ed3c51e5a3 100644 (file)
 
 #include "stp_string.c"
 
-// TODO fill in this file as needed!
+
+static int _stp_mem_fd = -1;
+
+static inline __must_check long __copy_from_user(void *to,
+               const void __user * from, unsigned long n)
+{
+       int rc = 0;
+
+       /*
+        * The pread syscall is faster than lseek()/read() (since it
+        * is only one syscall). Also, if we used lseek()/read() we
+        * couldn't use a cached fd - since 2 threads might hit this
+        * code at the same time and the 2nd lseek() might finish
+        * before the 1st read()...
+        */
+       if (pread(_stp_mem_fd, to, n, (off_t)from) != n)
+               rc = -EFAULT;
+       return rc;
+}
+
+static inline __must_check long __copy_to_user(void *to, const void *from,
+                                              unsigned long n)
+{
+       int rc = 0;
+
+       /*
+        * The pwrite syscall is faster than lseek()/write() (since it
+        * is only one syscall).
+        */
+       if (pwrite(_stp_mem_fd, to, n, (off_t)from) != n)
+               rc = -EFAULT;
+       return rc;
+}
+
+static long
+_stp_strncpy_from_user(char *dst, const char *src, long count)
+{
+       long i;
+       if (count <= 0)
+               return -EINVAL;
+       for (i = 0; i < count; ++i) {
+               if (__copy_from_user(dst, src++, 1))
+                       return -EFAULT;
+               if (*dst++ == 0)
+                       return i;
+       }
+       *(dst - 1) = 0;
+       return i - 1;
+}
+
+static unsigned long _stp_copy_from_user(char *dst, const char *src, unsigned long count)
+{
+       if (count && __copy_from_user(dst, src, count) == 0)
+               return 0;
+       return count;
+}
 
 #endif /* _STAPDYN_COPY_C_ */
 
index 9fd8a3981ef982090633f5a03e32130cbe9c9e51..9aa040371079ceb61fc620f6296470724908dbd4 100644 (file)
@@ -3,9 +3,6 @@
 #ifndef _STAPDYN_LINUX_DEFS_H_
 #define _STAPDYN_LINUX_DEFS_H_
 
-#include <stddef.h>
-#include <unistd.h>
-
 #include "linux_hash.h"
 
 #define min(x, y) ({                           \
@@ -160,24 +157,8 @@ static inline size_t strlcat(char *dest, const char *src, size_t count)
        __gu_err;                                               \
 })
 
-static int _stp_mem_fd;
-
 static inline __must_check long __copy_from_user(void *to,
-               const void __user * from, unsigned long n)
-{
-       int rc = 0;
-
-       /*
-        * The pread syscall is faster than lseek()/read() (since it
-        * is only one syscall). Also, if we used lseek()/read() we
-        * couldn't use a cached fd - since 2 threads might hit this
-        * code at the same time and the 2nd lseek() might finish
-        * before the 1st read()...
-        */
-       if (pread(_stp_mem_fd, to, n, (off_t)from) != n)
-               rc = -EFAULT;
-       return rc;
-}
+               const void __user * from, unsigned long n);
 
 static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
 {
@@ -224,18 +205,7 @@ extern int __get_user_bad(void) __attribute__((noreturn));
 })
 
 static inline __must_check long __copy_to_user(void *to, const void *from,
-                                              unsigned long n)
-{
-       int rc = 0;
-
-       /*
-        * The pwrite syscall is faster than lseek()/write() (since it
-        * is only one syscall).
-        */
-       if (pwrite(_stp_mem_fd, to, n, (off_t)from) != n)
-               rc = -EFAULT;
-       return rc;
-}
+                                              unsigned long n);
 
 static inline int __put_user_fn(size_t size, const void __user *ptr, void *x)
 {
index 53532ebde01eddad39f199de8cc902a3d8774a2c..bf1704f3a5ab1ed99b482c11a95b95b0b419af02 100644 (file)
@@ -1,3 +1,15 @@
+/* target operations in the Dyninst mode
+ * Copyright (C) 2012 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
+ * Public License (GPL); either version 2, or (at your option) any
+ * later version.
+ */
+
+#ifndef _STAPDYN_LOC2C_RUNTIME_H_
+#define _STAPDYN_LOC2C_RUNTIME_H_
+
 #include "../loc2c-runtime.h"
 
 #define __get_user_asm(x, addr, err, itype, rtype, ltype, errret)      \
@@ -5,3 +17,56 @@
 
 #define __put_user_asm(x, addr, err, itype, rtype, ltype, errret)      \
        (err) = __put_user((x), (typeof(x)*)(addr))
+
+
+#define u_fetch_register(regno) \
+  pt_regs_fetch_register(c->uregs, regno)
+#define u_store_register(regno, value) \
+  pt_regs_store_register(c->uregs, regno, value)
+
+
+#define uread(ptr) ({ \
+       typeof(*(ptr)) _v = 0; \
+       if (__copy_from_user((void *)&_v, (void *)(ptr), sizeof(*(ptr)))) \
+           DEREF_FAULT(ptr); \
+       _v; \
+    })
+
+#define uwrite(ptr, value) ({ \
+       typeof(*(ptr)) _v; \
+       _v = (typeof(*(ptr)))(value); \
+       if (__copy_to_user((void *)(ptr), (void *)&_v, sizeof(*(ptr)))) \
+           STORE_DEREF_FAULT(ptr); \
+    })
+
+#define uderef(size, addr) ({ \
+    intptr_t _i = 0; \
+    switch (size) { \
+       case 1: _i = uread((u8 *)(addr)); break; \
+       case 2: _i = uread((u16 *)(addr)); break; \
+       case 4: _i = uread((u32 *)(addr)); break; \
+       case 8: _i = uread((u64 *)(addr)); break; \
+       default: __get_user_bad(); \
+    } \
+    _i; \
+  })
+
+#define store_uderef(size, addr, value) ({ \
+    switch (size) { \
+       case 1: uwrite((u8 *)(addr), (value)); break; \
+       case 2: uwrite((u16 *)(addr), (value)); break; \
+       case 4: uwrite((u32 *)(addr), (value)); break; \
+       case 8: uwrite((u64 *)(addr), (value)); break; \
+       default: __put_user_bad(); \
+    } \
+  })
+
+
+/* We still need to clean the runtime more before these can go away... */
+#define kread uread
+#define kwrite uwrite
+#define kderef uderef
+#define store_kderef store_uderef
+
+
+#endif /* _STAPDYN_LOC2C_RUNTIME_H_ */
index c9589fb06877b25e384c6a9cc0262a7fe6896c97..b42b4fdc56116bc95f1a441f777c72d12378bf6c 100644 (file)
@@ -23,6 +23,9 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <stddef.h>
+#include <unistd.h>
+
 
 #include "loc2c-runtime.h"
 #include "stapdyn.h"
@@ -126,8 +129,6 @@ static void systemtap_module_exit(void);
 
 static unsigned long stap_hash_seed; /* Init during module startup */
 
-static int _stp_mem_fd = -1;
-
 
 /*
  * For stapdyn to work in a multiprocess environment, the module must be
diff --git a/runtime/linux/loc2c-runtime.h b/runtime/linux/loc2c-runtime.h
new file mode 100644 (file)
index 0000000..1da40be
--- /dev/null
@@ -0,0 +1,890 @@
+/* target operations in the Linux kernel mode
+ * Copyright (C) 2005-2012 Red Hat Inc.
+ * Copyright (C) 2005-2007 Intel Corporation.
+ * Copyright (C) 2007 Quentin Barnes.
+ *
+ * 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
+ * Public License (GPL); either version 2, or (at your option) any
+ * later version.
+ */
+
+#ifndef _LINUX_LOC2C_RUNTIME_H_
+#define _LINUX_LOC2C_RUNTIME_H_
+
+#ifdef STAPCONF_LINUX_UACCESS_H
+#include <linux/uaccess.h>
+#else
+#include <asm/uaccess.h>
+#endif
+#include <linux/types.h>
+#define intptr_t long
+#define uintptr_t unsigned long
+
+#include "../loc2c-runtime.h"
+
+
+#ifndef STAPCONF_PAGEFAULT_DISABLE  /* before linux commit a866374a */
+#define pagefault_disable() preempt_disable()
+#define pagefault_enable() preempt_enable_no_resched()
+#endif
+
+
+#define k_fetch_register(regno) \
+  pt_regs_fetch_register(c->kregs, regno)
+#define k_store_register(regno, value) \
+  pt_regs_store_register(c->kregs, regno, value)
+
+
+/* PR 10601: user-space (user_regset) register access.
+   Needs arch specific code, only i386 and x86_64 for now.  */
+#if ((defined(STAPCONF_REGSET) || defined(STAPCONF_UTRACE_REGSET)) \
+     && (defined (__i386__) || defined (__x86_64__)))
+
+#if defined(STAPCONF_REGSET)
+#include <linux/regset.h>
+#endif
+
+#if defined(STAPCONF_UTRACE_REGSET)
+#include <linux/tracehook.h>
+/* adapt new names to old decls */
+#define user_regset_view utrace_regset_view
+#define user_regset utrace_regset
+#define task_user_regset_view utrace_native_view
+
+#else // PR13489, inodes-uprobes export kludge
+#if !defined(STAPCONF_TASK_USER_REGSET_VIEW_EXPORTED)
+// First typedef from the original decl, then #define it as a typecasted call.
+// NB: not all archs actually have the function, but the decl is universal in regset.h
+typedef typeof(&task_user_regset_view) task_user_regset_view_fn;
+/* Special macro to tolerate the kallsyms function pointer being zero. */
+#define task_user_regset_view(t) (kallsyms_task_user_regset_view ? \
+                                  (* (task_user_regset_view_fn)(kallsyms_task_user_regset_view))((t)) : \
+                                  NULL)
+#endif
+#endif
+
+struct usr_regset_lut {
+  char *name;
+  unsigned rsn;
+  unsigned pos;
+};
+
+
+/* DWARF register number -to- user_regset bank/offset mapping table.
+   The register numbers come from the processor-specific ELF documents.
+   The user-regset bank/offset values come from kernel $ARCH/include/asm/user*.h
+   or $ARCH/kernel/ptrace.c. */
+#if defined (__i386__) || defined (__x86_64__)
+static const struct usr_regset_lut url_i386[] = {
+  { "ax", NT_PRSTATUS, 6*4 },
+  { "cx", NT_PRSTATUS, 1*4 },
+  { "dx", NT_PRSTATUS, 2*4 },
+  { "bx", NT_PRSTATUS, 0*4 },
+  { "sp", NT_PRSTATUS, 15*4 },
+  { "bp", NT_PRSTATUS, 5*4 },
+  { "si", NT_PRSTATUS, 3*4 },
+  { "di", NT_PRSTATUS, 4*4 },
+  { "ip", NT_PRSTATUS, 12*4 },
+};
+#endif
+
+#if defined (__x86_64__)
+static const struct usr_regset_lut url_x86_64[] = {
+  { "rax", NT_PRSTATUS, 10*8 },
+  { "rdx", NT_PRSTATUS, 12*8 },
+  { "rcx", NT_PRSTATUS, 11*8 },
+  { "rbx", NT_PRSTATUS, 5*8 },
+  { "rsi", NT_PRSTATUS, 13*8 },
+  { "rdi", NT_PRSTATUS, 14*8 },
+  { "rbp", NT_PRSTATUS, 4*8 },
+  { "rsp", NT_PRSTATUS, 19*8 },
+  { "r8", NT_PRSTATUS, 9*8 },
+  { "r9", NT_PRSTATUS, 8*8 }, 
+  { "r10", NT_PRSTATUS, 7*8 },  
+  { "r11", NT_PRSTATUS, 6*8 }, 
+  { "r12", NT_PRSTATUS, 3*8 }, 
+  { "r13", NT_PRSTATUS, 2*8 }, 
+  { "r14", NT_PRSTATUS, 1*8 }, 
+  { "r15", NT_PRSTATUS, 0*8 }, 
+  { "rip", NT_PRSTATUS, 16*8 }, 
+  /* XXX: SSE registers %xmm0-%xmm7 */ 
+  /* XXX: SSE2 registers %xmm8-%xmm15 */
+  /* XXX: FP registers %st0-%st7 */
+  /* XXX: MMX registers %mm0-%mm7 */
+};
+#endif
+/* XXX: insert other architectures here. */
+
+
+static u32 ursl_fetch32 (const struct usr_regset_lut* lut, unsigned lutsize, int e_machine, unsigned regno)
+{
+  u32 value = ~0;
+  const struct user_regset_view *rsv = task_user_regset_view(current); 
+  unsigned rsi;
+  int rc;
+  unsigned rsn;
+  unsigned pos;
+  unsigned count;
+
+  WARN_ON (!rsv);
+  if (!rsv) goto out;
+  WARN_ON (regno >= lutsize);
+  if (regno >= lutsize) goto out;
+  if (rsv->e_machine != e_machine) goto out;
+
+  rsn = lut[regno].rsn;
+  pos = lut[regno].pos;
+  count = sizeof(value);
+
+  for (rsi=0; rsi<rsv->n; rsi++)
+    if (rsv->regsets[rsi].core_note_type == rsn)
+      {
+        const struct user_regset *rs = & rsv->regsets[rsi];
+        rc = (rs->get)(current, rs, pos, count, & value, NULL);
+        WARN_ON (rc);
+        /* success */
+        goto out;
+      }
+  WARN_ON (1); /* did not find appropriate regset! */
+  
+ out:
+  return value;
+}
+
+
+static void ursl_store32 (const struct usr_regset_lut* lut,unsigned lutsize,  int e_machine, unsigned regno, u32 value)
+{
+  const struct user_regset_view *rsv = task_user_regset_view(current); 
+  unsigned rsi;
+  int rc;
+  unsigned rsn;
+  unsigned pos;
+  unsigned count;
+
+  WARN_ON (!rsv);
+  if (!rsv) goto out;
+  WARN_ON (regno >= lutsize);
+  if (regno >= lutsize) goto out;
+  if (rsv->e_machine != e_machine) goto out;
+
+  rsn = lut[regno].rsn;
+  pos = lut[regno].pos;
+  count = sizeof(value);
+
+  for (rsi=0; rsi<rsv->n; rsi++)
+    if (rsv->regsets[rsi].core_note_type == rsn)
+      {
+        const struct user_regset *rs = & rsv->regsets[rsi];
+        rc = (rs->set)(current, rs, pos, count, & value, NULL);
+        WARN_ON (rc);
+        /* success */
+        goto out;
+      }
+  WARN_ON (1); /* did not find appropriate regset! */
+  
+ out:
+  return;
+}
+
+
+static u64 ursl_fetch64 (const struct usr_regset_lut* lut, unsigned lutsize, int e_machine, unsigned regno)
+{
+  u64 value = ~0;
+  const struct user_regset_view *rsv = task_user_regset_view(current); 
+  unsigned rsi;
+  int rc;
+  unsigned rsn;
+  unsigned pos;
+  unsigned count;
+
+  if (!rsv) goto out;
+  if (regno >= lutsize) goto out;
+  if (rsv->e_machine != e_machine) goto out;
+
+  rsn = lut[regno].rsn;
+  pos = lut[regno].pos;
+  count = sizeof(value);
+
+  for (rsi=0; rsi<rsv->n; rsi++)
+    if (rsv->regsets[rsi].core_note_type == rsn)
+      {
+        const struct user_regset *rs = & rsv->regsets[rsi];
+        rc = (rs->get)(current, rs, pos, count, & value, NULL);
+        if (rc)
+          goto out;
+        /* success */
+        return value;
+      }
+ out:
+  printk (KERN_WARNING "process %d mach %d regno %d not available for fetch.\n", current->tgid, e_machine, regno);
+  return value;
+}
+
+
+static void ursl_store64 (const struct usr_regset_lut* lut,unsigned lutsize,  int e_machine, unsigned regno, u64 value)
+{
+  const struct user_regset_view *rsv = task_user_regset_view(current); 
+  unsigned rsi;
+  int rc;
+  unsigned rsn;
+  unsigned pos;
+  unsigned count;
+
+  WARN_ON (!rsv);
+  if (!rsv) goto out;
+  WARN_ON (regno >= lutsize);
+  if (regno >= lutsize) goto out;
+  if (rsv->e_machine != e_machine) goto out;
+
+  rsn = lut[regno].rsn;
+  pos = lut[regno].pos;
+  count = sizeof(value);
+
+  for (rsi=0; rsi<rsv->n; rsi++)
+    if (rsv->regsets[rsi].core_note_type == rsn)
+      {
+        const struct user_regset *rs = & rsv->regsets[rsi];
+        rc = (rs->set)(current, rs, pos, count, & value, NULL);
+        if (rc)
+          goto out;
+        /* success */
+        return;
+      }
+  
+ out:
+  printk (KERN_WARNING "process %d mach %d regno %d not available for store.\n", current->tgid, e_machine, regno);
+  return;
+}
+
+
+#if defined (__i386__)
+
+#define u_fetch_register(regno) ursl_fetch32(url_i386, ARRAY_SIZE(url_i386), EM_386, regno)
+#define u_store_register(regno,value) ursl_store32(url_i386, ARRAY_SIZE(url_i386), EM_386, regno, value)
+
+#elif defined (__x86_64__)
+
+#define u_fetch_register(regno) (_stp_is_compat_task() ? ursl_fetch32(url_i386, ARRAY_SIZE(url_i386), EM_386, regno) : ursl_fetch64(url_x86_64, ARRAY_SIZE(url_x86_64), EM_X86_64, regno))
+#define u_store_register(regno,value)  (_stp_is_compat_task() ? ursl_store32(url_i386, ARRAY_SIZE(url_i386), EM_386, regno, value) : ursl_store64(url_x86_64, ARRAY_SIZE(url_x86_64), EM_X86_64, regno, value))
+
+#endif
+
+#else /* ! STAPCONF_REGSET */
+/* Downgrade to pt_dwarf_register access. */
+#define u_fetch_register(regno) \
+  pt_regs_fetch_register(c->uregs, regno)
+#define u_store_register(regno, value) \
+  pt_regs_store_register(c->uregs, regno, value)
+#endif
+
+
+/* The deref and store_deref macros are called to safely access addresses
+   in the probe context.  These macros are used only for kernel addresses.
+   The macros must handle bogus addresses here gracefully (as from
+   corrupted data structures, stale pointers, etc), by doing a "goto
+   deref_fault".
+
+   On most machines, the asm/uaccess.h macros __get_user_asm and
+   __put_user_asm do exactly the low-level work we need to access memory
+   with fault handling, and are not actually specific to user-address
+   access at all.  Each machine's definition of deref and deref_store here
+   must work right for kernel addresses, and can use whatever existing
+   machine-specific kernel macros are convenient.  */
+
+
+/* NB: this autoconf is always disabled, pending further performance eval. */
+#if 0 && 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 = 0; \
+        if (lookup_bad_addr((unsigned long)(ptr), sizeof (*(ptr))) ||  \
+            probe_kernel_read((void *)&_v, (void *)(ptr), sizeof(*(ptr)))) \
+          DEREF_FAULT(ptr); \
+        _v; \
+    })
+#define uread kread
+
+#define kwrite(ptr, value) ({ \
+        typeof(*(ptr)) _v; \
+        _v = (typeof(*(ptr)))(value); \
+        if (lookup_bad_addr((unsigned long)addr, sizeof (*(ptr))) ||   \
+            probe_kernel_write((void *)(ptr), (void *)&_v, sizeof(*(ptr)))) \
+          STORE_DEREF_FAULT(ptr); \
+    })
+#define uwrite kwrite
+
+#define uderef(size, addr) ({ \
+    intptr_t _i = 0; \
+    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(); \
+    } \
+    _i; \
+  })
+#define kderef uderef
+
+#define store_uderef(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(); \
+    } \
+  })
+#define store_kderef store_uderef
+
+
+extern void __deref_bad(void);
+extern void __store_deref_bad(void);
+
+#else /* !STAPCONF_PROBE_KERNEL */
+
+#if defined __i386__
+
+#define _stp_deref(size, addr, seg)                                           \
+  ({                                                                         \
+    int _bad = 0;                                                            \
+    intptr_t _v = 0;                                                         \
+    mm_segment_t _oldfs = get_fs();                                           \
+    set_fs(seg);                                                              \
+    pagefault_disable();                                                      \
+    if (lookup_bad_addr((unsigned long)addr, size))                          \
+      _bad = 1;                                                               \
+    else                                                                      \
+      switch (size)                                                           \
+        {                                                                     \
+        case 1: { u8 _b; __get_user_asm(_b,addr,_bad,"b","b","=q",1); _v = _b; } break; \
+        case 2: { u16 _w; __get_user_asm(_w,addr,_bad,"w","w","=r",1); _v = _w; } break; \
+        case 4: { u32 _l; __get_user_asm(_l,addr,_bad,"l","","=r",1); _v = _l; } break; \
+        default: _v = __get_user_bad();                                       \
+        }                                                                     \
+    pagefault_enable();                                                       \
+    set_fs(_oldfs);                                                           \
+    if (_bad)                                                                 \
+      DEREF_FAULT(addr);                                                     \
+    _v;                                                                              \
+  })
+
+#define _stp_store_deref(size, addr, value, seg)                              \
+  ({                                                                         \
+    int _bad = 0;                                                            \
+    mm_segment_t _oldfs = get_fs();                                           \
+    set_fs(seg);                                                              \
+    pagefault_disable();                                                      \
+    if (lookup_bad_addr((unsigned long)addr, size))                          \
+      _bad = 1;                                                               \
+    else                                                                      \
+      switch (size)                                                           \
+        {                                                                     \
+        case 1: __put_user_asm(((u8)(value)),addr,_bad,"b","b","iq",1); break;\
+        case 2: __put_user_asm(((u16)(value)),addr,_bad,"w","w","ir",1); break;\
+        case 4: __put_user_asm(((u32)(value)),addr,_bad,"l","k","ir",1); break;\
+        default: __put_user_bad();                                            \
+        }                                                                     \
+    pagefault_enable();                                                       \
+    set_fs(_oldfs);                                                           \
+    if (_bad)                                                                 \
+      STORE_DEREF_FAULT(addr);                                                \
+  })
+
+
+#elif defined __x86_64__
+
+#define _stp_deref(size, addr, seg)                                           \
+  ({                                                                         \
+    int _bad = 0;                                                            \
+    intptr_t _v = 0;                                                         \
+    mm_segment_t _oldfs = get_fs();                                           \
+    set_fs(seg);                                                              \
+    pagefault_disable();                                                      \
+    if (lookup_bad_addr((unsigned long)addr, size))                          \
+      _bad = 1;                                                               \
+    else                                                                      \
+      switch (size)                                                           \
+        {                                                                     \
+        case 1: { u8 _b; __get_user_asm(_b,(unsigned long)addr,_bad,"b","b","=q",1); _v = _b; } break; \
+        case 2: { u16 _w; __get_user_asm(_w,(unsigned long)addr,_bad,"w","w","=r",1); _v = _w; } break; \
+        case 4: { u32 _l; __get_user_asm(_l,(unsigned long)addr,_bad,"l","","=r",1); _v = _l; } break; \
+        case 8: { u64 _q; __get_user_asm(_q,(unsigned long)addr,_bad,"q","","=r",1); _v = _q; } break; \
+        default: _v = __get_user_bad();                                       \
+        }                                                                     \
+    pagefault_enable();                                                       \
+    set_fs(_oldfs);                                                           \
+    if (_bad)                                                                \
+      DEREF_FAULT(addr);                                                     \
+    _v;                                                                              \
+  })
+
+#define _stp_store_deref(size, addr, value, seg)                              \
+  ({                                                                         \
+    int _bad = 0;                                                            \
+    mm_segment_t _oldfs = get_fs();                                           \
+    set_fs(seg);                                                              \
+    pagefault_disable();                                                      \
+    if (lookup_bad_addr((unsigned long)addr, size))                          \
+      _bad = 1;                                                               \
+    else                                                                      \
+      switch (size)                                                           \
+        {                                                                     \
+        case 1: __put_user_asm(((u8)(value)),addr,_bad,"b","b","iq",1); break; \
+        case 2: __put_user_asm(((u16)(value)),addr,_bad,"w","w","ir",1); break;\
+        case 4: __put_user_asm(((u32)(value)),addr,_bad,"l","k","ir",1); break;\
+        case 8: __put_user_asm(((u64)(value)),addr,_bad,"q","","Zr",1); break; \
+        default: __put_user_bad();                                      \
+        }                                                               \
+    pagefault_enable();                                                       \
+    set_fs(_oldfs);                                                           \
+    if (_bad)                                                                \
+      STORE_DEREF_FAULT(addr);                                               \
+  })
+
+#elif defined __ia64__
+
+#define _stp_deref(size, addr, seg)                                    \
+  ({                                                                   \
+     int _bad = 0;                                                     \
+     intptr_t _v=0;                                                    \
+     mm_segment_t _oldfs = get_fs();                                    \
+     set_fs(seg);                                                       \
+     pagefault_disable();                                               \
+     if (lookup_bad_addr((unsigned long)addr, size))                   \
+       _bad = 1;                                                        \
+     else {                                                            \
+       switch (size) {                                                  \
+        case 1: __get_user_size(_v, addr, 1, _bad); break;             \
+        case 2: __get_user_size(_v, addr, 2, _bad); break;             \
+        case 4: __get_user_size(_v, addr, 4, _bad); break;             \
+        case 8: __get_user_size(_v, addr, 8, _bad); break;             \
+        default: __get_user_unknown(); break;                          \
+         }                                                             \
+     }                                                                 \
+     pagefault_enable();                                                \
+     set_fs(_oldfs);                                                    \
+     if (_bad)                                                                 \
+       DEREF_FAULT(addr);                                              \
+     _v;                                                               \
+   })
+
+#define _stp_store_deref(size, addr, value, seg)                        \
+  ({                                                                   \
+    int _bad=0;                                                                \
+    mm_segment_t _oldfs = get_fs();                                     \
+    set_fs(seg);                                                        \
+    pagefault_disable();                                                \
+    if (lookup_bad_addr((unsigned long)addr, size))                    \
+      _bad = 1;                                                         \
+    else                                                                \
+      switch (size){                                                   \
+      case 1: __put_user_size(value, addr, 1, _bad); break;            \
+      case 2: __put_user_size(value, addr, 2, _bad); break;            \
+      case 4: __put_user_size(value, addr, 4, _bad); break;            \
+      case 8: __put_user_size(value, addr, 8, _bad); break;            \
+      default: __put_user_unknown(); break;                            \
+      }                                                                 \
+    pagefault_enable();                                                 \
+    set_fs(_oldfs);                                                     \
+    if (_bad)                                                          \
+          STORE_DEREF_FAULT(addr);                                     \
+   })
+
+#elif defined __powerpc__ || defined __powerpc64__
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
+#define __stp_get_user_size(x, ptr, size, retval)              \
+               __get_user_size(x, ptr, size, retval)
+#define __stp_put_user_size(x, ptr, size, retval)              \
+               __put_user_size(x, ptr, size, retval)
+#else
+#define __stp_get_user_size(x, ptr, size, retval)              \
+               __get_user_size(x, ptr, size, retval, -EFAULT)
+#define __stp_put_user_size(x, ptr, size, retval)              \
+               __put_user_size(x, ptr, size, retval, -EFAULT)
+#endif
+
+#define _stp_deref(size, addr, seg)                                           \
+  ({                                                                         \
+    int _bad = 0;                                                            \
+    intptr_t _v = 0;                                                         \
+    mm_segment_t _oldfs = get_fs();                                           \
+    set_fs(seg);                                                              \
+    pagefault_disable();                                                      \
+    if (lookup_bad_addr((unsigned long)addr, size))                          \
+      _bad = 1;                                                               \
+    else                                                                      \
+      switch (size)                                                           \
+        {                                                                     \
+       case 1: __stp_get_user_size(_v, addr, 1, _bad); break;                \
+       case 2: __stp_get_user_size(_v, addr, 2, _bad); break;                \
+       case 4: __stp_get_user_size(_v, addr, 4, _bad); break;                \
+       case 8: __stp_get_user_size(_v, addr, 8, _bad); break;                \
+        default: _v = __get_user_bad();                                       \
+        }                                                                     \
+    pagefault_enable();                                                       \
+    set_fs(_oldfs);                                                           \
+    if (_bad)                                                                \
+      DEREF_FAULT(addr);                                                     \
+    _v;                                                                              \
+  })
+
+#define _stp_store_deref(size, addr, value, seg)                              \
+  ({                                                                         \
+    int _bad = 0;                                                            \
+    mm_segment_t _oldfs = get_fs();                                           \
+    set_fs(seg);                                                              \
+    pagefault_disable();                                                      \
+    if (lookup_bad_addr((unsigned long)addr, size))                          \
+      _bad = 1;                                                               \
+    else                                                                      \
+      switch (size)                                                           \
+        {                                                                     \
+       case 1: __stp_put_user_size(((u8)(value)), addr, 1, _bad); break;     \
+       case 2: __stp_put_user_size(((u16)(value)), addr, 2, _bad); break;    \
+       case 4: __stp_put_user_size(((u32)(value)), addr, 4, _bad); break;    \
+       case 8: __stp_put_user_size(((u64)(value)), addr, 8, _bad); break;    \
+        default: __put_user_bad();                                            \
+        }                                                                     \
+    pagefault_enable();                                                       \
+    set_fs(_oldfs);                                                           \
+    if (_bad)                                                                \
+      STORE_DEREF_FAULT(addr);                                               \
+  })
+
+#elif defined (__arm__)
+
+/* Macros for ARM lifted from 2.6.21.1's linux/include/asm-arm/uaccess.h
+ * and slightly altered. */
+
+#define __stp_get_user_asm_byte(x,addr,err)                    \
+       __asm__ __volatile__(                                   \
+       "1:     ldrb    %1,[%2],#0\n"                           \
+       "2:\n"                                                  \
+       "       .section .fixup,\"ax\"\n"                       \
+       "       .align  2\n"                                    \
+       "3:     mov     %0, %3\n"                               \
+       "       mov     %1, #0\n"                               \
+       "       b       2b\n"                                   \
+       "       .previous\n"                                    \
+       "       .section __ex_table,\"a\"\n"                    \
+       "       .align  3\n"                                    \
+       "       .long   1b, 3b\n"                               \
+       "       .previous"                                      \
+       : "+r" (err), "=&r" (x)                                 \
+       : "r" (addr), "i" (-EFAULT)                             \
+       : "cc")
+
+#ifndef __ARMEB__
+#define __stp_get_user_asm_half(x,__gu_addr,err)               \
+({                                                             \
+       unsigned long __b1, __b2;                               \
+       __stp_get_user_asm_byte(__b1, __gu_addr, err);          \
+       __stp_get_user_asm_byte(__b2, __gu_addr + 1, err);      \
+       (x) = __b1 | (__b2 << 8);                               \
+})
+#else
+#define __stp_get_user_asm_half(x,__gu_addr,err)               \
+({                                                             \
+       unsigned long __b1, __b2;                               \
+       __stp_get_user_asm_byte(__b1, __gu_addr, err);          \
+       __stp_get_user_asm_byte(__b2, __gu_addr + 1, err);      \
+       (x) = (__b1 << 8) | __b2;                               \
+})
+#endif
+
+#define __stp_get_user_asm_word(x,addr,err)                    \
+       __asm__ __volatile__(                                   \
+       "1:     ldr     %1,[%2],#0\n"                           \
+       "2:\n"                                                  \
+       "       .section .fixup,\"ax\"\n"                       \
+       "       .align  2\n"                                    \
+       "3:     mov     %0, %3\n"                               \
+       "       mov     %1, #0\n"                               \
+       "       b       2b\n"                                   \
+       "       .previous\n"                                    \
+       "       .section __ex_table,\"a\"\n"                    \
+       "       .align  3\n"                                    \
+       "       .long   1b, 3b\n"                               \
+       "       .previous"                                      \
+       : "+r" (err), "=&r" (x)                                 \
+       : "r" (addr), "i" (-EFAULT)                             \
+       : "cc")
+
+#define __stp_put_user_asm_byte(x,__pu_addr,err)               \
+       __asm__ __volatile__(                                   \
+       "1:     strb    %1,[%2],#0\n"                           \
+       "2:\n"                                                  \
+       "       .section .fixup,\"ax\"\n"                       \
+       "       .align  2\n"                                    \
+       "3:     mov     %0, %3\n"                               \
+       "       b       2b\n"                                   \
+       "       .previous\n"                                    \
+       "       .section __ex_table,\"a\"\n"                    \
+       "       .align  3\n"                                    \
+       "       .long   1b, 3b\n"                               \
+       "       .previous"                                      \
+       : "+r" (err)                                            \
+       : "r" (x), "r" (__pu_addr), "i" (-EFAULT)               \
+       : "cc")
+
+#ifndef __ARMEB__
+#define __stp_put_user_asm_half(x,__pu_addr,err)                       \
+({                                                                     \
+       unsigned long __temp = (unsigned long)(x);                      \
+       __stp_put_user_asm_byte(__temp, __pu_addr, err);                \
+       __stp_put_user_asm_byte(__temp >> 8, __pu_addr + 1, err);       \
+})
+#else
+#define __stp_put_user_asm_half(x,__pu_addr,err)                       \
+({                                                                     \
+       unsigned long __temp = (unsigned long)(x);                      \
+       __stp_put_user_asm_byte(__temp >> 8, __pu_addr, err);           \
+       __stp_put_user_asm_byte(__temp, __pu_addr + 1, err);            \
+})
+#endif
+
+#define __stp_put_user_asm_word(x,__pu_addr,err)               \
+       __asm__ __volatile__(                                   \
+       "1:     str     %1,[%2],#0\n"                           \
+       "2:\n"                                                  \
+       "       .section .fixup,\"ax\"\n"                       \
+       "       .align  2\n"                                    \
+       "3:     mov     %0, %3\n"                               \
+       "       b       2b\n"                                   \
+       "       .previous\n"                                    \
+       "       .section __ex_table,\"a\"\n"                    \
+       "       .align  3\n"                                    \
+       "       .long   1b, 3b\n"                               \
+       "       .previous"                                      \
+       : "+r" (err)                                            \
+       : "r" (x), "r" (__pu_addr), "i" (-EFAULT)               \
+       : "cc")
+
+#define _stp_deref(size, addr, seg)                                    \
+  ({                                                                   \
+     int _bad = 0;                                                     \
+     intptr_t _v=0;                                                    \
+     mm_segment_t _oldfs = get_fs();                                    \
+     set_fs(seg);                                                       \
+     pagefault_disable();                                               \
+     if (lookup_bad_addr((unsigned long)addr, size))                   \
+      _bad = 1;                                                         \
+     else                                                               \
+      switch (size){                                                   \
+      case 1: __stp_get_user_asm_byte(_v, addr, _bad); break;           \
+      case 2: __stp_get_user_asm_half(_v, addr, _bad); break;           \
+      case 4: __stp_get_user_asm_word(_v, addr, _bad); break;           \
+      default: __get_user_bad(); break;                                 \
+      }                                                                 \
+    pagefault_enable();                                                 \
+    set_fs(_oldfs);                                                     \
+    if (_bad)                                                                  \
+       DEREF_FAULT(addr);                                              \
+     _v;                                                               \
+   })
+
+#define _stp_store_deref(size, addr, value, seg)                        \
+  ({                                                                   \
+    int _bad=0;                                                                \
+    mm_segment_t _oldfs = get_fs();                                           \
+    set_fs(seg);                                                              \
+    pagefault_disable();                                                      \
+    if (lookup_bad_addr((unsigned long)addr, size))                    \
+      _bad = 1;                                                         \
+    else                                                                \
+      switch (size){                                                   \
+      case 1: __stp_put_user_asm_byte(value, addr, _bad); break;       \
+      case 2: __stp_put_user_asm_half(value, addr, _bad); break;       \
+      case 4: __stp_put_user_asm_word(value, addr, _bad); break;       \
+      default: __put_user_bad(); break;                                 \
+      }                                                                 \
+    pagefault_enable();                                                       \
+    set_fs(_oldfs);                                                           \
+    if (_bad)                                                          \
+          STORE_DEREF_FAULT(addr);                                             \
+   })
+
+#elif defined (__s390__) || defined (__s390x__)
+
+/* Use same __get_user() and __put_user() for both user and kernel
+   addresses, but make sure set_fs() is called appropriately first. */
+
+#define _stp_deref(size, addr, seg) ({ \
+    u8 _b; u16 _w; u32 _l; u64 _q; \
+    uintptr_t _a = (uintptr_t) addr; \
+    intptr_t _v = 0; \
+    int _bad = 0; \
+    mm_segment_t _oldfs = get_fs();                                           \
+    set_fs(seg);                                                              \
+    pagefault_disable();                                                      \
+    if (lookup_bad_addr((unsigned long)addr, size))                    \
+      _bad = 1;                                                         \
+    else switch (size) { \
+      case 1: _bad = __get_user(_b, (u8 *)(_a)); _v = _b; break; \
+      case 2: _bad = __get_user(_w, (u16 *)(_a)); _v = _w; break; \
+      case 4: _bad = __get_user(_l, (u32 *)(_a)); _v = _l; break; \
+      case 8: _bad = __get_user(_q, (u64 *)(_a)); _v = _q; break; \
+      default: __get_user_bad(); \
+    } \
+    pagefault_enable();                                                       \
+    set_fs(_oldfs);                                                           \
+    if (_bad) \
+      DEREF_FAULT(addr); \
+    _v; \
+  })
+
+#define _stp_store_deref(size, addr, value, seg) ({ \
+    int _bad = 0; \
+    mm_segment_t _oldfs = get_fs();                                           \
+    set_fs(seg);                                                              \
+    pagefault_disable();                                                      \
+    if (lookup_bad_addr((unsigned long)addr, size))                    \
+      _bad = 1;                                                         \
+    else switch (size) {                                               \
+      case 1: _bad = __put_user(((u8)(value)), ((u8 *)(addr))); break; \
+      case 2: _bad = __put_user(((u16)(value)), ((u16 *)(addr))); break; \
+      case 4: _bad = __put_user(((u32)(value)), ((u32 *)(addr))); break; \
+      case 8: _bad = __put_user(((u64)(value)), ((u64 *)(addr))); break; \
+      default: __put_user_bad(); \
+    } \
+    pagefault_enable();                                                       \
+    set_fs(_oldfs);                                                           \
+    if (_bad) \
+       STORE_DEREF_FAULT(addr); \
+  })
+
+#endif /* (s390) || (s390x) */
+
+
+/* Map kderef/uderef to the generic segment-aware deref macros. */ 
+
+#ifndef kderef
+#define kderef(s,a) _stp_deref(s,a,KERNEL_DS)
+#endif
+
+#ifndef store_kderef
+#define store_kderef(s,a,v) _stp_store_deref(s,a,v,KERNEL_DS)
+#endif
+
+#ifndef uderef
+#define uderef(s,a) _stp_deref(s,a,USER_DS)
+#endif
+
+#ifndef store_uderef
+#define store_uderef(s,a,v) _stp_store_deref(s,a,v,USER_DS)
+#endif
+
+
+
+#if defined (__i386__) || defined (__arm__)
+
+/* x86 and arm can't do 8-byte put/get_user_asm, so we have to split it */
+
+#define __Xread(ptr, Xderef)                           \
+  ((sizeof(*(ptr)) == 8) ?                             \
+       *(typeof(ptr))&(u32[2]) {                       \
+        (u32) Xderef(4, &((u32 *)(ptr))[0]),           \
+        (u32) Xderef(4, &((u32 *)(ptr))[1]) }          \
+     : (typeof(*(ptr))) Xderef(sizeof(*(ptr)), (ptr)))
+
+#define __Xwrite(ptr, value, store_Xderef)                                  \
+  ({                                                                        \
+    if (sizeof(*(ptr)) == 8) {                                              \
+      union { typeof(*(ptr)) v; u32 l[2]; } _kw;                            \
+      _kw.v = (typeof(*(ptr)))(value);                                      \
+      store_Xderef(4, &((u32 *)(ptr))[0], _kw.l[0]);                        \
+      store_Xderef(4, &((u32 *)(ptr))[1], _kw.l[1]);                        \
+    } else                                                                  \
+      store_Xderef(sizeof(*(ptr)), (ptr), (long)(typeof(*(ptr)))(value));     \
+  })
+
+#else
+
+#define __Xread(ptr, Xderef) \
+  ( (typeof(*(ptr))) Xderef(sizeof(*(ptr)), (ptr)) )
+#define __Xwrite(ptr, value, store_Xderef) \
+  ( store_Xderef(sizeof(*(ptr)), (ptr), (long)(typeof(*(ptr)))(value)) )
+
+#endif
+
+#define kread(ptr) __Xread((ptr), kderef)
+#define uread(ptr) __Xread((ptr), uderef)
+
+#define kwrite(ptr, value) __Xwrite((ptr), (value), store_kderef)
+#define uwrite(ptr, value) __Xwrite((ptr), (value), store_uderef)
+
+#endif /* STAPCONF_PROBE_KERNEL */
+
+/* Dereference a kernel buffer ADDR of size MAXBYTES. Put the bytes in
+ * address DST (which can be NULL).
+ *
+ * This function is useful for reading memory when the size isn't a
+ * size that kderef() handles.  This function is very similar to
+ * kderef_string(), but kderef_buffer() doesn't quit when finding a
+ * '\0' byte or append a '\0' byte.
+ */
+
+#define kderef_buffer(dst, addr, maxbytes)                                   \
+  ({                                                                         \
+    uintptr_t _addr;                                                         \
+    size_t _len;                                                             \
+    unsigned char _c;                                                        \
+    char *_d = (dst);                                                        \
+    for (_len = (maxbytes), _addr = (uintptr_t)(addr);                       \
+        _len > 1;                                                            \
+        --_len, ++_addr)                                                     \
+      _c = kderef (1, _addr);                                                \
+      if (_d)                                                                \
+        *_d++ = _c;                                                          \
+    (dst);                                                                   \
+  })
+
+/* The following is for kernel strings, see the uconversions.stp
+   tapset for user_string functions. */
+
+#define kderef_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 = kderef (1, _addr)) != '\0';                        \
+        --_len, ++_addr)                                                     \
+      if (_d)                                                                \
+        *_d++ = _c;                                                          \
+    if (_d)                                                                  \
+      *_d = '\0';                                                            \
+    (dst);                                                                   \
+  })
+
+#define store_kderef_string(src, addr, maxbytes)                             \
+  ({                                                                         \
+    uintptr_t _addr;                                                         \
+    size_t _len;                                                             \
+    char *_s = (src);                                                        \
+    for (_len = (maxbytes), _addr = (uintptr_t)(addr);                       \
+        _len > 1 && _s && *_s != '\0'; --_len, ++_addr)                      \
+      store_kderef(1, _addr, *_s++);                                         \
+    store_kderef(1, _addr, '\0');                                            \
+  })
+
+#define CATCH_DEREF_FAULT()                            \
+  if (0) {                                             \
+deref_fault: ;                                         \
+  }
+
+
+#endif /* _LINUX_LOC2C_RUNTIME_H_ */
index fc2e7dbcaed893a2c6c24b1f2d1ac11583b95f15..c9679d8f05fa13654b816187e63bfa06ba52a68d 100644 (file)
@@ -9,21 +9,10 @@
  * later version.
  */
 
-#ifdef __KERNEL__
-#ifdef STAPCONF_LINUX_UACCESS_H
-#include <linux/uaccess.h>
-#else
-#include <asm/uaccess.h>
-#endif
-#include <linux/types.h>
-#define intptr_t long
-#define uintptr_t unsigned long
-#endif
+#ifndef _LOC2C_RUNTIME_H_
+#define _LOC2C_RUNTIME_H_
 
-#ifndef STAPCONF_PAGEFAULT_DISABLE  /* before linux commit a866374a */
-#define pagefault_disable() preempt_disable()
-#define pagefault_enable() preempt_enable_no_resched()
-#endif
+/* See also the linux/ and dyninst/ runtime specializations. */
 
 
 /* These three macro definitions are generic, just shorthands
               << (sizeof (target) * 8 - (higherbits) - (nbits))))
 
 
-/* Given a DWARF register number, fetch its intptr_t (long) value from the
-   probe context, or store a new value into the probe context.
-
-   The register number argument is always a canonical decimal number, so it
-   can be pasted into an identifier name.  These definitions turn it into a
-   per-register macro, defined below for machines with individually-named
-   registers.  */
-#define pt_regs_fetch_register(pt_regs, regno) \
-  ((intptr_t) k_dwarf_register_##regno (pt_regs))
-#define pt_regs_store_register(pt_regs, regno, value) \
-  (k_dwarf_register_##regno (pt_regs) = (value))
-
-#define k_fetch_register(regno) \
-  pt_regs_fetch_register(c->kregs, regno)
-#define k_store_register(regno, value) \
-  pt_regs_store_register(c->kregs, regno, value)
-
-
-/* The deref and store_deref macros are called to safely access addresses
-   in the probe context.  These macros are used only for kernel addresses.
-   The macros must handle bogus addresses here gracefully (as from
-   corrupted data structures, stale pointers, etc), by doing a "goto
-   deref_fault".
-
-   On most machines, the asm/uaccess.h macros __get_user_asm and
-   __put_user_asm do exactly the low-level work we need to access memory
-   with fault handling, and are not actually specific to user-address
-   access at all.  Each machine's definition of deref and deref_store here
-   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),                     \
-      STAP_MSG_LOC2C_01, (void *)(intptr_t)(addr), #addr);   \
-    c->last_error = c->error_buffer;                                       \
-    goto deref_fault;                                                      \
-    })
-
-#define STORE_DEREF_FAULT(addr) ({                                         \
-    snprintf(c->error_buffer, sizeof(c->error_buffer),                     \
-      STAP_MSG_LOC2C_02, (void *)(intptr_t)(addr), #addr);  \
-    c->last_error = c->error_buffer;                                       \
-    goto deref_fault;                                                      \
-    })
-#endif
-
 /* dwarf_div_op and dwarf_mod_op do division and modulo operations catching any
    divide by zero issues.  When they detect div_by_zero they "fault"
    by jumping to the (slightly misnamed) deref_fault label.  */
     a % b;                                                             \
 })
 
-/* PR 10601: user-space (user_regset) register access.
-   Needs arch specific code, only i386 and x86_64 for now.  */
-#if ((defined(STAPCONF_REGSET) || defined(STAPCONF_UTRACE_REGSET)) \
-     && (defined (__i386__) || defined (__x86_64__)))
-
-#if defined(STAPCONF_REGSET)
-#include <linux/regset.h>
-#endif
-
-#if defined(STAPCONF_UTRACE_REGSET)
-#include <linux/tracehook.h>
-/* adapt new names to old decls */
-#define user_regset_view utrace_regset_view
-#define user_regset utrace_regset
-#define task_user_regset_view utrace_native_view
-
-#else // PR13489, inodes-uprobes export kludge
-#if !defined(STAPCONF_TASK_USER_REGSET_VIEW_EXPORTED)
-// First typedef from the original decl, then #define it as a typecasted call.
-// NB: not all archs actually have the function, but the decl is universal in regset.h
-typedef typeof(&task_user_regset_view) task_user_regset_view_fn;
-/* Special macro to tolerate the kallsyms function pointer being zero. */
-#define task_user_regset_view(t) (kallsyms_task_user_regset_view ? \
-                                  (* (task_user_regset_view_fn)(kallsyms_task_user_regset_view))((t)) : \
-                                  NULL)
-#endif
-#endif
-
-struct usr_regset_lut {
-  char *name;
-  unsigned rsn;
-  unsigned pos;
-};
-
 
-/* DWARF register number -to- user_regset bank/offset mapping table.
-   The register numbers come from the processor-specific ELF documents.
-   The user-regset bank/offset values come from kernel $ARCH/include/asm/user*.h
-   or $ARCH/kernel/ptrace.c. */
-#if defined (__i386__) || defined (__x86_64__)
-static const struct usr_regset_lut url_i386[] = {
-  { "ax", NT_PRSTATUS, 6*4 },
-  { "cx", NT_PRSTATUS, 1*4 },
-  { "dx", NT_PRSTATUS, 2*4 },
-  { "bx", NT_PRSTATUS, 0*4 },
-  { "sp", NT_PRSTATUS, 15*4 },
-  { "bp", NT_PRSTATUS, 5*4 },
-  { "si", NT_PRSTATUS, 3*4 },
-  { "di", NT_PRSTATUS, 4*4 },
-  { "ip", NT_PRSTATUS, 12*4 },
-};
-#endif
-
-#if defined (__x86_64__)
-static const struct usr_regset_lut url_x86_64[] = {
-  { "rax", NT_PRSTATUS, 10*8 },
-  { "rdx", NT_PRSTATUS, 12*8 },
-  { "rcx", NT_PRSTATUS, 11*8 },
-  { "rbx", NT_PRSTATUS, 5*8 },
-  { "rsi", NT_PRSTATUS, 13*8 },
-  { "rdi", NT_PRSTATUS, 14*8 },
-  { "rbp", NT_PRSTATUS, 4*8 },
-  { "rsp", NT_PRSTATUS, 19*8 },
-  { "r8", NT_PRSTATUS, 9*8 },
-  { "r9", NT_PRSTATUS, 8*8 }, 
-  { "r10", NT_PRSTATUS, 7*8 },  
-  { "r11", NT_PRSTATUS, 6*8 }, 
-  { "r12", NT_PRSTATUS, 3*8 }, 
-  { "r13", NT_PRSTATUS, 2*8 }, 
-  { "r14", NT_PRSTATUS, 1*8 }, 
-  { "r15", NT_PRSTATUS, 0*8 }, 
-  { "rip", NT_PRSTATUS, 16*8 }, 
-  /* XXX: SSE registers %xmm0-%xmm7 */ 
-  /* XXX: SSE2 registers %xmm8-%xmm15 */
-  /* XXX: FP registers %st0-%st7 */
-  /* XXX: MMX registers %mm0-%mm7 */
-};
-#endif
-/* XXX: insert other architectures here. */
-
-
-static u32 ursl_fetch32 (const struct usr_regset_lut* lut, unsigned lutsize, int e_machine, unsigned regno)
-{
-  u32 value = ~0;
-  const struct user_regset_view *rsv = task_user_regset_view(current); 
-  unsigned rsi;
-  int rc;
-  unsigned rsn;
-  unsigned pos;
-  unsigned count;
-
-  WARN_ON (!rsv);
-  if (!rsv) goto out;
-  WARN_ON (regno >= lutsize);
-  if (regno >= lutsize) goto out;
-  if (rsv->e_machine != e_machine) goto out;
-
-  rsn = lut[regno].rsn;
-  pos = lut[regno].pos;
-  count = sizeof(value);
-
-  for (rsi=0; rsi<rsv->n; rsi++)
-    if (rsv->regsets[rsi].core_note_type == rsn)
-      {
-        const struct user_regset *rs = & rsv->regsets[rsi];
-        rc = (rs->get)(current, rs, pos, count, & value, NULL);
-        WARN_ON (rc);
-        /* success */
-        goto out;
-      }
-  WARN_ON (1); /* did not find appropriate regset! */
-  
- out:
-  return value;
-}
-
-
-static void ursl_store32 (const struct usr_regset_lut* lut,unsigned lutsize,  int e_machine, unsigned regno, u32 value)
-{
-  const struct user_regset_view *rsv = task_user_regset_view(current); 
-  unsigned rsi;
-  int rc;
-  unsigned rsn;
-  unsigned pos;
-  unsigned count;
-
-  WARN_ON (!rsv);
-  if (!rsv) goto out;
-  WARN_ON (regno >= lutsize);
-  if (regno >= lutsize) goto out;
-  if (rsv->e_machine != e_machine) goto out;
-
-  rsn = lut[regno].rsn;
-  pos = lut[regno].pos;
-  count = sizeof(value);
-
-  for (rsi=0; rsi<rsv->n; rsi++)
-    if (rsv->regsets[rsi].core_note_type == rsn)
-      {
-        const struct user_regset *rs = & rsv->regsets[rsi];
-        rc = (rs->set)(current, rs, pos, count, & value, NULL);
-        WARN_ON (rc);
-        /* success */
-        goto out;
-      }
-  WARN_ON (1); /* did not find appropriate regset! */
-  
- out:
-  return;
-}
-
-
-static u64 ursl_fetch64 (const struct usr_regset_lut* lut, unsigned lutsize, int e_machine, unsigned regno)
-{
-  u64 value = ~0;
-  const struct user_regset_view *rsv = task_user_regset_view(current); 
-  unsigned rsi;
-  int rc;
-  unsigned rsn;
-  unsigned pos;
-  unsigned count;
-
-  if (!rsv) goto out;
-  if (regno >= lutsize) goto out;
-  if (rsv->e_machine != e_machine) goto out;
-
-  rsn = lut[regno].rsn;
-  pos = lut[regno].pos;
-  count = sizeof(value);
-
-  for (rsi=0; rsi<rsv->n; rsi++)
-    if (rsv->regsets[rsi].core_note_type == rsn)
-      {
-        const struct user_regset *rs = & rsv->regsets[rsi];
-        rc = (rs->get)(current, rs, pos, count, & value, NULL);
-        if (rc)
-          goto out;
-        /* success */
-        return value;
-      }
- out:
-  printk (KERN_WARNING "process %d mach %d regno %d not available for fetch.\n", current->tgid, e_machine, regno);
-  return value;
-}
-
-
-static void ursl_store64 (const struct usr_regset_lut* lut,unsigned lutsize,  int e_machine, unsigned regno, u64 value)
-{
-  const struct user_regset_view *rsv = task_user_regset_view(current); 
-  unsigned rsi;
-  int rc;
-  unsigned rsn;
-  unsigned pos;
-  unsigned count;
-
-  WARN_ON (!rsv);
-  if (!rsv) goto out;
-  WARN_ON (regno >= lutsize);
-  if (regno >= lutsize) goto out;
-  if (rsv->e_machine != e_machine) goto out;
-
-  rsn = lut[regno].rsn;
-  pos = lut[regno].pos;
-  count = sizeof(value);
-
-  for (rsi=0; rsi<rsv->n; rsi++)
-    if (rsv->regsets[rsi].core_note_type == rsn)
-      {
-        const struct user_regset *rs = & rsv->regsets[rsi];
-        rc = (rs->set)(current, rs, pos, count, & value, NULL);
-        if (rc)
-          goto out;
-        /* success */
-        return;
-      }
-  
- out:
-  printk (KERN_WARNING "process %d mach %d regno %d not available for store.\n", current->tgid, e_machine, regno);
-  return;
-}
-
-
-#if defined (__i386__)
-
-#define u_fetch_register(regno) ursl_fetch32(url_i386, ARRAY_SIZE(url_i386), EM_386, regno)
-#define u_store_register(regno,value) ursl_store32(url_i386, ARRAY_SIZE(url_i386), EM_386, regno, value)
-
-#elif defined (__x86_64__)
-
-#define u_fetch_register(regno) (_stp_is_compat_task() ? ursl_fetch32(url_i386, ARRAY_SIZE(url_i386), EM_386, regno) : ursl_fetch64(url_x86_64, ARRAY_SIZE(url_x86_64), EM_X86_64, regno))
-#define u_store_register(regno,value)  (_stp_is_compat_task() ? ursl_store32(url_i386, ARRAY_SIZE(url_i386), EM_386, regno, value) : ursl_store64(url_x86_64, ARRAY_SIZE(url_x86_64), EM_X86_64, regno, value))
-
-#endif
+/* Given a DWARF register number, fetch its intptr_t (long) value from the
+   probe context, or store a new value into the probe context.
 
-#else /* ! STAPCONF_REGSET */
-/* Downgrade to k_dwarf_register access. */
-#define u_fetch_register(regno) \
-  pt_regs_fetch_register(c->uregs, regno)
-#define u_store_register(regno, value) \
-  pt_regs_store_register(c->uregs, regno, value)
-#endif
+   The register number argument is always a canonical decimal number, so it
+   can be pasted into an identifier name.  These definitions turn it into a
+   per-register macro, defined below for machines with individually-named
+   registers.  */
+#define pt_regs_fetch_register(pt_regs, regno) \
+  ((intptr_t) pt_dwarf_register_##regno (pt_regs))
+#define pt_regs_store_register(pt_regs, regno, value) \
+  (pt_dwarf_register_##regno (pt_regs) = (value))
 
 
 #if defined (STAPCONF_X86_UNIREGS) && defined (__i386__)
 
-#define k_dwarf_register_0(regs)  regs->ax
-#define k_dwarf_register_1(regs)  regs->cx
-#define k_dwarf_register_2(regs)  regs->dx
-#define k_dwarf_register_3(regs)  regs->bx
-#define k_dwarf_register_4(regs)  ((long) &regs->sp)
-#define k_dwarf_register_5(regs)  regs->bp
-#define k_dwarf_register_6(regs)  regs->si
-#define k_dwarf_register_7(regs)  regs->di
+#define pt_dwarf_register_0(regs)  regs->ax
+#define pt_dwarf_register_1(regs)  regs->cx
+#define pt_dwarf_register_2(regs)  regs->dx
+#define pt_dwarf_register_3(regs)  regs->bx
+#define pt_dwarf_register_4(regs)  ((long) &regs->sp)
+#define pt_dwarf_register_5(regs)  regs->bp
+#define pt_dwarf_register_6(regs)  regs->si
+#define pt_dwarf_register_7(regs)  regs->di
 
 #elif defined (STAPCONF_X86_UNIREGS) && defined (__x86_64__)
 
-#define k_dwarf_register_0(regs)  regs->ax
-#define k_dwarf_register_1(regs)  regs->dx
-#define k_dwarf_register_2(regs)  regs->cx
-#define k_dwarf_register_3(regs)  regs->bx
-#define k_dwarf_register_4(regs)  regs->si
-#define k_dwarf_register_5(regs)  regs->di
-#define k_dwarf_register_6(regs)  regs->bp
-#define k_dwarf_register_7(regs)  regs->sp
-#define k_dwarf_register_8(regs)  regs->r8
-#define k_dwarf_register_9(regs)  regs->r9
-#define k_dwarf_register_10(regs) regs->r10
-#define k_dwarf_register_11(regs) regs->r11
-#define k_dwarf_register_12(regs) regs->r12
-#define k_dwarf_register_13(regs) regs->r13
-#define k_dwarf_register_14(regs) regs->r14
-#define k_dwarf_register_15(regs) regs->r15
+#define pt_dwarf_register_0(regs)  regs->ax
+#define pt_dwarf_register_1(regs)  regs->dx
+#define pt_dwarf_register_2(regs)  regs->cx
+#define pt_dwarf_register_3(regs)  regs->bx
+#define pt_dwarf_register_4(regs)  regs->si
+#define pt_dwarf_register_5(regs)  regs->di
+#define pt_dwarf_register_6(regs)  regs->bp
+#define pt_dwarf_register_7(regs)  regs->sp
+#define pt_dwarf_register_8(regs)  regs->r8
+#define pt_dwarf_register_9(regs)  regs->r9
+#define pt_dwarf_register_10(regs) regs->r10
+#define pt_dwarf_register_11(regs) regs->r11
+#define pt_dwarf_register_12(regs) regs->r12
+#define pt_dwarf_register_13(regs) regs->r13
+#define pt_dwarf_register_14(regs) regs->r14
+#define pt_dwarf_register_15(regs) regs->r15
 
 #elif defined __i386__
 
@@ -397,14 +107,14 @@ static void ursl_store64 (const struct usr_regset_lut* lut,unsigned lutsize,  in
    For a kernel mode trap, the interrupted state's esp is actually an
    address inside where the `struct pt_regs' on the kernel trap stack points. */
 
-#define k_dwarf_register_0(regs)       regs->eax
-#define k_dwarf_register_1(regs)       regs->ecx
-#define k_dwarf_register_2(regs)       regs->edx
-#define k_dwarf_register_3(regs)       regs->ebx
-#define k_dwarf_register_4(regs)       (user_mode(regs) ? regs->esp : (long)&regs->esp)
-#define k_dwarf_register_5(regs)       regs->ebp
-#define k_dwarf_register_6(regs)       regs->esi
-#define k_dwarf_register_7(regs)       regs->edi
+#define pt_dwarf_register_0(regs)      regs->eax
+#define pt_dwarf_register_1(regs)      regs->ecx
+#define pt_dwarf_register_2(regs)      regs->edx
+#define pt_dwarf_register_3(regs)      regs->ebx
+#define pt_dwarf_register_4(regs)      (user_mode(regs) ? regs->esp : (long)&regs->esp)
+#define pt_dwarf_register_5(regs)      regs->ebp
+#define pt_dwarf_register_6(regs)      regs->esi
+#define pt_dwarf_register_7(regs)      regs->edi
 
 #elif defined __ia64__
 
@@ -418,22 +128,22 @@ static void ursl_store64 (const struct usr_regset_lut* lut,unsigned lutsize,  in
 
 #elif defined __x86_64__
 
-#define k_dwarf_register_0(regs)       regs->rax
-#define k_dwarf_register_1(regs)       regs->rdx
-#define k_dwarf_register_2(regs)       regs->rcx
-#define k_dwarf_register_3(regs)       regs->rbx
-#define k_dwarf_register_4(regs)       regs->rsi
-#define k_dwarf_register_5(regs)       regs->rdi
-#define k_dwarf_register_6(regs)       regs->rbp
-#define k_dwarf_register_7(regs)       regs->rsp
-#define k_dwarf_register_8(regs)       regs->r8
-#define k_dwarf_register_9(regs)       regs->r9
-#define k_dwarf_register_10(regs)      regs->r10
-#define k_dwarf_register_11(regs)      regs->r11
-#define k_dwarf_register_12(regs)      regs->r12
-#define k_dwarf_register_13(regs)      regs->r13
-#define k_dwarf_register_14(regs)      regs->r14
-#define k_dwarf_register_15(regs)      regs->r15
+#define pt_dwarf_register_0(regs)      regs->rax
+#define pt_dwarf_register_1(regs)      regs->rdx
+#define pt_dwarf_register_2(regs)      regs->rcx
+#define pt_dwarf_register_3(regs)      regs->rbx
+#define pt_dwarf_register_4(regs)      regs->rsi
+#define pt_dwarf_register_5(regs)      regs->rdi
+#define pt_dwarf_register_6(regs)      regs->rbp
+#define pt_dwarf_register_7(regs)      regs->rsp
+#define pt_dwarf_register_8(regs)      regs->r8
+#define pt_dwarf_register_9(regs)      regs->r9
+#define pt_dwarf_register_10(regs)     regs->r10
+#define pt_dwarf_register_11(regs)     regs->r11
+#define pt_dwarf_register_12(regs)     regs->r12
+#define pt_dwarf_register_13(regs)     regs->r13
+#define pt_dwarf_register_14(regs)     regs->r14
+#define pt_dwarf_register_15(regs)     regs->r15
 
 #elif defined __powerpc__
 
@@ -465,595 +175,24 @@ static void ursl_store64 (const struct usr_regset_lut* lut,unsigned lutsize,  in
 #endif
 
 
-/* NB: this autoconf is always disabled, pending further performance eval. */
-#if 0 && 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 = 0; \
-        if (lookup_bad_addr((unsigned long)(ptr), sizeof (*(ptr))) ||  \
-            probe_kernel_read((void *)&_v, (void *)(ptr), sizeof(*(ptr)))) \
-          DEREF_FAULT(ptr); \
-        _v; \
+#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),                     \
+      STAP_MSG_LOC2C_01, (void *)(intptr_t)(addr), #addr);   \
+    c->last_error = c->error_buffer;                                       \
+    goto deref_fault;                                                      \
     })
-#define uread kread
 
-#define kwrite(ptr, value) ({ \
-        typeof(*(ptr)) _v; \
-        _v = (typeof(*(ptr)))(value); \
-        if (lookup_bad_addr((unsigned long)addr, sizeof (*(ptr))) ||   \
-            probe_kernel_write((void *)(ptr), (void *)&_v, sizeof(*(ptr)))) \
-          STORE_DEREF_FAULT(ptr); \
+#define STORE_DEREF_FAULT(addr) ({                                         \
+    snprintf(c->error_buffer, sizeof(c->error_buffer),                     \
+      STAP_MSG_LOC2C_02, (void *)(intptr_t)(addr), #addr);  \
+    c->last_error = c->error_buffer;                                       \
+    goto deref_fault;                                                      \
     })
-#define uwrite kwrite
-
-#define uderef(size, addr) ({ \
-    intptr_t _i = 0; \
-    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(); \
-    } \
-    _i; \
-  })
-#define kderef uderef
-
-#define store_uderef(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(); \
-    } \
-  })
-#define store_kderef store_uderef
-
-
-extern void __deref_bad(void);
-extern void __store_deref_bad(void);
-
-#else /* !STAPCONF_PROBE_KERNEL */
-
-#if defined __i386__
-
-#define _stp_deref(size, addr, seg)                                           \
-  ({                                                                         \
-    int _bad = 0;                                                            \
-    intptr_t _v = 0;                                                         \
-    mm_segment_t _oldfs = get_fs();                                           \
-    set_fs(seg);                                                              \
-    pagefault_disable();                                                      \
-    if (lookup_bad_addr((unsigned long)addr, size))                          \
-      _bad = 1;                                                               \
-    else                                                                      \
-      switch (size)                                                           \
-        {                                                                     \
-        case 1: { u8 _b; __get_user_asm(_b,addr,_bad,"b","b","=q",1); _v = _b; } break; \
-        case 2: { u16 _w; __get_user_asm(_w,addr,_bad,"w","w","=r",1); _v = _w; } break; \
-        case 4: { u32 _l; __get_user_asm(_l,addr,_bad,"l","","=r",1); _v = _l; } break; \
-        default: _v = __get_user_bad();                                       \
-        }                                                                     \
-    pagefault_enable();                                                       \
-    set_fs(_oldfs);                                                           \
-    if (_bad)                                                                 \
-      DEREF_FAULT(addr);                                                     \
-    _v;                                                                              \
-  })
-
-#define _stp_store_deref(size, addr, value, seg)                              \
-  ({                                                                         \
-    int _bad = 0;                                                            \
-    mm_segment_t _oldfs = get_fs();                                           \
-    set_fs(seg);                                                              \
-    pagefault_disable();                                                      \
-    if (lookup_bad_addr((unsigned long)addr, size))                          \
-      _bad = 1;                                                               \
-    else                                                                      \
-      switch (size)                                                           \
-        {                                                                     \
-        case 1: __put_user_asm(((u8)(value)),addr,_bad,"b","b","iq",1); break;\
-        case 2: __put_user_asm(((u16)(value)),addr,_bad,"w","w","ir",1); break;\
-        case 4: __put_user_asm(((u32)(value)),addr,_bad,"l","k","ir",1); break;\
-        default: __put_user_bad();                                            \
-        }                                                                     \
-    pagefault_enable();                                                       \
-    set_fs(_oldfs);                                                           \
-    if (_bad)                                                                 \
-      STORE_DEREF_FAULT(addr);                                                \
-  })
-
-
-#elif defined __x86_64__
-
-#define _stp_deref(size, addr, seg)                                           \
-  ({                                                                         \
-    int _bad = 0;                                                            \
-    intptr_t _v = 0;                                                         \
-    mm_segment_t _oldfs = get_fs();                                           \
-    set_fs(seg);                                                              \
-    pagefault_disable();                                                      \
-    if (lookup_bad_addr((unsigned long)addr, size))                          \
-      _bad = 1;                                                               \
-    else                                                                      \
-      switch (size)                                                           \
-        {                                                                     \
-        case 1: { u8 _b; __get_user_asm(_b,(unsigned long)addr,_bad,"b","b","=q",1); _v = _b; } break; \
-        case 2: { u16 _w; __get_user_asm(_w,(unsigned long)addr,_bad,"w","w","=r",1); _v = _w; } break; \
-        case 4: { u32 _l; __get_user_asm(_l,(unsigned long)addr,_bad,"l","","=r",1); _v = _l; } break; \
-        case 8: { u64 _q; __get_user_asm(_q,(unsigned long)addr,_bad,"q","","=r",1); _v = _q; } break; \
-        default: _v = __get_user_bad();                                       \
-        }                                                                     \
-    pagefault_enable();                                                       \
-    set_fs(_oldfs);                                                           \
-    if (_bad)                                                                \
-      DEREF_FAULT(addr);                                                     \
-    _v;                                                                              \
-  })
-
-#define _stp_store_deref(size, addr, value, seg)                              \
-  ({                                                                         \
-    int _bad = 0;                                                            \
-    mm_segment_t _oldfs = get_fs();                                           \
-    set_fs(seg);                                                              \
-    pagefault_disable();                                                      \
-    if (lookup_bad_addr((unsigned long)addr, size))                          \
-      _bad = 1;                                                               \
-    else                                                                      \
-      switch (size)                                                           \
-        {                                                                     \
-        case 1: __put_user_asm(((u8)(value)),addr,_bad,"b","b","iq",1); break; \
-        case 2: __put_user_asm(((u16)(value)),addr,_bad,"w","w","ir",1); break;\
-        case 4: __put_user_asm(((u32)(value)),addr,_bad,"l","k","ir",1); break;\
-        case 8: __put_user_asm(((u64)(value)),addr,_bad,"q","","Zr",1); break; \
-        default: __put_user_bad();                                      \
-        }                                                               \
-    pagefault_enable();                                                       \
-    set_fs(_oldfs);                                                           \
-    if (_bad)                                                                \
-      STORE_DEREF_FAULT(addr);                                               \
-  })
-
-#elif defined __ia64__
-
-#define _stp_deref(size, addr, seg)                                    \
-  ({                                                                   \
-     int _bad = 0;                                                     \
-     intptr_t _v=0;                                                    \
-     mm_segment_t _oldfs = get_fs();                                    \
-     set_fs(seg);                                                       \
-     pagefault_disable();                                               \
-     if (lookup_bad_addr((unsigned long)addr, size))                   \
-       _bad = 1;                                                        \
-     else {                                                            \
-       switch (size) {                                                  \
-        case 1: __get_user_size(_v, addr, 1, _bad); break;             \
-        case 2: __get_user_size(_v, addr, 2, _bad); break;             \
-        case 4: __get_user_size(_v, addr, 4, _bad); break;             \
-        case 8: __get_user_size(_v, addr, 8, _bad); break;             \
-        default: __get_user_unknown(); break;                          \
-         }                                                             \
-     }                                                                 \
-     pagefault_enable();                                                \
-     set_fs(_oldfs);                                                    \
-     if (_bad)                                                                 \
-       DEREF_FAULT(addr);                                              \
-     _v;                                                               \
-   })
-
-#define _stp_store_deref(size, addr, value, seg)                        \
-  ({                                                                   \
-    int _bad=0;                                                                \
-    mm_segment_t _oldfs = get_fs();                                     \
-    set_fs(seg);                                                        \
-    pagefault_disable();                                                \
-    if (lookup_bad_addr((unsigned long)addr, size))                    \
-      _bad = 1;                                                         \
-    else                                                                \
-      switch (size){                                                   \
-      case 1: __put_user_size(value, addr, 1, _bad); break;            \
-      case 2: __put_user_size(value, addr, 2, _bad); break;            \
-      case 4: __put_user_size(value, addr, 4, _bad); break;            \
-      case 8: __put_user_size(value, addr, 8, _bad); break;            \
-      default: __put_user_unknown(); break;                            \
-      }                                                                 \
-    pagefault_enable();                                                 \
-    set_fs(_oldfs);                                                     \
-    if (_bad)                                                          \
-          STORE_DEREF_FAULT(addr);                                     \
-   })
-
-#elif defined __powerpc__ || defined __powerpc64__
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
-#define __stp_get_user_size(x, ptr, size, retval)              \
-               __get_user_size(x, ptr, size, retval)
-#define __stp_put_user_size(x, ptr, size, retval)              \
-               __put_user_size(x, ptr, size, retval)
-#else
-#define __stp_get_user_size(x, ptr, size, retval)              \
-               __get_user_size(x, ptr, size, retval, -EFAULT)
-#define __stp_put_user_size(x, ptr, size, retval)              \
-               __put_user_size(x, ptr, size, retval, -EFAULT)
-#endif
-
-#define _stp_deref(size, addr, seg)                                           \
-  ({                                                                         \
-    int _bad = 0;                                                            \
-    intptr_t _v = 0;                                                         \
-    mm_segment_t _oldfs = get_fs();                                           \
-    set_fs(seg);                                                              \
-    pagefault_disable();                                                      \
-    if (lookup_bad_addr((unsigned long)addr, size))                          \
-      _bad = 1;                                                               \
-    else                                                                      \
-      switch (size)                                                           \
-        {                                                                     \
-       case 1: __stp_get_user_size(_v, addr, 1, _bad); break;                \
-       case 2: __stp_get_user_size(_v, addr, 2, _bad); break;                \
-       case 4: __stp_get_user_size(_v, addr, 4, _bad); break;                \
-       case 8: __stp_get_user_size(_v, addr, 8, _bad); break;                \
-        default: _v = __get_user_bad();                                       \
-        }                                                                     \
-    pagefault_enable();                                                       \
-    set_fs(_oldfs);                                                           \
-    if (_bad)                                                                \
-      DEREF_FAULT(addr);                                                     \
-    _v;                                                                              \
-  })
-
-#define _stp_store_deref(size, addr, value, seg)                              \
-  ({                                                                         \
-    int _bad = 0;                                                            \
-    mm_segment_t _oldfs = get_fs();                                           \
-    set_fs(seg);                                                              \
-    pagefault_disable();                                                      \
-    if (lookup_bad_addr((unsigned long)addr, size))                          \
-      _bad = 1;                                                               \
-    else                                                                      \
-      switch (size)                                                           \
-        {                                                                     \
-       case 1: __stp_put_user_size(((u8)(value)), addr, 1, _bad); break;     \
-       case 2: __stp_put_user_size(((u16)(value)), addr, 2, _bad); break;    \
-       case 4: __stp_put_user_size(((u32)(value)), addr, 4, _bad); break;    \
-       case 8: __stp_put_user_size(((u64)(value)), addr, 8, _bad); break;    \
-        default: __put_user_bad();                                            \
-        }                                                                     \
-    pagefault_enable();                                                       \
-    set_fs(_oldfs);                                                           \
-    if (_bad)                                                                \
-      STORE_DEREF_FAULT(addr);                                               \
-  })
-
-#elif defined (__arm__)
-
-/* Macros for ARM lifted from 2.6.21.1's linux/include/asm-arm/uaccess.h
- * and slightly altered. */
-
-#define __stp_get_user_asm_byte(x,addr,err)                    \
-       __asm__ __volatile__(                                   \
-       "1:     ldrb    %1,[%2],#0\n"                           \
-       "2:\n"                                                  \
-       "       .section .fixup,\"ax\"\n"                       \
-       "       .align  2\n"                                    \
-       "3:     mov     %0, %3\n"                               \
-       "       mov     %1, #0\n"                               \
-       "       b       2b\n"                                   \
-       "       .previous\n"                                    \
-       "       .section __ex_table,\"a\"\n"                    \
-       "       .align  3\n"                                    \
-       "       .long   1b, 3b\n"                               \
-       "       .previous"                                      \
-       : "+r" (err), "=&r" (x)                                 \
-       : "r" (addr), "i" (-EFAULT)                             \
-       : "cc")
-
-#ifndef __ARMEB__
-#define __stp_get_user_asm_half(x,__gu_addr,err)               \
-({                                                             \
-       unsigned long __b1, __b2;                               \
-       __stp_get_user_asm_byte(__b1, __gu_addr, err);          \
-       __stp_get_user_asm_byte(__b2, __gu_addr + 1, err);      \
-       (x) = __b1 | (__b2 << 8);                               \
-})
-#else
-#define __stp_get_user_asm_half(x,__gu_addr,err)               \
-({                                                             \
-       unsigned long __b1, __b2;                               \
-       __stp_get_user_asm_byte(__b1, __gu_addr, err);          \
-       __stp_get_user_asm_byte(__b2, __gu_addr + 1, err);      \
-       (x) = (__b1 << 8) | __b2;                               \
-})
 #endif
 
-#define __stp_get_user_asm_word(x,addr,err)                    \
-       __asm__ __volatile__(                                   \
-       "1:     ldr     %1,[%2],#0\n"                           \
-       "2:\n"                                                  \
-       "       .section .fixup,\"ax\"\n"                       \
-       "       .align  2\n"                                    \
-       "3:     mov     %0, %3\n"                               \
-       "       mov     %1, #0\n"                               \
-       "       b       2b\n"                                   \
-       "       .previous\n"                                    \
-       "       .section __ex_table,\"a\"\n"                    \
-       "       .align  3\n"                                    \
-       "       .long   1b, 3b\n"                               \
-       "       .previous"                                      \
-       : "+r" (err), "=&r" (x)                                 \
-       : "r" (addr), "i" (-EFAULT)                             \
-       : "cc")
-
-#define __stp_put_user_asm_byte(x,__pu_addr,err)               \
-       __asm__ __volatile__(                                   \
-       "1:     strb    %1,[%2],#0\n"                           \
-       "2:\n"                                                  \
-       "       .section .fixup,\"ax\"\n"                       \
-       "       .align  2\n"                                    \
-       "3:     mov     %0, %3\n"                               \
-       "       b       2b\n"                                   \
-       "       .previous\n"                                    \
-       "       .section __ex_table,\"a\"\n"                    \
-       "       .align  3\n"                                    \
-       "       .long   1b, 3b\n"                               \
-       "       .previous"                                      \
-       : "+r" (err)                                            \
-       : "r" (x), "r" (__pu_addr), "i" (-EFAULT)               \
-       : "cc")
-
-#ifndef __ARMEB__
-#define __stp_put_user_asm_half(x,__pu_addr,err)                       \
-({                                                                     \
-       unsigned long __temp = (unsigned long)(x);                      \
-       __stp_put_user_asm_byte(__temp, __pu_addr, err);                \
-       __stp_put_user_asm_byte(__temp >> 8, __pu_addr + 1, err);       \
-})
-#else
-#define __stp_put_user_asm_half(x,__pu_addr,err)                       \
-({                                                                     \
-       unsigned long __temp = (unsigned long)(x);                      \
-       __stp_put_user_asm_byte(__temp >> 8, __pu_addr, err);           \
-       __stp_put_user_asm_byte(__temp, __pu_addr + 1, err);            \
-})
-#endif
-
-#define __stp_put_user_asm_word(x,__pu_addr,err)               \
-       __asm__ __volatile__(                                   \
-       "1:     str     %1,[%2],#0\n"                           \
-       "2:\n"                                                  \
-       "       .section .fixup,\"ax\"\n"                       \
-       "       .align  2\n"                                    \
-       "3:     mov     %0, %3\n"                               \
-       "       b       2b\n"                                   \
-       "       .previous\n"                                    \
-       "       .section __ex_table,\"a\"\n"                    \
-       "       .align  3\n"                                    \
-       "       .long   1b, 3b\n"                               \
-       "       .previous"                                      \
-       : "+r" (err)                                            \
-       : "r" (x), "r" (__pu_addr), "i" (-EFAULT)               \
-       : "cc")
-
-#define _stp_deref(size, addr, seg)                                    \
-  ({                                                                   \
-     int _bad = 0;                                                     \
-     intptr_t _v=0;                                                    \
-     mm_segment_t _oldfs = get_fs();                                    \
-     set_fs(seg);                                                       \
-     pagefault_disable();                                               \
-     if (lookup_bad_addr((unsigned long)addr, size))                   \
-      _bad = 1;                                                         \
-     else                                                               \
-      switch (size){                                                   \
-      case 1: __stp_get_user_asm_byte(_v, addr, _bad); break;           \
-      case 2: __stp_get_user_asm_half(_v, addr, _bad); break;           \
-      case 4: __stp_get_user_asm_word(_v, addr, _bad); break;           \
-      default: __get_user_bad(); break;                                 \
-      }                                                                 \
-    pagefault_enable();                                                 \
-    set_fs(_oldfs);                                                     \
-    if (_bad)                                                                  \
-       DEREF_FAULT(addr);                                              \
-     _v;                                                               \
-   })
-
-#define _stp_store_deref(size, addr, value, seg)                        \
-  ({                                                                   \
-    int _bad=0;                                                                \
-    mm_segment_t _oldfs = get_fs();                                           \
-    set_fs(seg);                                                              \
-    pagefault_disable();                                                      \
-    if (lookup_bad_addr((unsigned long)addr, size))                    \
-      _bad = 1;                                                         \
-    else                                                                \
-      switch (size){                                                   \
-      case 1: __stp_put_user_asm_byte(value, addr, _bad); break;       \
-      case 2: __stp_put_user_asm_half(value, addr, _bad); break;       \
-      case 4: __stp_put_user_asm_word(value, addr, _bad); break;       \
-      default: __put_user_bad(); break;                                 \
-      }                                                                 \
-    pagefault_enable();                                                       \
-    set_fs(_oldfs);                                                           \
-    if (_bad)                                                          \
-          STORE_DEREF_FAULT(addr);                                             \
-   })
-
-#elif defined (__s390__) || defined (__s390x__)
-
-/* Use same __get_user() and __put_user() for both user and kernel
-   addresses, but make sure set_fs() is called appropriately first. */
-
-#define _stp_deref(size, addr, seg) ({ \
-    u8 _b; u16 _w; u32 _l; u64 _q; \
-    uintptr_t _a = (uintptr_t) addr; \
-    intptr_t _v = 0; \
-    int _bad = 0; \
-    mm_segment_t _oldfs = get_fs();                                           \
-    set_fs(seg);                                                              \
-    pagefault_disable();                                                      \
-    if (lookup_bad_addr((unsigned long)addr, size))                    \
-      _bad = 1;                                                         \
-    else switch (size) { \
-      case 1: _bad = __get_user(_b, (u8 *)(_a)); _v = _b; break; \
-      case 2: _bad = __get_user(_w, (u16 *)(_a)); _v = _w; break; \
-      case 4: _bad = __get_user(_l, (u32 *)(_a)); _v = _l; break; \
-      case 8: _bad = __get_user(_q, (u64 *)(_a)); _v = _q; break; \
-      default: __get_user_bad(); \
-    } \
-    pagefault_enable();                                                       \
-    set_fs(_oldfs);                                                           \
-    if (_bad) \
-      DEREF_FAULT(addr); \
-    _v; \
-  })
-
-#define _stp_store_deref(size, addr, value, seg) ({ \
-    int _bad = 0; \
-    mm_segment_t _oldfs = get_fs();                                           \
-    set_fs(seg);                                                              \
-    pagefault_disable();                                                      \
-    if (lookup_bad_addr((unsigned long)addr, size))                    \
-      _bad = 1;                                                         \
-    else switch (size) {                                               \
-      case 1: _bad = __put_user(((u8)(value)), ((u8 *)(addr))); break; \
-      case 2: _bad = __put_user(((u16)(value)), ((u16 *)(addr))); break; \
-      case 4: _bad = __put_user(((u32)(value)), ((u32 *)(addr))); break; \
-      case 8: _bad = __put_user(((u64)(value)), ((u64 *)(addr))); break; \
-      default: __put_user_bad(); \
-    } \
-    pagefault_enable();                                                       \
-    set_fs(_oldfs);                                                           \
-    if (_bad) \
-       STORE_DEREF_FAULT(addr); \
-  })
-
-#endif /* (s390) || (s390x) */
-
-
-/* Map kderef/uderef to the generic segment-aware deref macros. */ 
-
-#ifndef kderef
-#define kderef(s,a) _stp_deref(s,a,KERNEL_DS)
-#endif
-
-#ifndef store_kderef
-#define store_kderef(s,a,v) _stp_store_deref(s,a,v,KERNEL_DS)
-#endif
-
-#ifndef uderef
-#define uderef(s,a) _stp_deref(s,a,USER_DS)
-#endif
-
-#ifndef store_uderef
-#define store_uderef(s,a,v) _stp_store_deref(s,a,v,USER_DS)
-#endif
-
-
-
-#if defined (__i386__) || defined (__arm__)
-
-/* x86 and arm can't do 8-byte put/get_user_asm, so we have to split it */
-
-#define __Xread(ptr, Xderef)                           \
-  ((sizeof(*(ptr)) == 8) ?                             \
-       *(typeof(ptr))&(u32[2]) {                       \
-        (u32) Xderef(4, &((u32 *)(ptr))[0]),           \
-        (u32) Xderef(4, &((u32 *)(ptr))[1]) }          \
-     : (typeof(*(ptr))) Xderef(sizeof(*(ptr)), (ptr)))
-
-#define __Xwrite(ptr, value, store_Xderef)                                  \
-  ({                                                                        \
-    if (sizeof(*(ptr)) == 8) {                                              \
-      union { typeof(*(ptr)) v; u32 l[2]; } _kw;                            \
-      _kw.v = (typeof(*(ptr)))(value);                                      \
-      store_Xderef(4, &((u32 *)(ptr))[0], _kw.l[0]);                        \
-      store_Xderef(4, &((u32 *)(ptr))[1], _kw.l[1]);                        \
-    } else                                                                  \
-      store_Xderef(sizeof(*(ptr)), (ptr), (long)(typeof(*(ptr)))(value));     \
-  })
-
-#else
-
-#define __Xread(ptr, Xderef) \
-  ( (typeof(*(ptr))) Xderef(sizeof(*(ptr)), (ptr)) )
-#define __Xwrite(ptr, value, store_Xderef) \
-  ( store_Xderef(sizeof(*(ptr)), (ptr), (long)(typeof(*(ptr)))(value)) )
-
-#endif
-
-#define kread(ptr) __Xread((ptr), kderef)
-#define uread(ptr) __Xread((ptr), uderef)
-
-#define kwrite(ptr, value) __Xwrite((ptr), (value), store_kderef)
-#define uwrite(ptr, value) __Xwrite((ptr), (value), store_uderef)
-
-#endif /* STAPCONF_PROBE_KERNEL */
-
-/* Dereference a kernel buffer ADDR of size MAXBYTES. Put the bytes in
- * address DST (which can be NULL).
- *
- * This function is useful for reading memory when the size isn't a
- * size that kderef() handles.  This function is very similar to
- * kderef_string(), but kderef_buffer() doesn't quit when finding a
- * '\0' byte or append a '\0' byte.
- */
-
-#define kderef_buffer(dst, addr, maxbytes)                                   \
-  ({                                                                         \
-    uintptr_t _addr;                                                         \
-    size_t _len;                                                             \
-    unsigned char _c;                                                        \
-    char *_d = (dst);                                                        \
-    for (_len = (maxbytes), _addr = (uintptr_t)(addr);                       \
-        _len > 1;                                                            \
-        --_len, ++_addr)                                                     \
-      _c = kderef (1, _addr);                                                \
-      if (_d)                                                                \
-        *_d++ = _c;                                                          \
-    (dst);                                                                   \
-  })
-
-/* The following is for kernel strings, see the uconversions.stp
-   tapset for user_string functions. */
-
-#define kderef_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 = kderef (1, _addr)) != '\0';                        \
-        --_len, ++_addr)                                                     \
-      if (_d)                                                                \
-        *_d++ = _c;                                                          \
-    if (_d)                                                                  \
-      *_d = '\0';                                                            \
-    (dst);                                                                   \
-  })
-
-#define store_kderef_string(src, addr, maxbytes)                             \
-  ({                                                                         \
-    uintptr_t _addr;                                                         \
-    size_t _len;                                                             \
-    char *_s = (src);                                                        \
-    for (_len = (maxbytes), _addr = (uintptr_t)(addr);                       \
-        _len > 1 && _s && *_s != '\0'; --_len, ++_addr)                      \
-      store_kderef(1, _addr, *_s++);                                         \
-    store_kderef(1, _addr, '\0');                                            \
-  })
 
-#define CATCH_DEREF_FAULT()                            \
-  if (0) {                                             \
-deref_fault: ;                                         \
-  }
+#endif /* _LOC2C_RUNTIME_H_ */
index c3f4ad9dac55aa3c6f1de4ec02a76cdaa492ef1a..a7848dccfe8049345391c527803c152b07797d85 100644 (file)
@@ -163,7 +163,6 @@ foreach file [lsort [glob -nocomplain $srcdir/$self/*.stp]] {
     # - buildok/iterate_histogram_buckets.stp - no timer probes
     # - buildok/per-process-syscall.stp - process.syscall
     #   probes implementable?
-    # - buildok/pretty-uprobes.stp - needs _stp_strncpy_from_user
     # - buildok/print_histogram_entry.stp - no timer probes
     # - buildok/print_histograms.stp - no timer probes
     # - buildok/printf.stp
This page took 0.07877 seconds and 5 git commands to generate.