objtool,x86: Rewrite LEAVE
authorPeter Zijlstra <peterz@infradead.org>
Tue, 9 Feb 2021 20:41:13 +0000 (21:41 +0100)
committerIngo Molnar <mingo@kernel.org>
Sat, 6 Mar 2021 11:44:23 +0000 (12:44 +0100)
Since we can now have multiple stack-ops per instruction, we don't
need to special case LEAVE and can simply emit the composite
operations.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://lkml.kernel.org/r/20210211173627.253273977@infradead.org
tools/objtool/arch/x86/decode.c
tools/objtool/check.c
tools/objtool/include/objtool/arch.h

index d8f0138..47b9acf 100644 (file)
@@ -446,9 +446,17 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
                 * mov bp, sp
                 * pop bp
                 */
-               ADD_OP(op)
-                       op->dest.type = OP_DEST_LEAVE;
-
+               ADD_OP(op) {
+                       op->src.type = OP_SRC_REG;
+                       op->src.reg = CFI_BP;
+                       op->dest.type = OP_DEST_REG;
+                       op->dest.reg = CFI_SP;
+               }
+               ADD_OP(op) {
+                       op->src.type = OP_SRC_POP;
+                       op->dest.type = OP_DEST_REG;
+                       op->dest.reg = CFI_BP;
+               }
                break;
 
        case 0xe3:
index 12b8f0f..a0f762a 100644 (file)
@@ -2020,7 +2020,7 @@ static int update_cfi_state(struct instruction *insn,
                        }
 
                        else if (op->src.reg == CFI_BP && op->dest.reg == CFI_SP &&
-                                cfa->base == CFI_BP) {
+                                (cfa->base == CFI_BP || cfa->base == cfi->drap_reg)) {
 
                                /*
                                 * mov %rbp, %rsp
@@ -2217,7 +2217,7 @@ static int update_cfi_state(struct instruction *insn,
                                cfa->offset = 0;
                                cfi->drap_offset = -1;
 
-                       } else if (regs[op->dest.reg].offset == -cfi->stack_size) {
+                       } else if (cfi->stack_size == -regs[op->dest.reg].offset) {
 
                                /* pop %reg */
                                restore_reg(cfi, op->dest.reg);
@@ -2358,26 +2358,6 @@ static int update_cfi_state(struct instruction *insn,
 
                break;
 
-       case OP_DEST_LEAVE:
-               if ((!cfi->drap && cfa->base != CFI_BP) ||
-                   (cfi->drap && cfa->base != cfi->drap_reg)) {
-                       WARN_FUNC("leave instruction with modified stack frame",
-                                 insn->sec, insn->offset);
-                       return -1;
-               }
-
-               /* leave (mov %rbp, %rsp; pop %rbp) */
-
-               cfi->stack_size = -cfi->regs[CFI_BP].offset - 8;
-               restore_reg(cfi, CFI_BP);
-
-               if (!cfi->drap) {
-                       cfa->base = CFI_SP;
-                       cfa->offset -= 8;
-               }
-
-               break;
-
        case OP_DEST_MEM:
                if (op->src.type != OP_SRC_POP && op->src.type != OP_SRC_POPF) {
                        WARN_FUNC("unknown stack-related memory operation",
index 6ff0685..ff21f38 100644 (file)
@@ -35,7 +35,6 @@ enum op_dest_type {
        OP_DEST_MEM,
        OP_DEST_PUSH,
        OP_DEST_PUSHF,
-       OP_DEST_LEAVE,
 };
 
 struct op_dest {