aboutsummaryrefslogtreecommitdiffstats
path: root/tools/objtool/check.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/objtool/check.c')
-rw-r--r--tools/objtool/check.c43
1 files changed, 29 insertions, 14 deletions
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) {