summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2009-12-18 12:20:52 -0500
committerFrank Ch. Eigler <fche@elastic.org>2009-12-20 12:17:07 -0500
commitb5a0dd413a3e4f521df7febca6b88f0ec6b9ff36 (patch)
tree820343aaf1d99099a2fd94070359c1b503c2f04f /runtime
parenta5a674fa2c2447e9dd34c8c8f7b1e5756a32df4d (diff)
downloadsystemtap-steved-b5a0dd413a3e4f521df7febca6b88f0ec6b9ff36.tar.gz
systemtap-steved-b5a0dd413a3e4f521df7febca6b88f0ec6b9ff36.tar.xz
systemtap-steved-b5a0dd413a3e4f521df7febca6b88f0ec6b9ff36.zip
PR10601 part 1: i386 and x86-64 regset for dwarf fetch/store_register()s
* runtime/loc2c-runtime.h (fetch_register, store_register): forked into k_ (kernel) and u_ (user) varieties. Implement i386 and x86_64 in terms of regset.h; fall back to k_* for other architectures. * tapsets.cxx: (*::visit_target_symbol): Emit macros to map loc2c's fetch/store_register to loc2c-runtime's k_ or u_ as appopriate.
Diffstat (limited to 'runtime')
-rw-r--r--runtime/loc2c-runtime.h385
1 files changed, 300 insertions, 85 deletions
diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h
index e9e5a071..d23df7f2 100644
--- a/runtime/loc2c-runtime.h
+++ b/runtime/loc2c-runtime.h
@@ -1,5 +1,5 @@
/* target operations
- * Copyright (C) 2005 Red Hat Inc.
+ * Copyright (C) 2005-2009 Red Hat Inc.
* Copyright (C) 2005, 2006, 2007 Intel Corporation.
* Copyright (C) 2007 Quentin Barnes.
*
@@ -44,10 +44,10 @@
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 fetch_register(regno) \
- ((intptr_t) dwarf_register_##regno (c->regs))
-#define store_register(regno, value) \
- (dwarf_register_##regno (c->regs) = (value))
+#define k_fetch_register(regno) \
+ ((intptr_t) k_dwarf_register_##regno (c->regs))
+#define k_store_register(regno, value) \
+ (k_dwarf_register_##regno (c->regs) = (value))
/* The deref and store_deref macros are called to safely access addresses
@@ -82,35 +82,242 @@
})
#endif
+
+/* PR 10601: user-space (user_regset) register access. Needs porting to each architecture. */
+#include <linux/regset.h>
+
+struct usr_regset_lut {
+ char *name;
+ unsigned rsn;
+ unsigned pos;
+};
+
+/* DWARF register number -to- user_regset offset/bank mapping table. */
+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 },
+ { "di", NT_PRSTATUS, 4*4 },
+ { "si", NT_PRSTATUS, 3*4 },
+};
+
+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 },
+};
+
+
+
+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;
+}
+
+
+#define S(array) sizeof(array)/sizeof(array[0])
+#if defined (__i386__)
+
+#define u_fetch_register(regno) ursl_fetch32(url_i386, S(url_i386), EM_386, regno)
+#define u_store_register(regno,value) ursl_store32(url_i386, S(url_i386), EM_386, regno, value)
+
+#elif defined (__x86_64__)
+
+#define u_fetch_register(regno) (_stp_probing_32bit_app(c->regs) ? ursl_fetch32(url_i386, S(url_i386), EM_386, regno) : ursl_fetch64(url_x86_64, S(url_x86_64), EM_X86_64, regno))
+#define u_store_register(regno,value) (_stp_probing_32bit_app(c->regs) ? ursl_store2(url_i386, S(url_i386), EM_386, regno, value) : ursl_store64(url_x86_64, S(url_x86_64), EM_X86_64, regno, value))
+
+#else
+
+#error "no can do"
+
+/* Some other architecture; downgrade to kernel register access. */
+#define u_fetch_register(regno) k_fetch_register(regno)
+#define u_store_register(regno,value) k_store_register(regno,value)
+
+#endif
+
+
+
#if defined (STAPCONF_X86_UNIREGS) && defined (__i386__)
-#define dwarf_register_0(regs) regs->ax
-#define dwarf_register_1(regs) regs->cx
-#define dwarf_register_2(regs) regs->dx
-#define dwarf_register_3(regs) regs->bx
-#define dwarf_register_4(regs) ((long) &regs->sp)
-#define dwarf_register_5(regs) regs->bp
-#define dwarf_register_6(regs) regs->si
-#define dwarf_register_7(regs) regs->di
+#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
#elif defined (STAPCONF_X86_UNIREGS) && defined (__x86_64__)
-#define dwarf_register_0(regs) regs->ax
-#define dwarf_register_1(regs) regs->dx
-#define dwarf_register_2(regs) regs->cx
-#define dwarf_register_3(regs) regs->bx
-#define dwarf_register_4(regs) regs->si
-#define dwarf_register_5(regs) regs->di
-#define dwarf_register_6(regs) regs->bp
-#define dwarf_register_7(regs) regs->sp
-#define dwarf_register_8(regs) regs->r8
-#define dwarf_register_9(regs) regs->r9
-#define dwarf_register_10(regs) regs->r10
-#define dwarf_register_11(regs) regs->r11
-#define dwarf_register_12(regs) regs->r12
-#define dwarf_register_13(regs) regs->r13
-#define dwarf_register_14(regs) regs->r14
-#define dwarf_register_15(regs) regs->r15
+#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
#elif defined __i386__
@@ -120,60 +327,60 @@
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 dwarf_register_0(regs) regs->eax
-#define dwarf_register_1(regs) regs->ecx
-#define dwarf_register_2(regs) regs->edx
-#define dwarf_register_3(regs) regs->ebx
-#define dwarf_register_4(regs) (user_mode(regs) ? regs->esp : (long)&regs->esp)
-#define dwarf_register_5(regs) regs->ebp
-#define dwarf_register_6(regs) regs->esi
-#define dwarf_register_7(regs) regs->edi
+#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
#elif defined __ia64__
-#undef fetch_register
-#undef store_register
+#undef k_fetch_register
+#undef k_store_register
-#define fetch_register(regno) ia64_fetch_register(regno, c->regs, &c->unwaddr)
-#define store_register(regno,value) ia64_store_register(regno, c->regs, value)
+#define k_fetch_register(regno) ia64_fetch_register(regno, c->regs, &c->unwaddr)
+#define k_store_register(regno,value) ia64_store_register(regno, c->regs, value)
#elif defined __x86_64__
-#define dwarf_register_0(regs) regs->rax
-#define dwarf_register_1(regs) regs->rdx
-#define dwarf_register_2(regs) regs->rcx
-#define dwarf_register_3(regs) regs->rbx
-#define dwarf_register_4(regs) regs->rsi
-#define dwarf_register_5(regs) regs->rdi
-#define dwarf_register_6(regs) regs->rbp
-#define dwarf_register_7(regs) regs->rsp
-#define dwarf_register_8(regs) regs->r8
-#define dwarf_register_9(regs) regs->r9
-#define dwarf_register_10(regs) regs->r10
-#define dwarf_register_11(regs) regs->r11
-#define dwarf_register_12(regs) regs->r12
-#define dwarf_register_13(regs) regs->r13
-#define dwarf_register_14(regs) regs->r14
-#define dwarf_register_15(regs) regs->r15
+#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
#elif defined __powerpc__
-#undef fetch_register
-#undef store_register
-#define fetch_register(regno) ((intptr_t) c->regs->gpr[regno])
-#define store_register(regno,value) (c->regs->gpr[regno] = (value))
+#undef k_fetch_register
+#undef k_store_register
+#define k_fetch_register(regno) ((intptr_t) c->regs->gpr[regno])
+#define k_store_register(regno,value) (c->regs->gpr[regno] = (value))
#elif defined (__arm__)
-#undef fetch_register
-#undef store_register
-#define fetch_register(regno) ((long) c->regs->uregs[regno])
-#define store_register(regno,value) (c->regs->uregs[regno] = (value))
+#undef k_fetch_register
+#undef k_store_register
+#define k_fetch_register(regno) ((long) c->regs->uregs[regno])
+#define k_store_register(regno,value) (c->regs->uregs[regno] = (value))
#elif defined (__s390__) || defined (__s390x__)
-#undef fetch_register
-#undef store_register
-#define fetch_register(regno) ((intptr_t) c->regs->gprs[regno])
-#define store_register(regno,value) (c->regs->gprs[regno] = (value))
+#undef k_fetch_register
+#undef k_store_register
+#define k_fetch_register(regno) ((intptr_t) c->regs->gprs[regno])
+#define k_store_register(regno,value) (c->regs->gprs[regno] = (value))
#endif
@@ -206,7 +413,7 @@
STORE_DEREF_FAULT(ptr); \
})
-#define deref(size, addr) ({ \
+#define k_deref(size, addr) ({ \
intptr_t _i = 0; \
switch (size) { \
case 1: _i = kread((u8 *)(addr)); break; \
@@ -218,7 +425,7 @@
_i; \
})
-#define store_deref(size, addr, value) ({ \
+#define k_store_deref(size, addr, value) ({ \
switch (size) { \
case 1: kwrite((u8 *)(addr), (value)); break; \
case 2: kwrite((u16 *)(addr), (value)); break; \
@@ -228,6 +435,7 @@
} \
})
+
extern void __deref_bad(void);
extern void __store_deref_bad(void);
@@ -235,7 +443,7 @@ extern void __store_deref_bad(void);
#if defined __i386__
-#define deref(size, addr) \
+#define k_deref(size, addr) \
({ \
int _bad = 0; \
u8 _b; u16 _w; u32 _l; \
@@ -255,7 +463,7 @@ extern void __store_deref_bad(void);
_v; \
})
-#define store_deref(size, addr, value) \
+#define k_store_deref(size, addr, value) \
({ \
int _bad = 0; \
if (lookup_bad_addr((unsigned long)addr, size)) \
@@ -275,7 +483,7 @@ extern void __store_deref_bad(void);
#elif defined __x86_64__
-#define deref(size, addr) \
+#define k_deref(size, addr) \
({ \
int _bad = 0; \
u8 _b; u16 _w; u32 _l; u64 _q; \
@@ -296,7 +504,7 @@ extern void __store_deref_bad(void);
_v; \
})
-#define store_deref(size, addr, value) \
+#define k_store_deref(size, addr, value) \
({ \
int _bad = 0; \
if (lookup_bad_addr((unsigned long)addr, size)) \
@@ -315,7 +523,7 @@ extern void __store_deref_bad(void);
})
#elif defined __ia64__
-#define deref(size, addr) \
+#define k_deref(size, addr) \
({ \
int _bad = 0; \
intptr_t _v=0; \
@@ -334,7 +542,7 @@ extern void __store_deref_bad(void);
_v; \
})
-#define store_deref(size, addr, value) \
+#define k_store_deref(size, addr, value) \
({ \
int _bad=0; \
if (lookup_bad_addr((unsigned long)addr, size)) \
@@ -393,7 +601,7 @@ extern void __store_deref_bad(void);
"i"(sizeof(unsigned long)))
-#define deref(size, addr) \
+#define k_deref(size, addr) \
({ \
int _bad = 0; \
intptr_t _v = 0; \
@@ -413,7 +621,7 @@ extern void __store_deref_bad(void);
_v; \
})
-#define store_deref(size, addr, value) \
+#define k_store_deref(size, addr, value) \
({ \
int _bad = 0; \
if (lookup_bad_addr((unsigned long)addr, size)) \
@@ -567,7 +775,7 @@ extern void __store_deref_bad(void);
: "r" (x), "i" (-EFAULT) \
: "cc")
-#define deref(size, addr) \
+#define k_deref(size, addr) \
({ \
int _bad = 0; \
intptr_t _v=0; \
@@ -585,7 +793,7 @@ extern void __store_deref_bad(void);
_v; \
})
-#define store_deref(size, addr, value) \
+#define k_store_deref(size, addr, value) \
({ \
int _bad=0; \
if (lookup_bad_addr((unsigned long)addr, size)) \
@@ -655,7 +863,7 @@ extern void __store_deref_bad(void);
: "cc"); \
})
-#define deref(size, addr) \
+#define k_deref(size, addr) \
({ \
u8 _b; u16 _w; u32 _l; u64 _q; \
int _bad = 0; \
@@ -692,7 +900,7 @@ extern void __store_deref_bad(void);
_v; \
})
-#define store_deref(size, addr, value) \
+#define k_store_deref(size, addr, value) \
({ \
int _bad = 0; \
int i; \
@@ -738,14 +946,21 @@ extern void __store_deref_bad(void);
#else
#define kread(ptr) \
- ( (typeof(*(ptr))) deref(sizeof(*(ptr)), (ptr)) )
+ ( (typeof(*(ptr))) k_deref(sizeof(*(ptr)), (ptr)) )
#define kwrite(ptr, value) \
- ( store_deref(sizeof(*(ptr)), (ptr), (long)(typeof(*(ptr)))(value)) )
+ ( k_store_deref(sizeof(*(ptr)), (ptr), (long)(typeof(*(ptr)))(value)) )
#endif
#endif /* STAPCONF_PROBE_KERNEL */
+/* XXX: PR10601 */
+/* Perhaps this should use something like set_fs(USER_DS); k_deref() ; set_fs(KERNEL_DS)
+ * But then again, the addr_map protections do that already. */
+#define u_deref(a,b) k_deref(a,b)
+#define u_store_deref(a,b,c) k_store_deref(a,b,c)
+
+
#define deref_string(dst, addr, maxbytes) \
({ \
uintptr_t _addr; \