Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752299AbbG0Ejp (ORCPT ); Mon, 27 Jul 2015 00:39:45 -0400 Received: from mail-qk0-f180.google.com ([209.85.220.180]:34270 "EHLO mail-qk0-f180.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751998AbbG0Ejl (ORCPT ); Mon, 27 Jul 2015 00:39:41 -0400 From: David Long To: "H. Peter Anvin" , Andy Lutomirski , Anton Blanchard , Behan Webster , Benjamin Herrenschmidt , Eric Paris , Heiko Carstens , Ingo Molnar , Jan Willeke , Kees Cook , Martin Schwidefsky , Michael Ellerman , Nikolay Borisov , Oleg Nesterov , Paul Mackerras , Richard Kuo , Robert Richter , Roland McGrath , Russell King , Tejun Heo , Thomas Gleixner , Will Deacon , linux-arm-kernel@lists.infradead.org, linux-hexagon@vger.kernel.org, linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org, linux-sh@vger.kernel.org, linux390@de.ibm.com, linuxppc-dev@lists.ozlabs.org, x86@kernel.org Subject: [PATCH v2 2/2] Consolidate redundant register/stack access code Date: Mon, 27 Jul 2015 00:39:34 -0400 Message-Id: <1437971974-2434-3-git-send-email-dave.long@linaro.org> X-Mailer: git-send-email 1.8.1.2 In-Reply-To: <1437971974-2434-1-git-send-email-dave.long@linaro.org> References: <1437971974-2434-1-git-send-email-dave.long@linaro.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 23527 Lines: 699 From: "David A. Long" Several architectures have identical or functionally equivalent code implementing parts of the HAVE_REGS_AND_STACK_ACCESS_API feature. Move that code out of the architecture directories. Signed-off-by: David A. Long --- arch/arm/include/asm/ptrace.h | 6 --- arch/arm/kernel/ptrace.c | 67 +-------------------------------- arch/hexagon/include/uapi/asm/ptrace.h | 3 -- arch/powerpc/include/asm/ptrace.h | 38 ------------------- arch/powerpc/kernel/ptrace.c | 34 +---------------- arch/s390/include/asm/ptrace.h | 3 -- arch/s390/kernel/ptrace.c | 69 ++++++++++------------------------ arch/sh/include/asm/ptrace.h | 39 ------------------- arch/sh/kernel/Makefile | 2 +- arch/sh/kernel/ptrace.c | 33 ---------------- arch/sh/kernel/ptrace_32.c | 2 +- arch/sh/kernel/ptrace_64.c | 2 +- arch/x86/include/asm/ptrace.h | 37 ------------------ arch/x86/kernel/ptrace.c | 34 +---------------- include/linux/ptrace.h | 42 +++++++++++++++++++++ kernel/ptrace.c | 38 +++++++++++++++++++ 16 files changed, 106 insertions(+), 343 deletions(-) delete mode 100644 arch/sh/kernel/ptrace.c diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index 51622ba..84a0ea4 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h @@ -120,12 +120,6 @@ extern unsigned long profile_pc(struct pt_regs *regs); #include #define MAX_REG_OFFSET (offsetof(struct pt_regs, ARM_ORIG_r0)) -extern int regs_query_register_offset(const char *name); -extern const char *regs_query_register_name(unsigned int offset); -extern bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr); -extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, - unsigned int n); - /** * regs_get_register() - get register value from its offset * @regs: pt_regs from which register value is gotten diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 3b5a2ba..f26e23b 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -63,7 +63,7 @@ #define REG_OFFSET_NAME(r) \ {.name = #r, .offset = offsetof(struct pt_regs, ARM_##r)} -static const struct pt_regs_offset regoffset_table[] = { +const struct pt_regs_offset regs_offset_table[] = { REG_OFFSET_NAME(r0), REG_OFFSET_NAME(r1), REG_OFFSET_NAME(r2), @@ -85,71 +85,6 @@ static const struct pt_regs_offset regoffset_table[] = { REGS_OFFSET_END, }; -/** - * regs_query_register_offset() - query register offset from its name - * @name: the name of a register - * - * regs_query_register_offset() returns the offset of a register in struct - * pt_regs from its name. If the name is invalid, this returns -EINVAL; - */ -int regs_query_register_offset(const char *name) -{ - const struct pt_regs_offset *roff; - for (roff = regoffset_table; roff->name != NULL; roff++) - if (!strcmp(roff->name, name)) - return roff->offset; - return -EINVAL; -} - -/** - * regs_query_register_name() - query register name from its offset - * @offset: the offset of a register in struct pt_regs. - * - * regs_query_register_name() returns the name of a register from its - * offset in struct pt_regs. If the @offset is invalid, this returns NULL; - */ -const char *regs_query_register_name(unsigned int offset) -{ - const struct pt_regs_offset *roff; - for (roff = regoffset_table; roff->name != NULL; roff++) - if (roff->offset == offset) - return roff->name; - return NULL; -} - -/** - * regs_within_kernel_stack() - check the address in the stack - * @regs: pt_regs which contains kernel stack pointer. - * @addr: address which is checked. - * - * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). - * If @addr is within the kernel stack, it returns true. If not, returns false. - */ -bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) -{ - return ((addr & ~(THREAD_SIZE - 1)) == - (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))); -} - -/** - * regs_get_kernel_stack_nth() - get Nth entry of the stack - * @regs: pt_regs which contains kernel stack pointer. - * @n: stack entry number. - * - * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which - * is specified by @regs. If the @n th entry is NOT in the kernel stack, - * this returns 0. - */ -unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) -{ - unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); - addr += n; - if (regs_within_kernel_stack(regs, (unsigned long)addr)) - return *addr; - else - return 0; -} - /* * this routine will get a word off of the processes privileged stack. * the offset is how far from the base addr as stored in the THREAD. diff --git a/arch/hexagon/include/uapi/asm/ptrace.h b/arch/hexagon/include/uapi/asm/ptrace.h index 065e5b3..0afb664 100644 --- a/arch/hexagon/include/uapi/asm/ptrace.h +++ b/arch/hexagon/include/uapi/asm/ptrace.h @@ -29,9 +29,6 @@ #define profile_pc(regs) instruction_pointer(regs) /* kprobe-based event tracer support */ -extern int regs_query_register_offset(const char *name); -extern const char *regs_query_register_name(unsigned int offset); - #define current_pt_regs() \ ((struct pt_regs *) \ ((unsigned long)current_thread_info() + THREAD_SIZE) - 1) diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h index c0c61fa..64b9b3d 100644 --- a/arch/powerpc/include/asm/ptrace.h +++ b/arch/powerpc/include/asm/ptrace.h @@ -156,8 +156,6 @@ do { \ #include #include -extern int regs_query_register_offset(const char *name); -extern const char *regs_query_register_name(unsigned int offset); #define MAX_REG_OFFSET (offsetof(struct pt_regs, dsisr)) /** @@ -177,42 +175,6 @@ static inline unsigned long regs_get_register(struct pt_regs *regs, return *(unsigned long *)((unsigned long)regs + offset); } -/** - * regs_within_kernel_stack() - check the address in the stack - * @regs: pt_regs which contains kernel stack pointer. - * @addr: address which is checked. - * - * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). - * If @addr is within the kernel stack, it returns true. If not, returns false. - */ - -static inline bool regs_within_kernel_stack(struct pt_regs *regs, - unsigned long addr) -{ - return ((addr & ~(THREAD_SIZE - 1)) == - (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))); -} - -/** - * regs_get_kernel_stack_nth() - get Nth entry of the stack - * @regs: pt_regs which contains kernel stack pointer. - * @n: stack entry number. - * - * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which - * is specified by @regs. If the @n th entry is NOT in the kernel stack, - * this returns 0. - */ -static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, - unsigned int n) -{ - unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); - addr += n; - if (regs_within_kernel_stack(regs, (unsigned long)addr)) - return *addr; - else - return 0; -} - #endif /* __ASSEMBLY__ */ #ifndef __powerpc64__ diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index b8f054c..47d28f4 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -56,7 +56,7 @@ #define GPR_OFFSET_NAME(num) \ {.name = STR(gpr##num), .offset = offsetof(struct pt_regs, gpr[num])} -static const struct pt_regs_offset regoffset_table[] = { +const struct pt_regs_offset regs_offset_table[] = { GPR_OFFSET_NAME(0), GPR_OFFSET_NAME(1), GPR_OFFSET_NAME(2), @@ -106,38 +106,6 @@ static const struct pt_regs_offset regoffset_table[] = { REGS_OFFSET_END, }; -/** - * regs_query_register_offset() - query register offset from its name - * @name: the name of a register - * - * regs_query_register_offset() returns the offset of a register in struct - * pt_regs from its name. If the name is invalid, this returns -EINVAL; - */ -int regs_query_register_offset(const char *name) -{ - const struct pt_regs_offset *roff; - for (roff = regoffset_table; roff->name != NULL; roff++) - if (!strcmp(roff->name, name)) - return roff->offset; - return -EINVAL; -} - -/** - * regs_query_register_name() - query register name from its offset - * @offset: the offset of a register in struct pt_regs. - * - * regs_query_register_name() returns the name of a register from its - * offset in struct pt_regs. If the @offset is invalid, this returns NULL; - */ -const char *regs_query_register_name(unsigned int offset) -{ - const struct pt_regs_offset *roff; - for (roff = regoffset_table; roff->name != NULL; roff++) - if (roff->offset == offset) - return roff->name; - return NULL; -} - /* * does not yet catch signals sent when the child dies. * in exit.c or in signal.c. diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index 6feda25..d4f9ad3 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h @@ -163,10 +163,7 @@ static inline void instruction_pointer_set(struct pt_regs *regs, regs->psw.addr = val | PSW_ADDR_AMODE; } -int regs_query_register_offset(const char *name); -const char *regs_query_register_name(unsigned int offset); unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset); -unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n); static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) { diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index d363c9c..54d1ec3 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -1474,9 +1474,26 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) return &user_s390_view; } -static const char *gpr_names[NUM_GPRS] = { - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", +#define REG_OFFSET_NAME(r) {.name = "r" #r, .offset = r} + +const struct pt_regs_offset regs_offset_table[NUM_GPRS+1] = { + REG_OFFSET_NAME(0), + REG_OFFSET_NAME(1), + REG_OFFSET_NAME(2), + REG_OFFSET_NAME(3), + REG_OFFSET_NAME(4), + REG_OFFSET_NAME(5), + REG_OFFSET_NAME(6), + REG_OFFSET_NAME(7), + REG_OFFSET_NAME(8), + REG_OFFSET_NAME(9), + REG_OFFSET_NAME(10), + REG_OFFSET_NAME(11), + REG_OFFSET_NAME(12), + REG_OFFSET_NAME(13), + REG_OFFSET_NAME(14), + REG_OFFSET_NAME(15), + REGS_OFFSET_END }; unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset) @@ -1485,49 +1502,3 @@ unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset) return 0; return regs->gprs[offset]; } - -int regs_query_register_offset(const char *name) -{ - unsigned long offset; - - if (!name || *name != 'r') - return -EINVAL; - if (kstrtoul(name + 1, 10, &offset)) - return -EINVAL; - if (offset >= NUM_GPRS) - return -EINVAL; - return offset; -} - -const char *regs_query_register_name(unsigned int offset) -{ - if (offset >= NUM_GPRS) - return NULL; - return gpr_names[offset]; -} - -static int regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) -{ - unsigned long ksp = kernel_stack_pointer(regs); - - return (addr & ~(THREAD_SIZE - 1)) == (ksp & ~(THREAD_SIZE - 1)); -} - -/** - * regs_get_kernel_stack_nth() - get Nth entry of the stack - * @regs:pt_regs which contains kernel stack pointer. - * @n:stack entry number. - * - * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which - * is specifined by @regs. If the @n th entry is NOT in the kernel stack, - * this returns 0. - */ -unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) -{ - unsigned long addr; - - addr = kernel_stack_pointer(regs) + n * sizeof(long); - if (!regs_within_kernel_stack(regs, addr)) - return 0; - return *(unsigned long *)addr; -} diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h index 523955f..8045eb4 100644 --- a/arch/sh/include/asm/ptrace.h +++ b/arch/sh/include/asm/ptrace.h @@ -29,10 +29,6 @@ {.name = __stringify(tr##num), .offset = offsetof(struct pt_regs, tregs[num])} /* Query offset/name of register from its name/offset */ -extern int regs_query_register_offset(const char *name); -extern const char *regs_query_register_name(unsigned int offset); - -extern const struct pt_regs_offset regoffset_table[]; /** * regs_get_register() - get register value from its offset @@ -51,41 +47,6 @@ static inline unsigned long regs_get_register(struct pt_regs *regs, return *(unsigned long *)((unsigned long)regs + offset); } -/** - * regs_within_kernel_stack() - check the address in the stack - * @regs: pt_regs which contains kernel stack pointer. - * @addr: address which is checked. - * - * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). - * If @addr is within the kernel stack, it returns true. If not, returns false. - */ -static inline int regs_within_kernel_stack(struct pt_regs *regs, - unsigned long addr) -{ - return ((addr & ~(THREAD_SIZE - 1)) == - (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))); -} - -/** - * regs_get_kernel_stack_nth() - get Nth entry of the stack - * @regs: pt_regs which contains kernel stack pointer. - * @n: stack entry number. - * - * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which - * is specified by @regs. If the @n th entry is NOT in the kernel stack, - * this returns 0. - */ -static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, - unsigned int n) -{ - unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); - addr += n; - if (regs_within_kernel_stack(regs, (unsigned long)addr)) - return *addr; - else - return 0; -} - struct perf_event; struct perf_sample_data; diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 2ccf36c..4ae9a11 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -14,7 +14,7 @@ CFLAGS_REMOVE_return_address.o = -pg obj-y := debugtraps.o dma-nommu.o dumpstack.o \ idle.o io.o irq.o irq_$(BITS).o kdebugfs.o \ machvec.o nmi_debug.o process.o \ - process_$(BITS).o ptrace.o ptrace_$(BITS).o \ + process_$(BITS).o ptrace_$(BITS).o \ reboot.o return_address.o \ setup.o signal_$(BITS).o sys_sh.o \ syscalls_$(BITS).o time.o topology.o traps.o \ diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c deleted file mode 100644 index 0a05983..0000000 --- a/arch/sh/kernel/ptrace.c +++ /dev/null @@ -1,33 +0,0 @@ -#include - -/** - * regs_query_register_offset() - query register offset from its name - * @name: the name of a register - * - * regs_query_register_offset() returns the offset of a register in struct - * pt_regs from its name. If the name is invalid, this returns -EINVAL; - */ -int regs_query_register_offset(const char *name) -{ - const struct pt_regs_offset *roff; - for (roff = regoffset_table; roff->name != NULL; roff++) - if (!strcmp(roff->name, name)) - return roff->offset; - return -EINVAL; -} - -/** - * regs_query_register_name() - query register name from its offset - * @offset: the offset of a register in struct pt_regs. - * - * regs_query_register_name() returns the name of a register from its - * offset in struct pt_regs. If the @offset is invalid, this returns NULL; - */ -const char *regs_query_register_name(unsigned int offset) -{ - const struct pt_regs_offset *roff; - for (roff = regoffset_table; roff->name != NULL; roff++) - if (roff->offset == offset) - return roff->name; - return NULL; -} diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c index e6fe4f4..c5c385c 100644 --- a/arch/sh/kernel/ptrace_32.c +++ b/arch/sh/kernel/ptrace_32.c @@ -276,7 +276,7 @@ static int dspregs_active(struct task_struct *target, } #endif -const struct pt_regs_offset regoffset_table[] = { +const struct pt_regs_offset regs_offset_table[] = { REG_OFFSET_NAME(0), REG_OFFSET_NAME(1), REG_OFFSET_NAME(2), diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c index af55bb6..565227ef 100644 --- a/arch/sh/kernel/ptrace_64.c +++ b/arch/sh/kernel/ptrace_64.c @@ -252,7 +252,7 @@ static int fpregs_active(struct task_struct *target, } #endif -const struct pt_regs_offset regoffset_table[] = { +const struct pt_regs_offset regs_offset_table[] = { REGS_OFFSET_NAME(pc), REGS_OFFSET_NAME(sr), REGS_OFFSET_NAME(syscall_nr), diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index 5fabf13..c01247c 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h @@ -157,8 +157,6 @@ static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) #include /* Query offset/name of register from its name/offset */ -extern int regs_query_register_offset(const char *name); -extern const char *regs_query_register_name(unsigned int offset); #define MAX_REG_OFFSET (offsetof(struct pt_regs, ss)) /** @@ -187,41 +185,6 @@ static inline unsigned long regs_get_register(struct pt_regs *regs, return *(unsigned long *)((unsigned long)regs + offset); } -/** - * regs_within_kernel_stack() - check the address in the stack - * @regs: pt_regs which contains kernel stack pointer. - * @addr: address which is checked. - * - * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). - * If @addr is within the kernel stack, it returns true. If not, returns false. - */ -static inline int regs_within_kernel_stack(struct pt_regs *regs, - unsigned long addr) -{ - return ((addr & ~(THREAD_SIZE - 1)) == - (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))); -} - -/** - * regs_get_kernel_stack_nth() - get Nth entry of the stack - * @regs: pt_regs which contains kernel stack pointer. - * @n: stack entry number. - * - * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which - * is specified by @regs. If the @n th entry is NOT in the kernel stack, - * this returns 0. - */ -static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, - unsigned int n) -{ - unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); - addr += n; - if (regs_within_kernel_stack(regs, (unsigned long)addr)) - return *addr; - else - return 0; -} - #define arch_has_single_step() (1) #ifdef CONFIG_X86_DEBUGCTLMSR #define arch_has_block_step() (1) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 2efc6aa..0ddabd5 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -54,7 +54,7 @@ enum x86_regset { }; -static const struct pt_regs_offset regoffset_table[] = { +const struct pt_regs_offset regs_offset_table[] = { #ifdef CONFIG_X86_64 REGS_OFFSET_NAME(r15), REGS_OFFSET_NAME(r14), @@ -87,38 +87,6 @@ static const struct pt_regs_offset regoffset_table[] = { REGS_OFFSET_END, }; -/** - * regs_query_register_offset() - query register offset from its name - * @name: the name of a register - * - * regs_query_register_offset() returns the offset of a register in struct - * pt_regs from its name. If the name is invalid, this returns -EINVAL; - */ -int regs_query_register_offset(const char *name) -{ - const struct pt_regs_offset *roff; - for (roff = regoffset_table; roff->name != NULL; roff++) - if (!strcmp(roff->name, name)) - return roff->offset; - return -EINVAL; -} - -/** - * regs_query_register_name() - query register name from its offset - * @offset: the offset of a register in struct pt_regs. - * - * regs_query_register_name() returns the name of a register from its - * offset in struct pt_regs. If the @offset is invalid, this returns NULL; - */ -const char *regs_query_register_name(unsigned int offset) -{ - const struct pt_regs_offset *roff; - for (roff = regoffset_table; roff->name != NULL; roff++) - if (roff->offset == offset) - return roff->name; - return NULL; -} - static const int arg_offs_table[] = { #ifdef CONFIG_X86_32 [0] = offsetof(struct pt_regs, ax), diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index dbb8df1..f3afbf8 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -393,6 +393,48 @@ struct pt_regs_offset { int offset; }; +extern const struct pt_regs_offset regs_offset_table[]; + +extern int regs_query_register_offset(const char *name); +extern const char *regs_query_register_name(unsigned int offset); + +/** + * regs_within_kernel_stack() - check the address in the stack + * @regs: pt_regs which contains kernel stack pointer. + * @addr: address which is checked. + * + * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). + * If @addr is within the kernel stack, it returns true. If not, returns false. + */ + +static inline bool regs_within_kernel_stack(struct pt_regs *regs, + unsigned long addr) +{ + return ((addr & ~(THREAD_SIZE - 1)) == + (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))); +} + +/** + * regs_get_kernel_stack_nth() - get Nth entry of the stack + * @regs: pt_regs which contains kernel stack pointer. + * @n: stack entry number. + * + * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which + * is specified by @regs. If the @n th entry is NOT in the kernel stack, + * this returns 0. + */ +static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, + unsigned int n) +{ + unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); + + addr += n; + if (regs_within_kernel_stack(regs, (unsigned long)addr)) + return *addr; + else + return 0; +} + #endif /* CONFIG_HAVE_REGS_AND_STACK_ACCESS_API */ #endif diff --git a/kernel/ptrace.c b/kernel/ptrace.c index c8e0e05..20c08d9 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -1217,3 +1217,41 @@ COMPAT_SYSCALL_DEFINE4(ptrace, compat_long_t, request, compat_long_t, pid, return ret; } #endif /* CONFIG_COMPAT */ + +#ifdef CONFIG_HAVE_REGS_AND_STACK_ACCESS_API + +/** + * regs_query_register_offset() - query register offset from its name + * @name: the name of a register + * + * regs_query_register_offset() returns the offset of a register in struct + * pt_regs from its name. If the name is invalid, this returns -EINVAL; + */ +int regs_query_register_offset(const char *name) +{ + const struct pt_regs_offset *roff; + + for (roff = regs_offset_table; roff->name != NULL; roff++) + if (!strcmp(roff->name, name)) + return roff->offset; + return -EINVAL; +} + +/** + * regs_query_register_name() - query register name from its offset + * @offset: the offset of a register in struct pt_regs. + * + * regs_query_register_name() returns the name of a register from its + * offset in struct pt_regs. If the @offset is invalid, this returns NULL; + */ +const char *regs_query_register_name(unsigned int offset) +{ + const struct pt_regs_offset *roff; + + for (roff = regs_offset_table; roff->name != NULL; roff++) + if (roff->offset == offset) + return roff->name; + return NULL; +} + +#endif /* CONFIG_HAVE_REGS_AND_STACK_ACCESS_API */ -- 1.8.1.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/