Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the consequences of changing a symbol from .globl to .weak?

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 at ftrace_graph_call assuming it's a 5 bytes near jmp (e9 ). However it's a short jmp consisting of 2 bytes only (eb ). And ftrace_stub() is located just below the ftrace_graph_caller so modification above breaks the instruction resulting in kernel oops on the ftrace_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.

like image 581
buratino Avatar asked Jun 14 '16 12:06

buratino


1 Answers

Since ftrace_stub is defined in the current file, the assembler knows the distance and can use the shorter version of jmp that only has limited range.

If it's changed to weak that means the symbol might not resolve to the one in the current file, as other module may override it. The offset to that potential override is not known, hence the assembler must use the full range jmp which is what the patching code expects.

like image 91
Jester Avatar answered Nov 10 '22 00:11

Jester