Skip to content

Commit 0d0970e

Browse files
jpoimboeIngo Molnar
authored andcommitted
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: dd88a0a ("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 <[email protected]> Signed-off-by: Josh Poimboeuf <[email protected]> Cc: Alexander Potapenko <[email protected]> Cc: Andrey Ryabinin <[email protected]> Cc: Andy Lutomirski <[email protected]> Cc: Arnd Bergmann <[email protected]> Cc: Dmitriy Vyukov <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Matthias Kaehlcke <[email protected]> Cc: Miguel Bernal Marin <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Fixes: dd88a0a ("objtool: Handle GCC stack pointer adjustment bug") Link: http://lkml.kernel.org/r/8c7aa8e9a36fbbb6655d9d8e7cea58958c912da8.1505942196.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar <[email protected]>
1 parent 4ba55e6 commit 0d0970e

File tree

2 files changed

+32
-17
lines changed

2 files changed

+32
-17
lines changed

tools/objtool/arch/x86/decode.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,14 +208,14 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
208208
break;
209209

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

213-
/* mov %rsp, %rbp */
213+
/* mov %rsp, reg */
214214
*type = INSN_STACK;
215215
op->src.type = OP_SRC_REG;
216216
op->src.reg = CFI_SP;
217217
op->dest.type = OP_DEST_REG;
218-
op->dest.reg = CFI_BP;
218+
op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b];
219219
break;
220220
}
221221

tools/objtool/check.c

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,24 +1203,39 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
12031203
switch (op->src.type) {
12041204

12051205
case OP_SRC_REG:
1206-
if (op->src.reg == CFI_SP && op->dest.reg == CFI_BP) {
1206+
if (op->src.reg == CFI_SP && op->dest.reg == CFI_BP &&
1207+
cfa->base == CFI_SP &&
1208+
regs[CFI_BP].base == CFI_CFA &&
1209+
regs[CFI_BP].offset == -cfa->offset) {
1210+
1211+
/* mov %rsp, %rbp */
1212+
cfa->base = op->dest.reg;
1213+
state->bp_scratch = false;
1214+
}
12071215

1208-
if (cfa->base == CFI_SP &&
1209-
regs[CFI_BP].base == CFI_CFA &&
1210-
regs[CFI_BP].offset == -cfa->offset) {
1216+
else if (op->src.reg == CFI_SP &&
1217+
op->dest.reg == CFI_BP && state->drap) {
12111218

1212-
/* mov %rsp, %rbp */
1213-
cfa->base = op->dest.reg;
1214-
state->bp_scratch = false;
1215-
}
1219+
/* drap: mov %rsp, %rbp */
1220+
regs[CFI_BP].base = CFI_BP;
1221+
regs[CFI_BP].offset = -state->stack_size;
1222+
state->bp_scratch = false;
1223+
}
12161224

1217-
else if (state->drap) {
1225+
else if (op->src.reg == CFI_SP && cfa->base == CFI_SP) {
12181226

1219-
/* drap: mov %rsp, %rbp */
1220-
regs[CFI_BP].base = CFI_BP;
1221-
regs[CFI_BP].offset = -state->stack_size;
1222-
state->bp_scratch = false;
1223-
}
1227+
/*
1228+
* mov %rsp, %reg
1229+
*
1230+
* This is needed for the rare case where GCC
1231+
* does:
1232+
*
1233+
* mov %rsp, %rax
1234+
* ...
1235+
* mov %rax, %rsp
1236+
*/
1237+
state->vals[op->dest.reg].base = CFI_CFA;
1238+
state->vals[op->dest.reg].offset = -state->stack_size;
12241239
}
12251240

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

0 commit comments

Comments
 (0)