[PATCH v2 2/2] Consolidate redundant register/stack access code
From: David Long <hidden>
Date: 2015-07-27 04:39:45
Also in:
linux-arm-kernel, linux-sh, lkml
Subsystem:
arm port, linux for powerpc (32-bit and 64-bit), ptrace support, qualcomm hexagon architecture, s390 architecture, superh, the rest, x86 architecture (32-bit and 64-bit) · Maintainers:
Russell King, Madhavan Srinivasan, Michael Ellerman, Oleg Nesterov, Brian Cain, Heiko Carstens, Vasily Gorbik, Alexander Gordeev, Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz, Linus Torvalds, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen
From: "David A. Long" <redacted> 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 <redacted> --- 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 <linux/types.h> #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 <linux/stddef.h> #include <linux/thread_info.h> -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 <linux/ptrace.h> - -/** - * 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 <asm-generic/ptrace.h> /* 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