Skip to content

Commit 7fdaa64

Browse files
committed
objtool: Handle Clang RSP musical chairs
For no apparent reason (possibly related to CONFIG_KMSAN), Clang can randomly pass the value of RSP to other registers and then back again to RSP. Handle that accordingly. Fixes the following warnings: drivers/input/misc/uinput.o: warning: objtool: uinput_str_to_user+0x165: undefined stack state drivers/input/misc/uinput.o: warning: objtool: uinput_str_to_user+0x165: unknown CFA base reg -1 Reported-by: Arnd Bergmann <arnd@arndb.de> Closes: https://lore.kernel.org/90956545-2066-46e3-b547-10c884582eb0@app.fastmail.com Link: https://patch.msgid.link/240e6a172cc73292499334a3724d02ccb3247fc7.1772818491.git.jpoimboe@kernel.org Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
1 parent 1fd1dc4 commit 7fdaa64

2 files changed

Lines changed: 37 additions & 39 deletions

File tree

tools/objtool/arch/x86/decode.c

Lines changed: 23 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -395,52 +395,36 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
395395
if (!rex_w)
396396
break;
397397

398-
if (modrm_reg == CFI_SP) {
399-
400-
if (mod_is_reg()) {
401-
/* mov %rsp, reg */
402-
ADD_OP(op) {
403-
op->src.type = OP_SRC_REG;
404-
op->src.reg = CFI_SP;
405-
op->dest.type = OP_DEST_REG;
406-
op->dest.reg = modrm_rm;
407-
}
408-
break;
409-
410-
} else {
411-
/* skip RIP relative displacement */
412-
if (is_RIP())
413-
break;
414-
415-
/* skip nontrivial SIB */
416-
if (have_SIB()) {
417-
modrm_rm = sib_base;
418-
if (sib_index != CFI_SP)
419-
break;
420-
}
421-
422-
/* mov %rsp, disp(%reg) */
423-
ADD_OP(op) {
424-
op->src.type = OP_SRC_REG;
425-
op->src.reg = CFI_SP;
426-
op->dest.type = OP_DEST_REG_INDIRECT;
427-
op->dest.reg = modrm_rm;
428-
op->dest.offset = ins.displacement.value;
429-
}
430-
break;
398+
if (mod_is_reg()) {
399+
/* mov reg, reg */
400+
ADD_OP(op) {
401+
op->src.type = OP_SRC_REG;
402+
op->src.reg = modrm_reg;
403+
op->dest.type = OP_DEST_REG;
404+
op->dest.reg = modrm_rm;
431405
}
432-
433406
break;
434407
}
435408

436-
if (rm_is_reg(CFI_SP)) {
409+
/* skip RIP relative displacement */
410+
if (is_RIP())
411+
break;
437412

438-
/* mov reg, %rsp */
413+
/* skip nontrivial SIB */
414+
if (have_SIB()) {
415+
modrm_rm = sib_base;
416+
if (sib_index != CFI_SP)
417+
break;
418+
}
419+
420+
/* mov %rsp, disp(%reg) */
421+
if (modrm_reg == CFI_SP) {
439422
ADD_OP(op) {
440423
op->src.type = OP_SRC_REG;
441-
op->src.reg = modrm_reg;
442-
op->dest.type = OP_DEST_REG;
443-
op->dest.reg = CFI_SP;
424+
op->src.reg = CFI_SP;
425+
op->dest.type = OP_DEST_REG_INDIRECT;
426+
op->dest.reg = modrm_rm;
427+
op->dest.offset = ins.displacement.value;
444428
}
445429
break;
446430
}

tools/objtool/check.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3000,6 +3000,20 @@ static int update_cfi_state(struct instruction *insn,
30003000
cfi->stack_size += 8;
30013001
}
30023002

3003+
else if (cfi->vals[op->src.reg].base == CFI_CFA) {
3004+
/*
3005+
* Clang RSP musical chairs:
3006+
*
3007+
* mov %rsp, %rdx [handled above]
3008+
* ...
3009+
* mov %rdx, %rbx [handled here]
3010+
* ...
3011+
* mov %rbx, %rsp [handled above]
3012+
*/
3013+
cfi->vals[op->dest.reg].base = CFI_CFA;
3014+
cfi->vals[op->dest.reg].offset = cfi->vals[op->src.reg].offset;
3015+
}
3016+
30033017

30043018
break;
30053019

0 commit comments

Comments
 (0)