objtool: Allow stack operations in UNWIND_HINT_UNDEFINED regions
authorJosh Poimboeuf <jpoimboe@kernel.org>
Mon, 5 Jun 2023 16:12:21 +0000 (09:12 -0700)
committerJosh Poimboeuf <jpoimboe@kernel.org>
Wed, 7 Jun 2023 17:03:11 +0000 (10:03 -0700)
If the code specified UNWIND_HINT_UNDEFINED, skip the "undefined stack
state" warning due to a stack operation.  Just ignore the stack op and
continue to propagate the undefined state.

Link: https://lore.kernel.org/r/820c5b433f17c84e8761fb7465a8d319d706b1cf.1685981486.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
tools/objtool/check.c
tools/objtool/include/objtool/cfi.h

index 4b869de7e827c3d9892438a4fa3316dbd17d37c7..b11c25a715acd7364f5b9d3343d6d34b818bf4fd 100644 (file)
@@ -33,6 +33,7 @@ static unsigned long nr_cfi, nr_cfi_reused, nr_cfi_cache;
 static struct cfi_init_state initial_func_cfi;
 static struct cfi_state init_cfi;
 static struct cfi_state func_cfi;
+static struct cfi_state force_undefined_cfi;
 
 struct instruction *find_insn(struct objtool_file *file,
                              struct section *sec, unsigned long offset)
@@ -2240,6 +2241,11 @@ static int read_unwind_hints(struct objtool_file *file)
 
                insn->hint = true;
 
+               if (hint->type == UNWIND_HINT_TYPE_UNDEFINED) {
+                       insn->cfi = &force_undefined_cfi;
+                       continue;
+               }
+
                if (hint->type == UNWIND_HINT_TYPE_SAVE) {
                        insn->hint = false;
                        insn->save = true;
@@ -2793,6 +2799,10 @@ static int update_cfi_state(struct instruction *insn,
        struct cfi_reg *cfa = &cfi->cfa;
        struct cfi_reg *regs = cfi->regs;
 
+       /* ignore UNWIND_HINT_UNDEFINED regions */
+       if (cfi->force_undefined)
+               return 0;
+
        /* stack operations don't make sense with an undefined CFA */
        if (cfa->base == CFI_UNDEFINED) {
                if (insn_func(insn)) {
@@ -4607,6 +4617,8 @@ int check(struct objtool_file *file)
        init_cfi_state(&init_cfi);
        init_cfi_state(&func_cfi);
        set_func_state(&func_cfi);
+       init_cfi_state(&force_undefined_cfi);
+       force_undefined_cfi.force_undefined = true;
 
        if (!cfi_hash_alloc(1UL << (file->elf->symbol_bits - 3)))
                goto out;
index b1258e79a1b7e34262475961a20ea8399ce48055..c8a6bec4f6b91ea7f3564d50801d9acddf0d4612 100644 (file)
@@ -36,6 +36,7 @@ struct cfi_state {
        bool drap;
        bool signal;
        bool end;
+       bool force_undefined;
 };
 
 #endif /* _OBJTOOL_CFI_H */