objtool: Convert {.UN}REACHABLE to ANNOTATE
authorPeter Zijlstra <peterz@infradead.org>
Thu, 28 Nov 2024 09:39:05 +0000 (10:39 +0100)
committerPeter Zijlstra <peterz@infradead.org>
Mon, 2 Dec 2024 11:01:44 +0000 (12:01 +0100)
Suggested-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Josh Poimboeuf <jpoimboe@kernel.org>
Link: https://lore.kernel.org/r/20241128094312.353431347@infradead.org
arch/loongarch/include/asm/bug.h
arch/x86/entry/entry_64.S
arch/x86/include/asm/bug.h
arch/x86/include/asm/irq_stack.h
include/linux/objtool.h
include/linux/objtool_types.h
tools/include/linux/objtool_types.h
tools/objtool/check.c

index 561ac1bf79e26c1b8721e5d9f60dc954494a3a27..e25404a938822450c8e223bec5f76db9a45691fb 100644 (file)
@@ -45,7 +45,7 @@
 #define __WARN_FLAGS(flags)                                    \
 do {                                                           \
        instrumentation_begin();                                \
-       __BUG_FLAGS(BUGFLAG_WARNING|(flags), ASM_REACHABLE);    \
+       __BUG_FLAGS(BUGFLAG_WARNING|(flags), ANNOTATE_REACHABLE);\
        instrumentation_end();                                  \
 } while (0)
 
index 1b5be07f86698a3b634a0d83b6578775781d1739..9248660ad4096acdb86d8b1842f81e1dc0dcfafe 100644 (file)
@@ -311,7 +311,7 @@ SYM_CODE_END(xen_error_entry)
        call    \cfunc
 
        /* For some configurations \cfunc ends up being a noreturn. */
-       REACHABLE
+       ANNOTATE_REACHABLE
 
        jmp     error_return
 .endm
@@ -532,7 +532,7 @@ SYM_CODE_START(\asmsym)
        call    \cfunc
 
        /* For some configurations \cfunc ends up being a noreturn. */
-       REACHABLE
+       ANNOTATE_REACHABLE
 
        jmp     paranoid_exit
 
