在previous question上花了一些时间后,用户向我介绍了有关以下问题的电子邮件主题:
[PATCH] ftrace/x86: Fix function graph tracer reset path
在我的系统上,只需启用和禁用功能图跟踪器即可 崩溃内核。直到现在我还不知道它是如何运作的。
ftrace_disable_ftrace_graph_caller()
修改了jmp指令ftrace_graph_call
假设它在jmp(e9)附近是5个字节。 然而,它是一个短的jmp,只包含2个字节(eb)。和ftrace_stub()
位于ftrace_graph_caller
的正下方 上面的修改打破了导致内核oops的指令 带有无效操作码的ftrace_stub()
如下所示:
此问题的一个解决方案是以下补丁:
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)
通过https://lkml.org/lkml/2016/5/16/493
我不明白用GLOBAL(ftrace_stub)
替换WEAK(ftrace_stub)
会产生什么影响。补丁中包含的评论以及GLOBAL()和WEAK()的评论都没有帮助我理解为什么这个解决方案有效。
我的问题,正如标题所暗示的那样:将符号从.globl更改为.weak有什么后果?我希望得到一个答案,考虑如何将GLOBAL(ftrace_stub)
替换为WEAK(ftrace_stub)
来解决引用的问题。
答案 0 :(得分:7)
由于ftrace_stub
是在当前文件中定义的,因此汇编程序知道距离,并且可以使用只有有限范围的jmp
的较短版本。
如果它更改为weak
,则表示符号可能无法解析为当前文件中的符号,因为其他模块可能会覆盖它。该潜在覆盖的偏移量是未知的,因此汇编程序必须使用修补代码所期望的全范围jmp
。