Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0d0970ee authored by Josh Poimboeuf's avatar Josh Poimboeuf Committed by Ingo Molnar
Browse files

objtool: Handle another GCC stack pointer adjustment bug



The kbuild bot reported the following warning with GCC 4.4 and a
randconfig:

  net/socket.o: warning: objtool: compat_sock_ioctl()+0x1083: stack state mismatch: cfa1=7+160 cfa2=-1+0

This is caused by another GCC non-optimization, where it backs up and
restores the stack pointer for no apparent reason:

    2f91:       48 89 e0                mov    %rsp,%rax
    2f94:       4c 89 e7                mov    %r12,%rdi
    2f97:       4c 89 f6                mov    %r14,%rsi
    2f9a:       ba 20 00 00 00          mov    $0x20,%edx
    2f9f:       48 89 c4                mov    %rax,%rsp

This issue would have been happily ignored before the following commit:

  dd88a0a0 ("objtool: Handle GCC stack pointer adjustment bug")

But now that objtool is paying attention to such stack pointer writes
to/from a register, it needs to understand them properly.  In this case
that means recognizing that the "mov %rsp, %rax" instruction is
potentially a backup of the stack pointer.

Reported-by: default avatarkbuild test robot <fengguang.wu@intel.com>
Signed-off-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Dmitriy Vyukov <dvyukov@google.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Matthias Kaehlcke <mka@chromium.org>
Cc: Miguel Bernal Marin <miguel.bernal.marin@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Fixes: dd88a0a0 ("objtool: Handle GCC stack pointer adjustment bug")
Link: http://lkml.kernel.org/r/8c7aa8e9a36fbbb6655d9d8e7cea58958c912da8.1505942196.git.jpoimboe@redhat.com


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 4ba55e65
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -208,14 +208,14 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
		break;

	case 0x89:
		if (rex == 0x48 && modrm == 0xe5) {
		if (rex_w && !rex_r && modrm_mod == 3 && modrm_reg == 4) {

			/* mov %rsp, %rbp */
			/* mov %rsp, reg */
			*type = INSN_STACK;
			op->src.type = OP_SRC_REG;
			op->src.reg = CFI_SP;
			op->dest.type = OP_DEST_REG;
			op->dest.reg = CFI_BP;
			op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b];
			break;
		}

+29 −14
Original line number Diff line number Diff line
@@ -1203,9 +1203,8 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
		switch (op->src.type) {

		case OP_SRC_REG:
			if (op->src.reg == CFI_SP && op->dest.reg == CFI_BP) {

				if (cfa->base == CFI_SP &&
			if (op->src.reg == CFI_SP && op->dest.reg == CFI_BP &&
			    cfa->base == CFI_SP &&
			    regs[CFI_BP].base == CFI_CFA &&
			    regs[CFI_BP].offset == -cfa->offset) {

@@ -1214,13 +1213,29 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
				state->bp_scratch = false;
			}

				else if (state->drap) {
			else if (op->src.reg == CFI_SP &&
				 op->dest.reg == CFI_BP && state->drap) {

				/* drap: mov %rsp, %rbp */
				regs[CFI_BP].base = CFI_BP;
				regs[CFI_BP].offset = -state->stack_size;
				state->bp_scratch = false;
			}

			else if (op->src.reg == CFI_SP && cfa->base == CFI_SP) {

				/*
				 * mov %rsp, %reg
				 *
				 * This is needed for the rare case where GCC
				 * does:
				 *
				 *   mov    %rsp, %rax
				 *   ...
				 *   mov    %rax, %rsp
				 */
				state->vals[op->dest.reg].base = CFI_CFA;
				state->vals[op->dest.reg].offset = -state->stack_size;
			}

			else if (op->dest.reg == cfa->base) {