mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 14:42:24 +00:00
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:dd88a0a0c8
("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: kbuild test robot <fengguang.wu@intel.com> Signed-off-by: Josh 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:dd88a0a0c8
("objtool: Handle GCC stack pointer adjustment bug") Link: http://lkml.kernel.org/r/8c7aa8e9a36fbbb6655d9d8e7cea58958c912da8.1505942196.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
4ba55e65f4
commit
0d0970eef3
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user