Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

objtool: Convert {.UN}REACHABLE to ANNOTATE

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

+36 -76
+1 -1
arch/loongarch/include/asm/bug.h
··· 45 45 #define __WARN_FLAGS(flags) \ 46 46 do { \ 47 47 instrumentation_begin(); \ 48 - __BUG_FLAGS(BUGFLAG_WARNING|(flags), ASM_REACHABLE); \ 48 + __BUG_FLAGS(BUGFLAG_WARNING|(flags), ANNOTATE_REACHABLE);\ 49 49 instrumentation_end(); \ 50 50 } while (0) 51 51
+2 -2
arch/x86/entry/entry_64.S
··· 311 311 call \cfunc 312 312 313 313 /* For some configurations \cfunc ends up being a noreturn. */ 314 - REACHABLE 314 + ANNOTATE_REACHABLE 315 315 316 316 jmp error_return 317 317 .endm ··· 532 532 call \cfunc 533 533 534 534 /* For some configurations \cfunc ends up being a noreturn. */ 535 - REACHABLE 535 + ANNOTATE_REACHABLE 536 536 537 537 jmp paranoid_exit 538 538
+1 -1
arch/x86/include/asm/bug.h
··· 92 92 do { \ 93 93 __auto_type __flags = BUGFLAG_WARNING|(flags); \ 94 94 instrumentation_begin(); \ 95 - _BUG_FLAGS(ASM_UD2, __flags, ASM_REACHABLE); \ 95 + _BUG_FLAGS(ASM_UD2, __flags, ANNOTATE_REACHABLE); \ 96 96 instrumentation_end(); \ 97 97 } while (0) 98 98
+1 -1
arch/x86/include/asm/irq_stack.h
··· 101 101 102 102 #define ASM_CALL_ARG0 \ 103 103 "call %c[__func] \n" \ 104 - ASM_REACHABLE 104 + ANNOTATE_REACHABLE 105 105 106 106 #define ASM_CALL_ARG1 \ 107 107 "movq %[arg1], %%rdi \n" \
+7 -11
include/linux/objtool.h
··· 111 111 #endif 112 112 .endm 113 113 114 - 115 - .macro REACHABLE 116 - .Lhere_\@: 117 - .pushsection .discard.reachable 118 - .long .Lhere_\@ 119 - .popsection 120 - .endm 121 - 122 114 .macro ANNOTATE type:req 123 115 .Lhere_\@: 124 116 .pushsection .discard.annotate_insn,"M",@progbits,8 ··· 130 138 #define STACK_FRAME_NON_STANDARD_FP(func) 131 139 #define __ASM_ANNOTATE(label, type) 132 140 #define ASM_ANNOTATE(type) 133 - #define ASM_REACHABLE 134 141 #else 135 142 .macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0 136 143 .endm 137 144 .macro STACK_FRAME_NON_STANDARD func:req 138 - .endm 139 - .macro REACHABLE 140 145 .endm 141 146 .macro ANNOTATE type:req 142 147 .endm ··· 176 187 * it will be ignored. 177 188 */ 178 189 #define ANNOTATE_UNRET_BEGIN ASM_ANNOTATE(ANNOTYPE_UNRET_BEGIN) 190 + /* 191 + * This should be used directly after an instruction that is considered 192 + * terminating, like a noreturn CALL or UD2 when we know they are not -- eg 193 + * WARN using UD2. 194 + */ 195 + #define ANNOTATE_REACHABLE ASM_ANNOTATE(ANNOTYPE_REACHABLE) 179 196 180 197 #else 181 198 #define ANNOTATE_NOENDBR ANNOTATE type=ANNOTYPE_NOENDBR ··· 191 196 #define ANNOTATE_IGNORE_ALTERNATIVE ANNOTATE type=ANNOTYPE_IGNORE_ALTS 192 197 #define ANNOTATE_INTRA_FUNCTION_CALL ANNOTATE type=ANNOTYPE_INTRA_FUNCTION_CALL 193 198 #define ANNOTATE_UNRET_BEGIN ANNOTATE type=ANNOTYPE_UNRET_BEGIN 199 + #define ANNOTATE_REACHABLE ANNOTATE type=ANNOTYPE_REACHABLE 194 200 #endif 195 201 196 202 #if defined(CONFIG_NOINSTR_VALIDATION) && \
+1
include/linux/objtool_types.h
··· 64 64 #define ANNOTYPE_UNRET_BEGIN 5 65 65 #define ANNOTYPE_IGNORE_ALTS 6 66 66 #define ANNOTYPE_INTRA_FUNCTION_CALL 7 67 + #define ANNOTYPE_REACHABLE 8 67 68 68 69 #endif /* _LINUX_OBJTOOL_TYPES_H */
+1
tools/include/linux/objtool_types.h
··· 64 64 #define ANNOTYPE_UNRET_BEGIN 5 65 65 #define ANNOTYPE_IGNORE_ALTS 6 66 66 #define ANNOTYPE_INTRA_FUNCTION_CALL 7 67 + #define ANNOTYPE_REACHABLE 8 67 68 68 69 #endif /* _LINUX_OBJTOOL_TYPES_H */
+22 -60
tools/objtool/check.c
··· 627 627 return insn; 628 628 } 629 629 630 - /* 631 - * Mark "ud2" instructions and manually annotated dead ends. 632 - */ 633 - static int add_dead_ends(struct objtool_file *file) 634 - { 635 - struct section *rsec; 636 - struct reloc *reloc; 637 - struct instruction *insn; 638 - uint64_t offset; 639 - 640 - /* 641 - * UD2 defaults to being a dead-end, allow them to be annotated for 642 - * non-fatal, eg WARN. 643 - */ 644 - rsec = find_section_by_name(file->elf, ".rela.discard.reachable"); 645 - if (!rsec) 646 - return 0; 647 - 648 - for_each_reloc(rsec, reloc) { 649 - if (reloc->sym->type == STT_SECTION) { 650 - offset = reloc_addend(reloc); 651 - } else if (reloc->sym->local_label) { 652 - offset = reloc->sym->offset; 653 - } else { 654 - WARN("unexpected relocation symbol type in %s", rsec->name); 655 - return -1; 656 - } 657 - 658 - insn = find_insn(file, reloc->sym->sec, offset); 659 - if (insn) 660 - insn = prev_insn_same_sec(file, insn); 661 - else if (offset == reloc->sym->sec->sh.sh_size) { 662 - insn = find_last_insn(file, reloc->sym->sec); 663 - if (!insn) { 664 - WARN("can't find reachable insn at %s+0x%" PRIx64, 665 - reloc->sym->sec->name, offset); 666 - return -1; 667 - } 668 - } else { 669 - WARN("can't find reachable insn at %s+0x%" PRIx64, 670 - reloc->sym->sec->name, offset); 671 - return -1; 672 - } 673 - 674 - insn->dead_end = false; 675 - } 676 - 677 - return 0; 678 - } 679 - 680 630 static int create_static_call_sections(struct objtool_file *file) 681 631 { 682 632 struct static_call_site *site; ··· 2256 2306 struct section *sec; 2257 2307 struct instruction *insn; 2258 2308 struct reloc *reloc; 2309 + uint64_t offset; 2259 2310 int type, ret; 2260 2311 2261 2312 sec = find_section_by_name(file->elf, ".discard.annotate_insn"); ··· 2278 2327 for_each_reloc(sec->rsec, reloc) { 2279 2328 type = *(u32 *)(sec->data->d_buf + (reloc_idx(reloc) * sec->sh.sh_entsize) + 4); 2280 2329 2281 - insn = find_insn(file, reloc->sym->sec, 2282 - reloc->sym->offset + reloc_addend(reloc)); 2330 + offset = reloc->sym->offset + reloc_addend(reloc); 2331 + insn = find_insn(file, reloc->sym->sec, offset); 2332 + 2333 + /* 2334 + * Reachable annotations are 'funneh' and act on the previous instruction :/ 2335 + */ 2336 + if (type == ANNOTYPE_REACHABLE) { 2337 + if (insn) 2338 + insn = prev_insn_same_sec(file, insn); 2339 + else if (offset == reloc->sym->sec->sh.sh_size) 2340 + insn = find_last_insn(file, reloc->sym->sec); 2341 + } 2342 + 2283 2343 if (!insn) { 2284 2344 WARN("bad .discard.annotate_insn entry: %d of type %d", reloc_idx(reloc), type); 2285 2345 return -1; ··· 2380 2418 2381 2419 case ANNOTYPE_UNRET_BEGIN: 2382 2420 insn->unret = 1; 2421 + break; 2422 + 2423 + case ANNOTYPE_REACHABLE: 2424 + insn->dead_end = false; 2383 2425 break; 2384 2426 2385 2427 default: ··· 2532 2566 if (ret) 2533 2567 return ret; 2534 2568 2535 - /* 2536 - * Must be after add_call_destinations() such that it can override 2537 - * dead_end_function() marks. 2538 - */ 2539 - ret = add_dead_ends(file); 2540 - if (ret) 2541 - return ret; 2542 - 2543 2569 ret = add_jump_table_alts(file); 2544 2570 if (ret) 2545 2571 return ret; ··· 2540 2582 if (ret) 2541 2583 return ret; 2542 2584 2585 + /* 2586 + * Must be after add_call_destinations() such that it can override 2587 + * dead_end_function() marks. 2588 + */ 2543 2589 ret = read_annotate(file, __annotate_late); 2544 2590 if (ret) 2545 2591 return ret;