]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
objtool: Separate prefix code from stack validation code
authorJosh Poimboeuf <jpoimboe@kernel.org>
Wed, 12 Apr 2023 20:26:13 +0000 (13:26 -0700)
committerPeter Zijlstra <peterz@infradead.org>
Fri, 14 Apr 2023 14:08:29 +0000 (16:08 +0200)
Simplify the prefix code by moving it after
validate_reachable_instructions().

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/d7f31ac2de462d0cd7b1db01b7ecb525c057c8f6.1681331135.git.jpoimboe@kernel.org
tools/objtool/check.c

index 1cf2e2841c474a45f42f9b0d858854be94e1c430..8ee4d51de6fa87e912980c4d5cd4674e9d515944 100644 (file)
@@ -4114,54 +4114,61 @@ static bool ignore_unreachable_insn(struct objtool_file *file, struct instructio
        return false;
 }
 
-static int add_prefix_symbol(struct objtool_file *file, struct symbol *func,
-                            struct instruction *insn)
+static int add_prefix_symbol(struct objtool_file *file, struct symbol *func)
 {
-       if (!opts.prefix)
-               return 0;
+       struct instruction *insn, *prev;
 
-       for (;;) {
-               struct instruction *prev = prev_insn_same_sec(file, insn);
-               u64 offset;
+       insn = find_insn(file, func->sec, func->offset);
+       if (!insn)
+               return -1;
 
-               if (!prev)
-                       break;
+       for (prev = prev_insn_same_sec(file, insn);
+            prev;
+            prev = prev_insn_same_sec(file, prev)) {
+               u64 offset;
 
                if (prev->type != INSN_NOP)
-                       break;
+                       return -1;
 
                offset = func->offset - prev->offset;
-               if (offset >= opts.prefix) {
-                       if (offset == opts.prefix) {
-                               /*
-                                * Since the sec->symbol_list is ordered by
-                                * offset (see elf_add_symbol()) the added
-                                * symbol will not be seen by the iteration in
-                                * validate_section().
-                                *
-                                * Hence the lack of list_for_each_entry_safe()
-                                * there.
-                                *
-                                * The direct concequence is that prefix symbols
-                                * don't get visited (because pointless), except
-                                * for the logic in ignore_unreachable_insn()
-                                * that needs the terminating insn to be visited
-                                * otherwise it will report the hole.
-                                *
-                                * Hence mark the first instruction of the
-                                * prefix symbol as visisted.
-                                */
-                               prev->visited |= VISITED_BRANCH;
-                               elf_create_prefix_symbol(file->elf, func, opts.prefix);
-                       }
-                       break;
-               }
-               insn = prev;
+
+               if (offset > opts.prefix)
+                       return -1;
+
+               if (offset < opts.prefix)
+                       continue;
+
+               elf_create_prefix_symbol(file->elf, func, opts.prefix);
+               break;
        }
 
+       if (!prev)
+               return -1;
+
        return 0;
 }
 
+static int add_prefix_symbols(struct objtool_file *file)
+{
+       struct section *sec;
+       struct symbol *func;
+       int warnings = 0;
+
+       for_each_sec(file, sec) {
+               if (!(sec->sh.sh_flags & SHF_EXECINSTR))
+                       continue;
+
+               sec_for_each_sym(sec, func) {
+                       if (func->type != STT_FUNC)
+                               continue;
+
+                       add_prefix_symbol(file, func);
+               }
+       }
+
+       return warnings;
+}
+
 static int validate_symbol(struct objtool_file *file, struct section *sec,
                           struct symbol *sym, struct insn_state *state)
 {
@@ -4180,8 +4187,6 @@ static int validate_symbol(struct objtool_file *file, struct section *sec,
        if (!insn || insn->ignore || insn->visited)
                return 0;
 
-       add_prefix_symbol(file, sym, insn);
-
        state->uaccess = sym->uaccess_safe;
 
        ret = validate_branch(file, insn_func(insn), insn, *state);
@@ -4621,6 +4626,13 @@ int check(struct objtool_file *file)
                warnings += ret;
        }
 
+       if (opts.prefix) {
+               ret = add_prefix_symbols(file);
+               if (ret < 0)
+                       return ret;
+               warnings += ret;
+       }
+
        if (opts.ibt) {
                ret = create_ibt_endbr_seal_sections(file);
                if (ret < 0)