index 806649c7f23dc627d4680fb0f64a7312468b14a3..dd8fb1779d972b3a2bce5517283167f721b12925 100644 (file)
@@ -92,7 +92,7 @@ do {                                                          \
 do {                                                           \
        __auto_type __flags = BUGFLAG_WARNING|(flags);          \
        instrumentation_begin();                                \
-       _BUG_FLAGS(ASM_UD2, __flags, ASM_REACHABLE);            \
+       _BUG_FLAGS(ASM_UD2, __flags, ANNOTATE_REACHABLE);       \
        instrumentation_end();                                  \
 } while (0)
 
index b71ad173f8776fa986840f4a6567c8ee588a8a51..5455747ed918e20cbc4f17b31b1ee809cb18bba7 100644 (file)
 
 #define ASM_CALL_ARG0                                                  \
        "call %c[__func]                                \n"             \
-       ASM_REACHABLE
+       ANNOTATE_REACHABLE
 
 #define ASM_CALL_ARG1                                                  \
        "movq   %[arg1], %%rdi                          \n"             \
index fd487d466bb2e34dc0594c8335346b3ec8d27d0e..e3cb13583fba29e42a7f5922fdf91fbe1b8e3e21 100644 (file)
 #endif
 .endm
 
-
-.macro REACHABLE
-.Lhere_\@:
-       .pushsection .discard.reachable
-       .long   .Lhere_\@
-       .popsection
-.endm
-
 .macro ANNOTATE type:req
 .Lhere_\@:
        .pushsection .discard.annotate_insn,"M",@progbits,8
 #define STACK_FRAME_NON_STANDARD_FP(func)
 #define __ASM_ANNOTATE(label, type)
 #define ASM_ANNOTATE(type)
-#define ASM_REACHABLE
 #else
 .macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0
 .endm
 .macro STACK_FRAME_NON_STANDARD func:req
 .endm
-.macro REACHABLE
-.endm
 .macro ANNOTATE type:req
 .endm
 #endif
  * it will be ignored.
  */
 #define ANNOTATE_UNRET_BEGIN           ASM_ANNOTATE(ANNOTYPE_UNRET_BEGIN)
+/*
+ * This should be used directly after an instruction that is considered
+ * terminating, like a noreturn CALL or UD2 when we know they are not -- eg
+ * WARN using UD2.
+ */
+#define ANNOTATE_REACHABLE             ASM_ANNOTATE(ANNOTYPE_REACHABLE)
 
 #else
 #define ANNOTATE_NOENDBR               ANNOTATE type=ANNOTYPE_NOENDBR
 #define ANNOTATE_IGNORE_ALTERNATIVE    ANNOTATE type=ANNOTYPE_IGNORE_ALTS
 #define ANNOTATE_INTRA_FUNCTION_CALL   ANNOTATE type=ANNOTYPE_INTRA_FUNCTION_CALL
 #define ANNOTATE_UNRET_BEGIN           ANNOTATE type=ANNOTYPE_UNRET_BEGIN
+#define ANNOTATE_REACHABLE             ANNOTATE type=ANNOTYPE_REACHABLE
 #endif
 
 #if defined(CONFIG_NOINSTR_VALIDATION) && \
index 23d6fb6d04c70fbd79c686880ab006158a786e89..df5d9fa84dba339b7c14a57667f8e534db3e236e 100644 (file)
@@ -64,5 +64,6 @@ struct unwind_hint {
 #define ANNOTYPE_UNRET_BEGIN           5
 #define ANNOTYPE_IGNORE_ALTS           6
 #define ANNOTYPE_INTRA_FUNCTION_CALL   7
+#define ANNOTYPE_REACHABLE             8
 
 #endif /* _LINUX_OBJTOOL_TYPES_H */
index 23d6fb6d04c70fbd79c686880ab006158a786e89..df5d9fa84dba339b7c14a57667f8e534db3e236e 100644 (file)
@@ -64,5 +64,6 @@ struct unwind_hint {
 #define ANNOTYPE_UNRET_BEGIN           5
 #define ANNOTYPE_IGNORE_ALTS           6
 #define ANNOTYPE_INTRA_FUNCTION_CALL   7
+#define ANNOTYPE_REACHABLE             8
 
 #endif /* _LINUX_OBJTOOL_TYPES_H */
index 798cff5bffc42c3a41ff2748c311b9b9f2dd1308..27d0c41535829683394de6c98440f939e2cb6199 100644 (file)
@@ -627,56 +627,6 @@ static struct instruction *find_last_insn(struct objtool_file *file,
        return insn;
 }
 
-/*
- * Mark "ud2" instructions and manually annotated dead ends.
- */
-static int add_dead_ends(struct objtool_file *file)
-{
-       struct section *rsec;
-       struct reloc *reloc;
-       struct instruction *insn;
-       uint64_t offset;
-
-       /*
-        * UD2 defaults to being a dead-end, allow them to be annotated for
-        * non-fatal, eg WARN.
-        */
-       rsec = find_section_by_name(file->elf, ".rela.discard.reachable");
-       if (!rsec)
-               return 0;
-
-       for_each_reloc(rsec, reloc) {
-               if (reloc->sym->type == STT_SECTION) {
-                       offset = reloc_addend(reloc);
-               } else if (reloc->sym->local_label) {
-                       offset = reloc->sym->offset;
-               } else {
-                       WARN("unexpected relocation symbol type in %s", rsec->name);
-                       return -1;
-               }
-
-               insn = find_insn(file, reloc->sym->sec, offset);
-               if (insn)
-                       insn = prev_insn_same_sec(file, insn);
-               else if (offset == reloc->sym->sec->sh.sh_size) {
-                       insn = find_last_insn(file, reloc->sym->sec);
-                       if (!insn) {
-                               WARN("can't find reachable insn at %s+0x%" PRIx64,
-                                    reloc->sym->sec->name, offset);
-                               return -1;
-                       }
-               } else {
-                       WARN("can't find reachable insn at %s+0x%" PRIx64,
-                            reloc->sym->sec->name, offset);
-                       return -1;
-               }
-
-               insn->dead_end = false;
-       }
-
-       return 0;
-}
-
 static int create_static_call_sections(struct objtool_file *file)
 {
        struct static_call_site *site;
@@ -2306,6 +2256,7 @@ static int read_annotate(struct objtool_file *file,
        struct section *sec;
        struct instruction *insn;
        struct reloc *reloc;
+       uint64_t offset;
        int type, ret;
 
        sec = find_section_by_name(file->elf, ".discard.annotate_insn");
@@ -2327,8 +2278,19 @@ static int read_annotate(struct objtool_file *file,
        for_each_reloc(sec->rsec, reloc) {
                type = *(u32 *)(sec->data->d_buf + (reloc_idx(reloc) * sec->sh.sh_entsize) + 4);
 
-               insn = find_insn(file, reloc->sym->sec,
-                                reloc->sym->offset + reloc_addend(reloc));
+               offset = reloc->sym->offset + reloc_addend(reloc);
+               insn = find_insn(file, reloc->sym->sec, offset);
+
+               /*
+                * Reachable annotations are 'funneh' and act on the previous instruction :/
+                */
+               if (type == ANNOTYPE_REACHABLE) {
+                       if (insn)
+                               insn = prev_insn_same_sec(file, insn);
+                       else if (offset == reloc->sym->sec->sh.sh_size)
+                               insn = find_last_insn(file, reloc->sym->sec);
+               }
+
                if (!insn) {
                        WARN("bad .discard.annotate_insn entry: %d of type %d", reloc_idx(reloc), type);
                        return -1;
@@ -2420,6 +2382,10 @@ static int __annotate_late(struct objtool_file *file, int type, struct instructi
                insn->unret = 1;
                break;
 
+       case ANNOTYPE_REACHABLE:
+               insn->dead_end = false;
+               break;
+
        default:
                break;
        }
@@ -2566,14 +2532,6 @@ static int decode_sections(struct objtool_file *file)
        if (ret)
                return ret;
 
-       /*
-        * Must be after add_call_destinations() such that it can override
-        * dead_end_function() marks.
-        */
-       ret = add_dead_ends(file);
-       if (ret)
-               return ret;
-
        ret = add_jump_table_alts(file);
        if (ret)
                return ret;
@@ -2582,6 +2540,10 @@ static int decode_sections(struct objtool_file *file)
        if (ret)
                return ret;
 
+       /*
+        * Must be after add_call_destinations() such that it can override
+        * dead_end_function() marks.
+        */
        ret = read_annotate(file, __annotate_late);
        if (ret)
                return ret;