After having spent some time on a previous question, a user introduced me to an email thread concerning the below issue:
[PATCH] ftrace/x86: Fix function graph tracer reset path
On my system, simply enabling and disabling function graph tracer can crash the kernel. I don't know how it worked until now.
The
ftrace_disable_ftrace_graph_caller()
modifies jmp instruction atftrace_graph_call
assuming it's a 5 bytes near jmp (e9 ). However it's a short jmp consisting of 2 bytes only (eb ). Andftrace_stub()
is located just below theftrace_graph_caller
so modification above breaks the instruction resulting in kernel oops on theftrace_stub()
with the invalid opcode like below:
One solution for this issue is the following patch:
diff --git a/arch/x86/kernel/mcount_64.S b/arch/x86/kernel/mcount_64.S
index ed48a9f465f8..e13a695c3084 100644
--- a/arch/x86/kernel/mcount_64.S
+++ b/arch/x86/kernel/mcount_64.S
@@ -182,7 +182,8 @@ GLOBAL(ftrace_graph_call)
jmp ftrace_stub
#endif
-GLOBAL(ftrace_stub)
+/* This is weak to keep gas from relaxing the jumps */
+WEAK(ftrace_stub)
retq
END(ftrace_caller)
via https://lkml.org/lkml/2016/5/16/493
I do not understand what the effect is in replacing GLOBAL(ftrace_stub)
with WEAK(ftrace_stub)
. Neither the comment included in the patch nor looking into GLOBAL() and WEAK() have helped me understand why this solution works.
My question, as the title suggest, is: What are the consequences of changing a symbol from .globl to .weak? I would appreciate an answer that considers how replacing GLOBAL(ftrace_stub)
to WEAK(ftrace_stub)
could address the referenced problem.