objtool: Fix sibling call detection logic
With some configs, objtool reports the following warning: arch/x86/kernel/ftrace.o: warning: objtool: ftrace_modify_code_direct()+0x2d: sibling call from callable instruction with modified stack frame The instruction it's complaining about isn't actually a sibling call. It's just a normal jump to an address inside the function. Objtool thought it was a sibling call because the instruction's jump_dest wasn't initialized because the function was supposed to be ignored due to its use of sync_core(). Objtool ended up validating the function instead of ignoring it because it didn't properly recognize a sibling call to the function. So fix the sibling call logic. Also add a warning to catch ignored functions being validated so we'll get a more useful error message next time. Reported-by: Mike Galbraith <efault@gmx.de> Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/96cc8ecbcdd8cb29ddd783817b4af918a6a171b0.1499437107.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
4422d80ed7
commit
4855022a52
|
@ -1371,6 +1371,12 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
|
|||
|
||||
func = insn->func;
|
||||
|
||||
if (func && insn->ignore) {
|
||||
WARN_FUNC("BUG: why am I validating an ignored function?",
|
||||
sec, insn->offset);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (insn->visited) {
|
||||
if (!!insn_state_match(insn, &state))
|
||||
return 1;
|
||||
|
@ -1426,16 +1432,19 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
|
|||
|
||||
case INSN_JUMP_CONDITIONAL:
|
||||
case INSN_JUMP_UNCONDITIONAL:
|
||||
if (insn->jump_dest) {
|
||||
if (insn->jump_dest &&
|
||||
(!func || !insn->jump_dest->func ||
|
||||
func == insn->jump_dest->func)) {
|
||||
ret = validate_branch(file, insn->jump_dest,
|
||||
state);
|
||||
if (ret)
|
||||
return 1;
|
||||
|
||||
} else if (func && has_modified_stack_frame(&state)) {
|
||||
WARN_FUNC("sibling call from callable instruction with modified stack frame",
|
||||
sec, insn->offset);
|
||||
return 1;
|
||||
} /* else it's a sibling call */
|
||||
}
|
||||
|
||||
if (insn->type == INSN_JUMP_UNCONDITIONAL)
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue