diff options
-rw-r--r-- | tools/objtool/arch/x86/decode.c | 6 | ||||
-rw-r--r-- | tools/objtool/check.c | 43 |
2 files changed, 32 insertions, 17 deletions
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c index 0e8c8ec4fd4e..0f22768c0d4d 100644 --- a/tools/objtool/arch/x86/decode.c +++ b/tools/objtool/arch/x86/decode.c | |||
@@ -208,14 +208,14 @@ int arch_decode_instruction(struct elf *elf, struct section *sec, | |||
208 | break; | 208 | break; |
209 | 209 | ||
210 | case 0x89: | 210 | case 0x89: |
211 | if (rex == 0x48 && modrm == 0xe5) { | 211 | if (rex_w && !rex_r && modrm_mod == 3 && modrm_reg == 4) { |
212 | 212 | ||
213 | /* mov %rsp, %rbp */ | 213 | /* mov %rsp, reg */ |
214 | *type = INSN_STACK; | 214 | *type = INSN_STACK; |
215 | op->src.type = OP_SRC_REG; | 215 | op->src.type = OP_SRC_REG; |
216 | op->src.reg = CFI_SP; | 216 | op->src.reg = CFI_SP; |
217 | op->dest.type = OP_DEST_REG; | 217 | op->dest.type = OP_DEST_REG; |
218 | op->dest.reg = CFI_BP; | 218 | op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b]; |
219 | break; | 219 | break; |
220 | } | 220 | } |
221 | 221 | ||
diff --git a/tools/objtool/check.c b/tools/objtool/check.c index f744617c9946..a0c518ecf085 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c | |||
@@ -1203,24 +1203,39 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state) | |||
1203 | switch (op->src.type) { | 1203 | switch (op->src.type) { |
1204 | 1204 | ||
1205 | case OP_SRC_REG: | 1205 | 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 | } | ||
1207 | 1215 | ||
1208 | if (cfa->base == CFI_SP && | 1216 | else if (op->src.reg == CFI_SP && |
1209 | regs[CFI_BP].base == CFI_CFA && | 1217 | op->dest.reg == CFI_BP && state->drap) { |
1210 | regs[CFI_BP].offset == -cfa->offset) { | ||
1211 | 1218 | ||
1212 | /* mov %rsp, %rbp */ | 1219 | /* drap: mov %rsp, %rbp */ |
1213 | cfa->base = op->dest.reg; | 1220 | regs[CFI_BP].base = CFI_BP; |
1214 | state->bp_scratch = false; | 1221 | regs[CFI_BP].offset = -state->stack_size; |
1215 | } | 1222 | state->bp_scratch = false; |
1223 | } | ||
1216 | 1224 | ||
1217 | else if (state->drap) { | 1225 | else if (op->src.reg == CFI_SP && cfa->base == CFI_SP) { |
1218 | 1226 | ||
1219 | /* drap: mov %rsp, %rbp */ | 1227 | /* |
1220 | regs[CFI_BP].base = CFI_BP; | 1228 | * mov %rsp, %reg |
1221 | regs[CFI_BP].offset = -state->stack_size; | 1229 | * |
1222 | state->bp_scratch = false; | 1230 | * This is needed for the rare case where GCC |
1223 | } | 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; | ||
1224 | } | 1239 | } |
1225 | 1240 | ||
1226 | else if (op->dest.reg == cfa->base) { | 1241 | else if (op->dest.reg == cfa->base) { |