objtool: Support conditional retpolines
A Clang-built kernel is showing the following warning: arch/x86/kernel/platform-quirks.o: warning: objtool: x86_early_init_platform_quirks()+0x84: unreachable instruction That corresponds to this code: 7e: 0f 85 00 00 00 00 jne 84 <x86_early_init_platform_quirks+0x84> 80: R_X86_64_PC32 __x86_indirect_thunk_r11-0x4 84: c3 retq This is a conditional retpoline sibling call, which is now possible thanks to retpolines. Objtool hasn't seen that before. It's incorrectly interpreting the conditional jump as an unconditional dynamic jump. Reported-by: Nick Desaulniers <ndesaulniers@google.com> Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Nick Desaulniers <ndesaulniers@google.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lkml.kernel.org/r/30d4c758b267ef487fb97e6ecb2f148ad007b554.1563413318.git.jpoimboe@redhat.com
This commit is contained in:
Родитель
9fe7b7642f
Коммит
b68b990706
|
@ -15,6 +15,7 @@ enum insn_type {
|
|||
INSN_JUMP_CONDITIONAL,
|
||||
INSN_JUMP_UNCONDITIONAL,
|
||||
INSN_JUMP_DYNAMIC,
|
||||
INSN_JUMP_DYNAMIC_CONDITIONAL,
|
||||
INSN_CALL,
|
||||
INSN_CALL_DYNAMIC,
|
||||
INSN_RETURN,
|
||||
|
|
|
@ -575,7 +575,11 @@ static int add_jump_destinations(struct objtool_file *file)
|
|||
* Retpoline jumps are really dynamic jumps in
|
||||
* disguise, so convert them accordingly.
|
||||
*/
|
||||
insn->type = INSN_JUMP_DYNAMIC;
|
||||
if (insn->type == INSN_JUMP_UNCONDITIONAL)
|
||||
insn->type = INSN_JUMP_DYNAMIC;
|
||||
else
|
||||
insn->type = INSN_JUMP_DYNAMIC_CONDITIONAL;
|
||||
|
||||
insn->retpoline_safe = true;
|
||||
continue;
|
||||
} else {
|
||||
|
@ -2114,13 +2118,17 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
|
|||
break;
|
||||
|
||||
case INSN_JUMP_DYNAMIC:
|
||||
case INSN_JUMP_DYNAMIC_CONDITIONAL:
|
||||
if (func && is_sibling_call(insn)) {
|
||||
ret = validate_sibling_call(insn, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (insn->type == INSN_JUMP_DYNAMIC)
|
||||
return 0;
|
||||
|
||||
break;
|
||||
|
||||
case INSN_CONTEXT_SWITCH:
|
||||
if (func && (!next_insn || !next_insn->hint)) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче