[1/3] ptrace: Introduce exception_ip arch hook
Commit Message
On architectures with delay slot, architecture level instruction
pointer (or program counter) in pt_regs may differ from where
exception was triggered.
Introduce exception_ip hook to invoke architecture code and determine
actual instruction pointer to the exception.
Link: https://lore.kernel.org/lkml/00d1b813-c55f-4365-8d81-d70258e10b16@app.fastmail.com/
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
arch/alpha/include/asm/ptrace.h | 1 +
arch/arc/include/asm/ptrace.h | 1 +
arch/arm/include/asm/ptrace.h | 1 +
arch/csky/include/asm/ptrace.h | 1 +
arch/hexagon/include/uapi/asm/ptrace.h | 1 +
arch/loongarch/include/asm/ptrace.h | 1 +
arch/m68k/include/asm/ptrace.h | 1 +
arch/microblaze/include/asm/ptrace.h | 3 ++-
arch/mips/include/asm/ptrace.h | 1 +
arch/mips/kernel/ptrace.c | 7 +++++++
arch/nios2/include/asm/ptrace.h | 3 ++-
arch/openrisc/include/asm/ptrace.h | 1 +
arch/parisc/include/asm/ptrace.h | 1 +
arch/s390/include/asm/ptrace.h | 1 +
arch/sparc/include/asm/ptrace.h | 2 ++
arch/um/include/asm/ptrace-generic.h | 1 +
16 files changed, 25 insertions(+), 2 deletions(-)
Comments
On Thu, 2024-02-01 at 15:46 +0000, Jiaxun Yang wrote:
> On architectures with delay slot, architecture level instruction
> pointer (or program counter) in pt_regs may differ from where
> exception was triggered.
>
> Introduce exception_ip hook to invoke architecture code and determine
> actual instruction pointer to the exception.
>
> Link:
> https://lore.kernel.org/lkml/00d1b813-c55f-4365-8d81-d70258e10b16@app.fastmail.com/
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
How about adding something like
#ifndef arch_exception_ip
#define exception_ip(regs) instruction_pointer(regs)
#else
#define exception_ip(regs) arch_exception_ip(regs)
#endif
into a generic header, instead of having to add exception_ip definition
everywhere?
> ---
> arch/alpha/include/asm/ptrace.h | 1 +
> arch/arc/include/asm/ptrace.h | 1 +
> arch/arm/include/asm/ptrace.h | 1 +
> arch/csky/include/asm/ptrace.h | 1 +
> arch/hexagon/include/uapi/asm/ptrace.h | 1 +
> arch/loongarch/include/asm/ptrace.h | 1 +
> arch/m68k/include/asm/ptrace.h | 1 +
> arch/microblaze/include/asm/ptrace.h | 3 ++-
> arch/mips/include/asm/ptrace.h | 1 +
> arch/mips/kernel/ptrace.c | 7 +++++++
> arch/nios2/include/asm/ptrace.h | 3 ++-
> arch/openrisc/include/asm/ptrace.h | 1 +
> arch/parisc/include/asm/ptrace.h | 1 +
> arch/s390/include/asm/ptrace.h | 1 +
> arch/sparc/include/asm/ptrace.h | 2 ++
> arch/um/include/asm/ptrace-generic.h | 1 +
> 16 files changed, 25 insertions(+), 2 deletions(-)
>
> diff --git a/arch/alpha/include/asm/ptrace.h
> b/arch/alpha/include/asm/ptrace.h
> index 3557ce64ed21..1ded3f2d09e9 100644
> --- a/arch/alpha/include/asm/ptrace.h
> +++ b/arch/alpha/include/asm/ptrace.h
> @@ -8,6 +8,7 @@
> #define arch_has_single_step() (1)
> #define user_mode(regs) (((regs)->ps & 8) != 0)
> #define instruction_pointer(regs) ((regs)->pc)
> +#define exception_ip(regs) instruction_pointer(regs)
> #define profile_pc(regs) instruction_pointer(regs)
> #define current_user_stack_pointer() rdusp()
>
> diff --git a/arch/arc/include/asm/ptrace.h
> b/arch/arc/include/asm/ptrace.h
> index 00b9318e551e..94084f1048df 100644
> --- a/arch/arc/include/asm/ptrace.h
> +++ b/arch/arc/include/asm/ptrace.h
> @@ -105,6 +105,7 @@ struct callee_regs {
> #endif
>
> #define instruction_pointer(regs) ((regs)->ret)
> +#define exception_ip(regs) instruction_pointer(regs)
> #define profile_pc(regs) instruction_pointer(regs)
>
> /* return 1 if user mode or 0 if kernel mode */
> diff --git a/arch/arm/include/asm/ptrace.h
> b/arch/arm/include/asm/ptrace.h
> index 7f44e88d1f25..fb4dc23eba78 100644
> --- a/arch/arm/include/asm/ptrace.h
> +++ b/arch/arm/include/asm/ptrace.h
> @@ -89,6 +89,7 @@ static inline long regs_return_value(struct pt_regs
> *regs)
> }
>
> #define instruction_pointer(regs) (regs)->ARM_pc
> +#define
> exception_ip(regs) instruction_pointer(regs)
>
> #ifdef CONFIG_THUMB2_KERNEL
> #define frame_pointer(regs) (regs)->ARM_r7
> diff --git a/arch/csky/include/asm/ptrace.h
> b/arch/csky/include/asm/ptrace.h
> index 0634b7895d81..a738630e64b0 100644
> --- a/arch/csky/include/asm/ptrace.h
> +++ b/arch/csky/include/asm/ptrace.h
> @@ -22,6 +22,7 @@
>
> #define user_mode(regs) (!((regs)->sr & PS_S))
> #define instruction_pointer(regs) ((regs)->pc)
> +#define exception_ip(regs) instruction_pointer(regs)
> #define profile_pc(regs) instruction_pointer(regs)
> #define trap_no(regs) ((regs->sr >> 16) & 0xff)
>
> diff --git a/arch/hexagon/include/uapi/asm/ptrace.h
> b/arch/hexagon/include/uapi/asm/ptrace.h
> index 2a3ea14ad9b9..846471936237 100644
> --- a/arch/hexagon/include/uapi/asm/ptrace.h
> +++ b/arch/hexagon/include/uapi/asm/ptrace.h
> @@ -25,6 +25,7 @@
> #include <asm/registers.h>
>
> #define instruction_pointer(regs) pt_elr(regs)
> +#define exception_ip(regs) instruction_pointer(regs)
> #define user_stack_pointer(regs) ((regs)->r29)
>
> #define profile_pc(regs) instruction_pointer(regs)
> diff --git a/arch/loongarch/include/asm/ptrace.h
> b/arch/loongarch/include/asm/ptrace.h
> index f3ddaed9ef7f..a34327f0e69d 100644
> --- a/arch/loongarch/include/asm/ptrace.h
> +++ b/arch/loongarch/include/asm/ptrace.h
> @@ -160,6 +160,7 @@ static inline void regs_set_return_value(struct
> pt_regs *regs, unsigned long val
> }
>
> #define instruction_pointer(regs) ((regs)->csr_era)
> +#define exception_ip(regs) instruction_pointer(regs)
> #define profile_pc(regs) instruction_pointer(regs)
>
> extern void die(const char *str, struct pt_regs *regs);
> diff --git a/arch/m68k/include/asm/ptrace.h
> b/arch/m68k/include/asm/ptrace.h
> index ea5a80ca1ab3..cb553e2ec73a 100644
> --- a/arch/m68k/include/asm/ptrace.h
> +++ b/arch/m68k/include/asm/ptrace.h
> @@ -13,6 +13,7 @@
>
> #define user_mode(regs) (!((regs)->sr & PS_S))
> #define instruction_pointer(regs) ((regs)->pc)
> +#define exception_ip(regs) instruction_pointer(regs)
> #define profile_pc(regs) instruction_pointer(regs)
> #define current_pt_regs() \
> (struct pt_regs *)((char *)current_thread_info() +
> THREAD_SIZE) - 1
> diff --git a/arch/microblaze/include/asm/ptrace.h
> b/arch/microblaze/include/asm/ptrace.h
> index bfcb89df5e26..974c00fa7212 100644
> --- a/arch/microblaze/include/asm/ptrace.h
> +++ b/arch/microblaze/include/asm/ptrace.h
> @@ -12,7 +12,8 @@
> #define user_mode(regs) (!kernel_mode(regs))
>
> #define instruction_pointer(regs) ((regs)->pc)
> -#define profile_pc(regs) instruction_pointer(regs)
> +#define
> exception_ip(regs) instruction_pointer(regs)
> +#define
> profile_pc(regs) instruction_pointer(regs)
> #define user_stack_pointer(regs) ((regs)->r1)
>
> static inline long regs_return_value(struct pt_regs *regs)
> diff --git a/arch/mips/include/asm/ptrace.h
> b/arch/mips/include/asm/ptrace.h
> index daf3cf244ea9..97589731fd40 100644
> --- a/arch/mips/include/asm/ptrace.h
> +++ b/arch/mips/include/asm/ptrace.h
> @@ -154,6 +154,7 @@ static inline long regs_return_value(struct
> pt_regs *regs)
> }
>
> #define instruction_pointer(regs) ((regs)->cp0_epc)
> +extern unsigned long exception_ip(struct pt_regs *regs);
> #define profile_pc(regs) instruction_pointer(regs)
>
> extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long
> syscall);
> diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
> index d9df543f7e2c..59288c13b581 100644
> --- a/arch/mips/kernel/ptrace.c
> +++ b/arch/mips/kernel/ptrace.c
> @@ -31,6 +31,7 @@
> #include <linux/seccomp.h>
> #include <linux/ftrace.h>
>
> +#include <asm/branch.h>
> #include <asm/byteorder.h>
> #include <asm/cpu.h>
> #include <asm/cpu-info.h>
> @@ -48,6 +49,12 @@
> #define CREATE_TRACE_POINTS
> #include <trace/events/syscalls.h>
>
> +unsigned long exception_ip(struct pt_regs *regs)
> +{
> + return exception_epc(regs);
> +}
> +EXPORT_SYMBOL(exception_ip);
> +
> /*
> * Called by kernel/ptrace.c when detaching..
> *
> diff --git a/arch/nios2/include/asm/ptrace.h
> b/arch/nios2/include/asm/ptrace.h
> index 9da34c3022a2..136f5679ae79 100644
> --- a/arch/nios2/include/asm/ptrace.h
> +++ b/arch/nios2/include/asm/ptrace.h
> @@ -66,7 +66,8 @@ struct switch_stack {
> #define user_mode(regs) (((regs)->estatus & ESTATUS_EU))
>
> #define instruction_pointer(regs) ((regs)->ra)
> -#define profile_pc(regs) instruction_pointer(regs)
> +#define
> exception_ip(regs) instruction_pointer(regs)
> +#define
> profile_pc(regs) instruction_pointer(regs)
> #define user_stack_pointer(regs) ((regs)->sp)
> extern void show_regs(struct pt_regs *);
>
> diff --git a/arch/openrisc/include/asm/ptrace.h
> b/arch/openrisc/include/asm/ptrace.h
> index 375147ff71fc..67c28484d17e 100644
> --- a/arch/openrisc/include/asm/ptrace.h
> +++ b/arch/openrisc/include/asm/ptrace.h
> @@ -67,6 +67,7 @@ struct pt_regs {
> #define STACK_FRAME_OVERHEAD 128 /* size of minimum stack frame */
>
> #define instruction_pointer(regs) ((regs)->pc)
> +#define
> exception_ip(regs) instruction_pointer(regs)
> #define user_mode(regs) (((regs)->sr &
> SPR_SR_SM) == 0)
> #define user_stack_pointer(regs) ((unsigned long)(regs)->sp)
> #define profile_pc(regs) instruction_pointer(regs)
> diff --git a/arch/parisc/include/asm/ptrace.h
> b/arch/parisc/include/asm/ptrace.h
> index eea3f3df0823..d7e8dcf26582 100644
> --- a/arch/parisc/include/asm/ptrace.h
> +++ b/arch/parisc/include/asm/ptrace.h
> @@ -17,6 +17,7 @@
> #define user_mode(regs) (((regs)->iaoq[0] &
> 3) != PRIV_KERNEL)
> #define user_space(regs) ((regs)->iasq[1] !=
> PRIV_KERNEL)
> #define instruction_pointer(regs) ((regs)->iaoq[0] & ~3)
> +#define
> exception_ip(regs) instruction_pointer(regs)
> #define user_stack_pointer(regs) ((regs)->gr[30])
> unsigned long profile_pc(struct pt_regs *);
>
> diff --git a/arch/s390/include/asm/ptrace.h
> b/arch/s390/include/asm/ptrace.h
> index d28bf8fb2799..a5255b2337af 100644
> --- a/arch/s390/include/asm/ptrace.h
> +++ b/arch/s390/include/asm/ptrace.h
> @@ -211,6 +211,7 @@ static inline int
> test_and_clear_pt_regs_flag(struct pt_regs *regs, int flag)
>
> #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
> #define instruction_pointer(regs) ((regs)->psw.addr)
> +#define exception_ip(regs) instruction_pointer(regs)
> #define user_stack_pointer(regs)((regs)->gprs[15])
> #define profile_pc(regs) instruction_pointer(regs)
>
> diff --git a/arch/sparc/include/asm/ptrace.h
> b/arch/sparc/include/asm/ptrace.h
> index d1419e669027..41ae186f2245 100644
> --- a/arch/sparc/include/asm/ptrace.h
> +++ b/arch/sparc/include/asm/ptrace.h
> @@ -63,6 +63,7 @@ extern union global_cpu_snapshot
> global_cpu_snapshot[NR_CPUS];
> #define force_successful_syscall_return() set_thread_noerror(1)
> #define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
> #define instruction_pointer(regs) ((regs)->tpc)
> +#define exception_ip(regs) instruction_pointer(regs)
> #define instruction_pointer_set(regs, val) do { \
> (regs)->tpc = (val); \
> (regs)->tnpc = (val)+4; \
> @@ -142,6 +143,7 @@ static inline bool pt_regs_clear_syscall(struct
> pt_regs *regs)
>
> #define user_mode(regs) (!((regs)->psr & PSR_PS))
> #define instruction_pointer(regs) ((regs)->pc)
> +#define exception_ip(regs) instruction_pointer(regs)
> #define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
> unsigned long profile_pc(struct pt_regs *);
> #else /* (!__ASSEMBLY__) */
> diff --git a/arch/um/include/asm/ptrace-generic.h
> b/arch/um/include/asm/ptrace-generic.h
> index adf91ef553ae..f9ada287ca12 100644
> --- a/arch/um/include/asm/ptrace-generic.h
> +++ b/arch/um/include/asm/ptrace-generic.h
> @@ -26,6 +26,7 @@ struct pt_regs {
> #define PT_REGS_SYSCALL_NR(r) UPT_SYSCALL_NR(&(r)->regs)
>
> #define instruction_pointer(regs) PT_REGS_IP(regs)
> +#define exception_ip(regs) instruction_pointer(regs)
>
> #define PTRACE_OLDSETOPTIONS 21
>
>
在 2024/2/1 16:35, Xi Ruoyao 写道:
> On Thu, 2024-02-01 at 15:46 +0000, Jiaxun Yang wrote:
>> On architectures with delay slot, architecture level instruction
>> pointer (or program counter) in pt_regs may differ from where
>> exception was triggered.
>>
>> Introduce exception_ip hook to invoke architecture code and determine
>> actual instruction pointer to the exception.
>>
>> Link:
>> https://lore.kernel.org/lkml/00d1b813-c55f-4365-8d81-d70258e10b16@app.fastmail.com/
>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> How about adding something like
>
> #ifndef arch_exception_ip
> #define exception_ip(regs) instruction_pointer(regs)
> #else
> #define exception_ip(regs) arch_exception_ip(regs)
> #endif
>
> into a generic header, instead of having to add exception_ip definition
> everywhere?
Actually I tried but failed, cuz there is no asm-generic version of
ptrace.h, besides
exception_ip shall be used at many scenarios so extable.h is also a no go.
Thanks
- Jiaxun
>
>> ---
>> arch/alpha/include/asm/ptrace.h | 1 +
>> arch/arc/include/asm/ptrace.h | 1 +
>> arch/arm/include/asm/ptrace.h | 1 +
>> arch/csky/include/asm/ptrace.h | 1 +
>> arch/hexagon/include/uapi/asm/ptrace.h | 1 +
>> arch/loongarch/include/asm/ptrace.h | 1 +
>> arch/m68k/include/asm/ptrace.h | 1 +
>> arch/microblaze/include/asm/ptrace.h | 3 ++-
>> arch/mips/include/asm/ptrace.h | 1 +
>> arch/mips/kernel/ptrace.c | 7 +++++++
>> arch/nios2/include/asm/ptrace.h | 3 ++-
>> arch/openrisc/include/asm/ptrace.h | 1 +
>> arch/parisc/include/asm/ptrace.h | 1 +
>> arch/s390/include/asm/ptrace.h | 1 +
>> arch/sparc/include/asm/ptrace.h | 2 ++
>> arch/um/include/asm/ptrace-generic.h | 1 +
>> 16 files changed, 25 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/alpha/include/asm/ptrace.h
>> b/arch/alpha/include/asm/ptrace.h
>> index 3557ce64ed21..1ded3f2d09e9 100644
>> --- a/arch/alpha/include/asm/ptrace.h
>> +++ b/arch/alpha/include/asm/ptrace.h
>> @@ -8,6 +8,7 @@
>> #define arch_has_single_step() (1)
>> #define user_mode(regs) (((regs)->ps & 8) != 0)
>> #define instruction_pointer(regs) ((regs)->pc)
>> +#define exception_ip(regs) instruction_pointer(regs)
>> #define profile_pc(regs) instruction_pointer(regs)
>> #define current_user_stack_pointer() rdusp()
>>
>> diff --git a/arch/arc/include/asm/ptrace.h
>> b/arch/arc/include/asm/ptrace.h
>> index 00b9318e551e..94084f1048df 100644
>> --- a/arch/arc/include/asm/ptrace.h
>> +++ b/arch/arc/include/asm/ptrace.h
>> @@ -105,6 +105,7 @@ struct callee_regs {
>> #endif
>>
>> #define instruction_pointer(regs) ((regs)->ret)
>> +#define exception_ip(regs) instruction_pointer(regs)
>> #define profile_pc(regs) instruction_pointer(regs)
>>
>> /* return 1 if user mode or 0 if kernel mode */
>> diff --git a/arch/arm/include/asm/ptrace.h
>> b/arch/arm/include/asm/ptrace.h
>> index 7f44e88d1f25..fb4dc23eba78 100644
>> --- a/arch/arm/include/asm/ptrace.h
>> +++ b/arch/arm/include/asm/ptrace.h
>> @@ -89,6 +89,7 @@ static inline long regs_return_value(struct pt_regs
>> *regs)
>> }
>>
>> #define instruction_pointer(regs) (regs)->ARM_pc
>> +#define
>> exception_ip(regs) instruction_pointer(regs)
>>
>> #ifdef CONFIG_THUMB2_KERNEL
>> #define frame_pointer(regs) (regs)->ARM_r7
>> diff --git a/arch/csky/include/asm/ptrace.h
>> b/arch/csky/include/asm/ptrace.h
>> index 0634b7895d81..a738630e64b0 100644
>> --- a/arch/csky/include/asm/ptrace.h
>> +++ b/arch/csky/include/asm/ptrace.h
>> @@ -22,6 +22,7 @@
>>
>> #define user_mode(regs) (!((regs)->sr & PS_S))
>> #define instruction_pointer(regs) ((regs)->pc)
>> +#define exception_ip(regs) instruction_pointer(regs)
>> #define profile_pc(regs) instruction_pointer(regs)
>> #define trap_no(regs) ((regs->sr >> 16) & 0xff)
>>
>> diff --git a/arch/hexagon/include/uapi/asm/ptrace.h
>> b/arch/hexagon/include/uapi/asm/ptrace.h
>> index 2a3ea14ad9b9..846471936237 100644
>> --- a/arch/hexagon/include/uapi/asm/ptrace.h
>> +++ b/arch/hexagon/include/uapi/asm/ptrace.h
>> @@ -25,6 +25,7 @@
>> #include <asm/registers.h>
>>
>> #define instruction_pointer(regs) pt_elr(regs)
>> +#define exception_ip(regs) instruction_pointer(regs)
>> #define user_stack_pointer(regs) ((regs)->r29)
>>
>> #define profile_pc(regs) instruction_pointer(regs)
>> diff --git a/arch/loongarch/include/asm/ptrace.h
>> b/arch/loongarch/include/asm/ptrace.h
>> index f3ddaed9ef7f..a34327f0e69d 100644
>> --- a/arch/loongarch/include/asm/ptrace.h
>> +++ b/arch/loongarch/include/asm/ptrace.h
>> @@ -160,6 +160,7 @@ static inline void regs_set_return_value(struct
>> pt_regs *regs, unsigned long val
>> }
>>
>> #define instruction_pointer(regs) ((regs)->csr_era)
>> +#define exception_ip(regs) instruction_pointer(regs)
>> #define profile_pc(regs) instruction_pointer(regs)
>>
>> extern void die(const char *str, struct pt_regs *regs);
>> diff --git a/arch/m68k/include/asm/ptrace.h
>> b/arch/m68k/include/asm/ptrace.h
>> index ea5a80ca1ab3..cb553e2ec73a 100644
>> --- a/arch/m68k/include/asm/ptrace.h
>> +++ b/arch/m68k/include/asm/ptrace.h
>> @@ -13,6 +13,7 @@
>>
>> #define user_mode(regs) (!((regs)->sr & PS_S))
>> #define instruction_pointer(regs) ((regs)->pc)
>> +#define exception_ip(regs) instruction_pointer(regs)
>> #define profile_pc(regs) instruction_pointer(regs)
>> #define current_pt_regs() \
>> (struct pt_regs *)((char *)current_thread_info() +
>> THREAD_SIZE) - 1
>> diff --git a/arch/microblaze/include/asm/ptrace.h
>> b/arch/microblaze/include/asm/ptrace.h
>> index bfcb89df5e26..974c00fa7212 100644
>> --- a/arch/microblaze/include/asm/ptrace.h
>> +++ b/arch/microblaze/include/asm/ptrace.h
>> @@ -12,7 +12,8 @@
>> #define user_mode(regs) (!kernel_mode(regs))
>>
>> #define instruction_pointer(regs) ((regs)->pc)
>> -#define profile_pc(regs) instruction_pointer(regs)
>> +#define
>> exception_ip(regs) instruction_pointer(regs)
>> +#define
>> profile_pc(regs) instruction_pointer(regs)
>> #define user_stack_pointer(regs) ((regs)->r1)
>>
>> static inline long regs_return_value(struct pt_regs *regs)
>> diff --git a/arch/mips/include/asm/ptrace.h
>> b/arch/mips/include/asm/ptrace.h
>> index daf3cf244ea9..97589731fd40 100644
>> --- a/arch/mips/include/asm/ptrace.h
>> +++ b/arch/mips/include/asm/ptrace.h
>> @@ -154,6 +154,7 @@ static inline long regs_return_value(struct
>> pt_regs *regs)
>> }
>>
>> #define instruction_pointer(regs) ((regs)->cp0_epc)
>> +extern unsigned long exception_ip(struct pt_regs *regs);
>> #define profile_pc(regs) instruction_pointer(regs)
>>
>> extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long
>> syscall);
>> diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
>> index d9df543f7e2c..59288c13b581 100644
>> --- a/arch/mips/kernel/ptrace.c
>> +++ b/arch/mips/kernel/ptrace.c
>> @@ -31,6 +31,7 @@
>> #include <linux/seccomp.h>
>> #include <linux/ftrace.h>
>>
>> +#include <asm/branch.h>
>> #include <asm/byteorder.h>
>> #include <asm/cpu.h>
>> #include <asm/cpu-info.h>
>> @@ -48,6 +49,12 @@
>> #define CREATE_TRACE_POINTS
>> #include <trace/events/syscalls.h>
>>
>> +unsigned long exception_ip(struct pt_regs *regs)
>> +{
>> + return exception_epc(regs);
>> +}
>> +EXPORT_SYMBOL(exception_ip);
>> +
>> /*
>> * Called by kernel/ptrace.c when detaching..
>> *
>> diff --git a/arch/nios2/include/asm/ptrace.h
>> b/arch/nios2/include/asm/ptrace.h
>> index 9da34c3022a2..136f5679ae79 100644
>> --- a/arch/nios2/include/asm/ptrace.h
>> +++ b/arch/nios2/include/asm/ptrace.h
>> @@ -66,7 +66,8 @@ struct switch_stack {
>> #define user_mode(regs) (((regs)->estatus & ESTATUS_EU))
>>
>> #define instruction_pointer(regs) ((regs)->ra)
>> -#define profile_pc(regs) instruction_pointer(regs)
>> +#define
>> exception_ip(regs) instruction_pointer(regs)
>> +#define
>> profile_pc(regs) instruction_pointer(regs)
>> #define user_stack_pointer(regs) ((regs)->sp)
>> extern void show_regs(struct pt_regs *);
>>
>> diff --git a/arch/openrisc/include/asm/ptrace.h
>> b/arch/openrisc/include/asm/ptrace.h
>> index 375147ff71fc..67c28484d17e 100644
>> --- a/arch/openrisc/include/asm/ptrace.h
>> +++ b/arch/openrisc/include/asm/ptrace.h
>> @@ -67,6 +67,7 @@ struct pt_regs {
>> #define STACK_FRAME_OVERHEAD 128 /* size of minimum stack frame */
>>
>> #define instruction_pointer(regs) ((regs)->pc)
>> +#define
>> exception_ip(regs) instruction_pointer(regs)
>> #define user_mode(regs) (((regs)->sr &
>> SPR_SR_SM) == 0)
>> #define user_stack_pointer(regs) ((unsigned long)(regs)->sp)
>> #define profile_pc(regs) instruction_pointer(regs)
>> diff --git a/arch/parisc/include/asm/ptrace.h
>> b/arch/parisc/include/asm/ptrace.h
>> index eea3f3df0823..d7e8dcf26582 100644
>> --- a/arch/parisc/include/asm/ptrace.h
>> +++ b/arch/parisc/include/asm/ptrace.h
>> @@ -17,6 +17,7 @@
>> #define user_mode(regs) (((regs)->iaoq[0] &
>> 3) != PRIV_KERNEL)
>> #define user_space(regs) ((regs)->iasq[1] !=
>> PRIV_KERNEL)
>> #define instruction_pointer(regs) ((regs)->iaoq[0] & ~3)
>> +#define
>> exception_ip(regs) instruction_pointer(regs)
>> #define user_stack_pointer(regs) ((regs)->gr[30])
>> unsigned long profile_pc(struct pt_regs *);
>>
>> diff --git a/arch/s390/include/asm/ptrace.h
>> b/arch/s390/include/asm/ptrace.h
>> index d28bf8fb2799..a5255b2337af 100644
>> --- a/arch/s390/include/asm/ptrace.h
>> +++ b/arch/s390/include/asm/ptrace.h
>> @@ -211,6 +211,7 @@ static inline int
>> test_and_clear_pt_regs_flag(struct pt_regs *regs, int flag)
>>
>> #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
>> #define instruction_pointer(regs) ((regs)->psw.addr)
>> +#define exception_ip(regs) instruction_pointer(regs)
>> #define user_stack_pointer(regs)((regs)->gprs[15])
>> #define profile_pc(regs) instruction_pointer(regs)
>>
>> diff --git a/arch/sparc/include/asm/ptrace.h
>> b/arch/sparc/include/asm/ptrace.h
>> index d1419e669027..41ae186f2245 100644
>> --- a/arch/sparc/include/asm/ptrace.h
>> +++ b/arch/sparc/include/asm/ptrace.h
>> @@ -63,6 +63,7 @@ extern union global_cpu_snapshot
>> global_cpu_snapshot[NR_CPUS];
>> #define force_successful_syscall_return() set_thread_noerror(1)
>> #define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
>> #define instruction_pointer(regs) ((regs)->tpc)
>> +#define exception_ip(regs) instruction_pointer(regs)
>> #define instruction_pointer_set(regs, val) do { \
>> (regs)->tpc = (val); \
>> (regs)->tnpc = (val)+4; \
>> @@ -142,6 +143,7 @@ static inline bool pt_regs_clear_syscall(struct
>> pt_regs *regs)
>>
>> #define user_mode(regs) (!((regs)->psr & PSR_PS))
>> #define instruction_pointer(regs) ((regs)->pc)
>> +#define exception_ip(regs) instruction_pointer(regs)
>> #define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
>> unsigned long profile_pc(struct pt_regs *);
>> #else /* (!__ASSEMBLY__) */
>> diff --git a/arch/um/include/asm/ptrace-generic.h
>> b/arch/um/include/asm/ptrace-generic.h
>> index adf91ef553ae..f9ada287ca12 100644
>> --- a/arch/um/include/asm/ptrace-generic.h
>> +++ b/arch/um/include/asm/ptrace-generic.h
>> @@ -26,6 +26,7 @@ struct pt_regs {
>> #define PT_REGS_SYSCALL_NR(r) UPT_SYSCALL_NR(&(r)->regs)
>>
>> #define instruction_pointer(regs) PT_REGS_IP(regs)
>> +#define exception_ip(regs) instruction_pointer(regs)
>>
>> #define PTRACE_OLDSETOPTIONS 21
>>
>>
@@ -8,6 +8,7 @@
#define arch_has_single_step() (1)
#define user_mode(regs) (((regs)->ps & 8) != 0)
#define instruction_pointer(regs) ((regs)->pc)
+#define exception_ip(regs) instruction_pointer(regs)
#define profile_pc(regs) instruction_pointer(regs)
#define current_user_stack_pointer() rdusp()
@@ -105,6 +105,7 @@ struct callee_regs {
#endif
#define instruction_pointer(regs) ((regs)->ret)
+#define exception_ip(regs) instruction_pointer(regs)
#define profile_pc(regs) instruction_pointer(regs)
/* return 1 if user mode or 0 if kernel mode */
@@ -89,6 +89,7 @@ static inline long regs_return_value(struct pt_regs *regs)
}
#define instruction_pointer(regs) (regs)->ARM_pc
+#define exception_ip(regs) instruction_pointer(regs)
#ifdef CONFIG_THUMB2_KERNEL
#define frame_pointer(regs) (regs)->ARM_r7
@@ -22,6 +22,7 @@
#define user_mode(regs) (!((regs)->sr & PS_S))
#define instruction_pointer(regs) ((regs)->pc)
+#define exception_ip(regs) instruction_pointer(regs)
#define profile_pc(regs) instruction_pointer(regs)
#define trap_no(regs) ((regs->sr >> 16) & 0xff)
@@ -25,6 +25,7 @@
#include <asm/registers.h>
#define instruction_pointer(regs) pt_elr(regs)
+#define exception_ip(regs) instruction_pointer(regs)
#define user_stack_pointer(regs) ((regs)->r29)
#define profile_pc(regs) instruction_pointer(regs)
@@ -160,6 +160,7 @@ static inline void regs_set_return_value(struct pt_regs *regs, unsigned long val
}
#define instruction_pointer(regs) ((regs)->csr_era)
+#define exception_ip(regs) instruction_pointer(regs)
#define profile_pc(regs) instruction_pointer(regs)
extern void die(const char *str, struct pt_regs *regs);
@@ -13,6 +13,7 @@
#define user_mode(regs) (!((regs)->sr & PS_S))
#define instruction_pointer(regs) ((regs)->pc)
+#define exception_ip(regs) instruction_pointer(regs)
#define profile_pc(regs) instruction_pointer(regs)
#define current_pt_regs() \
(struct pt_regs *)((char *)current_thread_info() + THREAD_SIZE) - 1
@@ -12,7 +12,8 @@
#define user_mode(regs) (!kernel_mode(regs))
#define instruction_pointer(regs) ((regs)->pc)
-#define profile_pc(regs) instruction_pointer(regs)
+#define exception_ip(regs) instruction_pointer(regs)
+#define profile_pc(regs) instruction_pointer(regs)
#define user_stack_pointer(regs) ((regs)->r1)
static inline long regs_return_value(struct pt_regs *regs)
@@ -154,6 +154,7 @@ static inline long regs_return_value(struct pt_regs *regs)
}
#define instruction_pointer(regs) ((regs)->cp0_epc)
+extern unsigned long exception_ip(struct pt_regs *regs);
#define profile_pc(regs) instruction_pointer(regs)
extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall);
@@ -31,6 +31,7 @@
#include <linux/seccomp.h>
#include <linux/ftrace.h>
+#include <asm/branch.h>
#include <asm/byteorder.h>
#include <asm/cpu.h>
#include <asm/cpu-info.h>
@@ -48,6 +49,12 @@
#define CREATE_TRACE_POINTS
#include <trace/events/syscalls.h>
+unsigned long exception_ip(struct pt_regs *regs)
+{
+ return exception_epc(regs);
+}
+EXPORT_SYMBOL(exception_ip);
+
/*
* Called by kernel/ptrace.c when detaching..
*
@@ -66,7 +66,8 @@ struct switch_stack {
#define user_mode(regs) (((regs)->estatus & ESTATUS_EU))
#define instruction_pointer(regs) ((regs)->ra)
-#define profile_pc(regs) instruction_pointer(regs)
+#define exception_ip(regs) instruction_pointer(regs)
+#define profile_pc(regs) instruction_pointer(regs)
#define user_stack_pointer(regs) ((regs)->sp)
extern void show_regs(struct pt_regs *);
@@ -67,6 +67,7 @@ struct pt_regs {
#define STACK_FRAME_OVERHEAD 128 /* size of minimum stack frame */
#define instruction_pointer(regs) ((regs)->pc)
+#define exception_ip(regs) instruction_pointer(regs)
#define user_mode(regs) (((regs)->sr & SPR_SR_SM) == 0)
#define user_stack_pointer(regs) ((unsigned long)(regs)->sp)
#define profile_pc(regs) instruction_pointer(regs)
@@ -17,6 +17,7 @@
#define user_mode(regs) (((regs)->iaoq[0] & 3) != PRIV_KERNEL)
#define user_space(regs) ((regs)->iasq[1] != PRIV_KERNEL)
#define instruction_pointer(regs) ((regs)->iaoq[0] & ~3)
+#define exception_ip(regs) instruction_pointer(regs)
#define user_stack_pointer(regs) ((regs)->gr[30])
unsigned long profile_pc(struct pt_regs *);
@@ -211,6 +211,7 @@ static inline int test_and_clear_pt_regs_flag(struct pt_regs *regs, int flag)
#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
#define instruction_pointer(regs) ((regs)->psw.addr)
+#define exception_ip(regs) instruction_pointer(regs)
#define user_stack_pointer(regs)((regs)->gprs[15])
#define profile_pc(regs) instruction_pointer(regs)
@@ -63,6 +63,7 @@ extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS];
#define force_successful_syscall_return() set_thread_noerror(1)
#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
#define instruction_pointer(regs) ((regs)->tpc)
+#define exception_ip(regs) instruction_pointer(regs)
#define instruction_pointer_set(regs, val) do { \
(regs)->tpc = (val); \
(regs)->tnpc = (val)+4; \
@@ -142,6 +143,7 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
#define user_mode(regs) (!((regs)->psr & PSR_PS))
#define instruction_pointer(regs) ((regs)->pc)
+#define exception_ip(regs) instruction_pointer(regs)
#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
unsigned long profile_pc(struct pt_regs *);
#else /* (!__ASSEMBLY__) */
@@ -26,6 +26,7 @@ struct pt_regs {
#define PT_REGS_SYSCALL_NR(r) UPT_SYSCALL_NR(&(r)->regs)
#define instruction_pointer(regs) PT_REGS_IP(regs)
+#define exception_ip(regs) instruction_pointer(regs)
#define PTRACE_OLDSETOPTIONS 21