Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

objtool: Ignore exc_double_fault() __noreturn warnings

This is a hack, but it works for now.

Problem is, exc_double_fault() may or may not return, depending on
whether CONFIG_X86_ESPFIX64 is set. But objtool has no visibility to
the kernel config.

"Fix" it by silencing the exc_double_fault() __noreturn warning.

This removes the following warning:

vmlinux.o: warning: objtool: xenpv_exc_double_fault+0xd: exc_double_fault() is missing a __noreturn annotation

Reviewed-by: Miroslav Benes <mbenes@suse.cz>
Link: https://lore.kernel.org/r/a45b085071d3a7d049a20f9e78754452336ecbe8.1681853186.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>

+30 -1
+30 -1
tools/objtool/check.c
··· 4505 4505 return warnings; 4506 4506 } 4507 4507 4508 + static bool ignore_noreturn_call(struct instruction *insn) 4509 + { 4510 + struct symbol *call_dest = insn_call_dest(insn); 4511 + 4512 + /* 4513 + * FIXME: hack, we need a real noreturn solution 4514 + * 4515 + * Problem is, exc_double_fault() may or may not return, depending on 4516 + * whether CONFIG_X86_ESPFIX64 is set. But objtool has no visibility 4517 + * to the kernel config. 4518 + * 4519 + * Other potential ways to fix it: 4520 + * 4521 + * - have compiler communicate __noreturn functions somehow 4522 + * - remove CONFIG_X86_ESPFIX64 4523 + * - read the .config file 4524 + * - add a cmdline option 4525 + * - create a generic objtool annotation format (vs a bunch of custom 4526 + * formats) and annotate it 4527 + */ 4528 + if (!strcmp(call_dest->name, "exc_double_fault")) { 4529 + /* prevent further unreachable warnings for the caller */ 4530 + insn->sym->warned = 1; 4531 + return true; 4532 + } 4533 + 4534 + return false; 4535 + } 4536 + 4508 4537 static int validate_reachable_instructions(struct objtool_file *file) 4509 4538 { 4510 4539 struct instruction *insn, *prev_insn; ··· 4550 4521 prev_insn = prev_insn_same_sec(file, insn); 4551 4522 if (prev_insn && prev_insn->dead_end) { 4552 4523 call_dest = insn_call_dest(prev_insn); 4553 - if (call_dest) { 4524 + if (call_dest && !ignore_noreturn_call(prev_insn)) { 4554 4525 WARN_INSN(insn, "%s() is missing a __noreturn annotation", 4555 4526 call_dest->name); 4556 4527 warnings++;