Skip to content

Commit fc2e426

Browse files
Chen ZhongjinIngo Molnar
authored andcommitted
x86/unwind/orc: Unwind ftrace trampolines with correct ORC entry
When meeting ftrace trampolines in ORC unwinding, unwinder uses address of ftrace_{regs_}call address to find the ORC entry, which gets next frame at sp+176. If there is an IRQ hitting at sub $0xa8,%rsp, the next frame should be sp+8 instead of 176. It makes unwinder skip correct frame and throw warnings such as "wrong direction" or "can't access registers", etc, depending on the content of the incorrect frame address. By adding the base address ftrace_{regs_}caller with the offset *ip - ops->trampoline*, we can get the correct address to find the ORC entry. Also change "caller" to "tramp_addr" to make variable name conform to its content. [ mingo: Clarified the changelog a bit. ] Fixes: 6be7fa3 ("ftrace, orc, x86: Handle ftrace dynamically allocated trampolines") Signed-off-by: Chen Zhongjin <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Reviewed-by: Steven Rostedt (Google) <[email protected]> Cc: <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 3329249 commit fc2e426

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

arch/x86/kernel/unwind_orc.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,22 +93,27 @@ static struct orc_entry *orc_find(unsigned long ip);
9393
static struct orc_entry *orc_ftrace_find(unsigned long ip)
9494
{
9595
struct ftrace_ops *ops;
96-
unsigned long caller;
96+
unsigned long tramp_addr, offset;
9797

9898
ops = ftrace_ops_trampoline(ip);
9999
if (!ops)
100100
return NULL;
101101

102+
/* Set tramp_addr to the start of the code copied by the trampoline */
102103
if (ops->flags & FTRACE_OPS_FL_SAVE_REGS)
103-
caller = (unsigned long)ftrace_regs_call;
104+
tramp_addr = (unsigned long)ftrace_regs_caller;
104105
else
105-
caller = (unsigned long)ftrace_call;
106+
tramp_addr = (unsigned long)ftrace_caller;
107+
108+
/* Now place tramp_addr to the location within the trampoline ip is at */
109+
offset = ip - ops->trampoline;
110+
tramp_addr += offset;
106111

107112
/* Prevent unlikely recursion */
108-
if (ip == caller)
113+
if (ip == tramp_addr)
109114
return NULL;
110115

111-
return orc_find(caller);
116+
return orc_find(tramp_addr);
112117
}
113118
#else
114119
static struct orc_entry *orc_ftrace_find(unsigned long ip)

0 commit comments

Comments
 (0)