diff options
author | Frank Ch. Eigler <fche@elastic.org> | 2009-12-18 12:20:52 -0500 |
---|---|---|
committer | Frank Ch. Eigler <fche@elastic.org> | 2009-12-20 12:17:07 -0500 |
commit | b5a0dd413a3e4f521df7febca6b88f0ec6b9ff36 (patch) | |
tree | 820343aaf1d99099a2fd94070359c1b503c2f04f /runtime/loc2c-runtime.h | |
parent | a5a674fa2c2447e9dd34c8c8f7b1e5756a32df4d (diff) | |
download | systemtap-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/loc2c-runtime.h')
-rw-r--r-- | runtime/loc2c-runtime.h | 385 |
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) ®s->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) ®s->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)®s->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)®s->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; \ |