mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
objtool: Split INSN_CONTEXT_SWITCH into INSN_SYSCALL and INSN_SYSRET
INSN_CONTEXT_SWITCH is ambiguous. It can represent both call semantics (SYSCALL, SYSENTER) and return semantics (SYSRET, IRET, RETS, RETU). Those differ significantly: calls preserve control flow whereas returns terminate it. Objtool uses an arbitrary rule for INSN_CONTEXT_SWITCH that almost works by accident: if in a function, keep going; otherwise stop. It should instead be based on the semantics of the underlying instruction. In preparation for improving that, split INSN_CONTEXT_SWITCH into INSN_SYCALL and INSN_SYSRET. No functional change. Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Link: https://lore.kernel.org/r/19a76c74d2c051d3bc9a775823cafc65ad267a7a.1744095216.git.jpoimboe@kernel.org
This commit is contained in:
parent
a8df7d0ef9
commit
fe1042b1ef
3 changed files with 17 additions and 10 deletions
|
@ -522,7 +522,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
case INAT_PFX_REPNE:
|
||||
if (modrm == 0xca)
|
||||
/* eretu/erets */
|
||||
insn->type = INSN_CONTEXT_SWITCH;
|
||||
insn->type = INSN_SYSRET;
|
||||
break;
|
||||
default:
|
||||
if (modrm == 0xca)
|
||||
|
@ -535,11 +535,15 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
|
||||
insn->type = INSN_JUMP_CONDITIONAL;
|
||||
|
||||
} else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 ||
|
||||
op2 == 0x35) {
|
||||
} else if (op2 == 0x05 || op2 == 0x34) {
|
||||
|
||||
/* sysenter, sysret */
|
||||
insn->type = INSN_CONTEXT_SWITCH;
|
||||
/* syscall, sysenter */
|
||||
insn->type = INSN_SYSCALL;
|
||||
|
||||
} else if (op2 == 0x07 || op2 == 0x35) {
|
||||
|
||||
/* sysret, sysexit */
|
||||
insn->type = INSN_SYSRET;
|
||||
|
||||
} else if (op2 == 0x0b || op2 == 0xb9) {
|
||||
|
||||
|
@ -676,7 +680,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
|
||||
case 0xca: /* retf */
|
||||
case 0xcb: /* retf */
|
||||
insn->type = INSN_CONTEXT_SWITCH;
|
||||
insn->type = INSN_SYSRET;
|
||||
break;
|
||||
|
||||
case 0xe0: /* loopne */
|
||||
|
@ -721,7 +725,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
} else if (modrm_reg == 5) {
|
||||
|
||||
/* jmpf */
|
||||
insn->type = INSN_CONTEXT_SWITCH;
|
||||
insn->type = INSN_SYSRET;
|
||||
|
||||
} else if (modrm_reg == 6) {
|
||||
|
||||
|
|
|
@ -3684,7 +3684,8 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
|
|||
|
||||
break;
|
||||
|
||||
case INSN_CONTEXT_SWITCH:
|
||||
case INSN_SYSCALL:
|
||||
case INSN_SYSRET:
|
||||
if (func) {
|
||||
if (!next_insn || !next_insn->hint) {
|
||||
WARN_INSN(insn, "unsupported instruction in callable function");
|
||||
|
@ -3886,7 +3887,8 @@ static int validate_unret(struct objtool_file *file, struct instruction *insn)
|
|||
WARN_INSN(insn, "RET before UNTRAIN");
|
||||
return 1;
|
||||
|
||||
case INSN_CONTEXT_SWITCH:
|
||||
case INSN_SYSCALL:
|
||||
case INSN_SYSRET:
|
||||
if (insn_func(insn))
|
||||
break;
|
||||
return 0;
|
||||
|
|
|
@ -19,7 +19,8 @@ enum insn_type {
|
|||
INSN_CALL,
|
||||
INSN_CALL_DYNAMIC,
|
||||
INSN_RETURN,
|
||||
INSN_CONTEXT_SWITCH,
|
||||
INSN_SYSCALL,
|
||||
INSN_SYSRET,
|
||||
INSN_BUG,
|
||||
INSN_NOP,
|
||||
INSN_STAC,
|
||||
|
|
Loading…
Add table
Reference in a new issue