Skip to content

Commit fe1042b

Browse files
jpoimboeIngo Molnar
authored andcommitted
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
1 parent a8df7d0 commit fe1042b

File tree

3 files changed

+17
-10
lines changed

3 files changed

+17
-10
lines changed

tools/objtool/arch/x86/decode.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
522522
case INAT_PFX_REPNE:
523523
if (modrm == 0xca)
524524
/* eretu/erets */
525-
insn->type = INSN_CONTEXT_SWITCH;
525+
insn->type = INSN_SYSRET;
526526
break;
527527
default:
528528
if (modrm == 0xca)
@@ -535,11 +535,15 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
535535

536536
insn->type = INSN_JUMP_CONDITIONAL;
537537

538-
} else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 ||
539-
op2 == 0x35) {
538+
} else if (op2 == 0x05 || op2 == 0x34) {
540539

541-
/* sysenter, sysret */
542-
insn->type = INSN_CONTEXT_SWITCH;
540+
/* syscall, sysenter */
541+
insn->type = INSN_SYSCALL;
542+
543+
} else if (op2 == 0x07 || op2 == 0x35) {
544+
545+
/* sysret, sysexit */
546+
insn->type = INSN_SYSRET;
543547

544548
} else if (op2 == 0x0b || op2 == 0xb9) {
545549

@@ -676,7 +680,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
676680

677681
case 0xca: /* retf */
678682
case 0xcb: /* retf */
679-
insn->type = INSN_CONTEXT_SWITCH;
683+
insn->type = INSN_SYSRET;
680684
break;
681685

682686
case 0xe0: /* loopne */
@@ -721,7 +725,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
721725
} else if (modrm_reg == 5) {
722726

723727
/* jmpf */
724-
insn->type = INSN_CONTEXT_SWITCH;
728+
insn->type = INSN_SYSRET;
725729

726730
} else if (modrm_reg == 6) {
727731

tools/objtool/check.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3684,7 +3684,8 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
36843684

36853685
break;
36863686

3687-
case INSN_CONTEXT_SWITCH:
3687+
case INSN_SYSCALL:
3688+
case INSN_SYSRET:
36883689
if (func) {
36893690
if (!next_insn || !next_insn->hint) {
36903691
WARN_INSN(insn, "unsupported instruction in callable function");
@@ -3886,7 +3887,8 @@ static int validate_unret(struct objtool_file *file, struct instruction *insn)
38863887
WARN_INSN(insn, "RET before UNTRAIN");
38873888
return 1;
38883889

3889-
case INSN_CONTEXT_SWITCH:
3890+
case INSN_SYSCALL:
3891+
case INSN_SYSRET:
38903892
if (insn_func(insn))
38913893
break;
38923894
return 0;

tools/objtool/include/objtool/arch.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ enum insn_type {
1919
INSN_CALL,
2020
INSN_CALL_DYNAMIC,
2121
INSN_RETURN,
22-
INSN_CONTEXT_SWITCH,
22+
INSN_SYSCALL,
23+
INSN_SYSRET,
2324
INSN_BUG,
2425
INSN_NOP,
2526
INSN_STAC,

0 commit comments

Comments
 (0)