Lines Matching refs:insn
25 struct instruction *insn; member
34 struct instruction *insn; in find_insn() local
36 hash_for_each_possible(file->insn_hash, insn, hash, sec_offset_hash(sec, offset)) { in find_insn()
37 if (insn->sec == sec && insn->offset == offset) in find_insn()
38 return insn; in find_insn()
45 struct instruction *insn) in next_insn_same_sec() argument
47 struct instruction *next = list_next_entry(insn, list); in next_insn_same_sec()
49 if (!next || &next->list == &file->insn_list || next->sec != insn->sec) in next_insn_same_sec()
56 struct instruction *insn) in next_insn_same_func() argument
58 struct instruction *next = list_next_entry(insn, list); in next_insn_same_func()
59 struct symbol *func = insn->func; in next_insn_same_func()
76 struct instruction *insn) in prev_insn_same_sym() argument
78 struct instruction *prev = list_prev_entry(insn, list); in prev_insn_same_sym()
80 if (&prev->list != &file->insn_list && prev->func == insn->func) in prev_insn_same_sym()
86 #define func_for_each_insn(file, func, insn) \ argument
87 for (insn = find_insn(file, func->sec, func->offset); \
88 insn; \
89 insn = next_insn_same_func(file, insn))
91 #define sym_for_each_insn(file, sym, insn) \ argument
92 for (insn = find_insn(file, sym->sec, sym->offset); \
93 insn && &insn->list != &file->insn_list && \
94 insn->sec == sym->sec && \
95 insn->offset < sym->offset + sym->len; \
96 insn = list_next_entry(insn, list))
98 #define sym_for_each_insn_continue_reverse(file, sym, insn) \ argument
99 for (insn = list_prev_entry(insn, list); \
100 &insn->list != &file->insn_list && \
101 insn->sec == sym->sec && insn->offset >= sym->offset; \
102 insn = list_prev_entry(insn, list))
104 #define sec_for_each_insn_from(file, insn) \ argument
105 for (; insn; insn = next_insn_same_sec(file, insn))
107 #define sec_for_each_insn_continue(file, insn) \ argument
108 for (insn = next_insn_same_sec(file, insn); insn; \
109 insn = next_insn_same_sec(file, insn))
111 static bool is_jump_table_jump(struct instruction *insn) in is_jump_table_jump() argument
113 struct alt_group *alt_group = insn->alt_group; in is_jump_table_jump()
115 if (insn->jump_table) in is_jump_table_jump()
123 static bool is_sibling_call(struct instruction *insn) in is_sibling_call() argument
130 if (!insn->func) in is_sibling_call()
134 if (insn->type == INSN_JUMP_DYNAMIC) in is_sibling_call()
135 return !is_jump_table_jump(insn); in is_sibling_call()
138 return (is_static_jump(insn) && insn->call_dest); in is_sibling_call()
154 struct instruction *insn; in __dead_end_function() local
192 insn = find_insn(file, func->sec, func->offset); in __dead_end_function()
193 if (!insn->func) in __dead_end_function()
196 func_for_each_insn(file, func, insn) { in __dead_end_function()
199 if (insn->type == INSN_RETURN) in __dead_end_function()
211 func_for_each_insn(file, func, insn) { in __dead_end_function()
212 if (is_sibling_call(insn)) { in __dead_end_function()
213 struct instruction *dest = insn->jump_dest; in __dead_end_function()
277 struct instruction *insn; in decode_instructions() local
295 for (offset = 0; offset < sec->sh.sh_size; offset += insn->len) { in decode_instructions()
296 insn = malloc(sizeof(*insn)); in decode_instructions()
297 if (!insn) { in decode_instructions()
301 memset(insn, 0, sizeof(*insn)); in decode_instructions()
302 INIT_LIST_HEAD(&insn->alts); in decode_instructions()
303 INIT_LIST_HEAD(&insn->stack_ops); in decode_instructions()
304 init_cfi_state(&insn->cfi); in decode_instructions()
306 insn->sec = sec; in decode_instructions()
307 insn->offset = offset; in decode_instructions()
311 &insn->len, &insn->type, in decode_instructions()
312 &insn->immediate, in decode_instructions()
313 &insn->stack_ops); in decode_instructions()
317 hash_add(file->insn_hash, &insn->hash, sec_offset_hash(sec, insn->offset)); in decode_instructions()
318 list_add_tail(&insn->list, &file->insn_list); in decode_instructions()
332 sym_for_each_insn(file, func, insn) in decode_instructions()
333 insn->func = func; in decode_instructions()
343 free(insn); in decode_instructions()
350 struct instruction *insn = NULL; in find_last_insn() local
354 for (offset = sec->sh.sh_size - 1; offset >= end && !insn; offset--) in find_last_insn()
355 insn = find_insn(file, sec, offset); in find_last_insn()
357 return insn; in find_last_insn()
367 struct instruction *insn; in add_dead_ends() local
373 for_each_insn(file, insn) in add_dead_ends()
374 if (insn->type == INSN_BUG) in add_dead_ends()
375 insn->dead_end = true; in add_dead_ends()
389 insn = find_insn(file, reloc->sym->sec, reloc->addend); in add_dead_ends()
390 if (insn) in add_dead_ends()
391 insn = list_prev_entry(insn, list); in add_dead_ends()
393 insn = find_last_insn(file, reloc->sym->sec); in add_dead_ends()
394 if (!insn) { in add_dead_ends()
405 insn->dead_end = true; in add_dead_ends()
424 insn = find_insn(file, reloc->sym->sec, reloc->addend); in add_dead_ends()
425 if (insn) in add_dead_ends()
426 insn = list_prev_entry(insn, list); in add_dead_ends()
428 insn = find_last_insn(file, reloc->sym->sec); in add_dead_ends()
429 if (!insn) { in add_dead_ends()
440 insn->dead_end = false; in add_dead_ends()
450 struct instruction *insn; in create_static_call_sections() local
466 list_for_each_entry(insn, &file->static_call_list, call_node) in create_static_call_sections()
475 list_for_each_entry(insn, &file->static_call_list, call_node) { in create_static_call_sections()
484 insn->sec, insn->offset)) in create_static_call_sections()
488 key_name = strdup(insn->call_dest->name); in create_static_call_sections()
517 key_sym = insn->call_dest; in create_static_call_sections()
525 is_sibling_call(insn) * STATIC_CALL_SITE_TAIL)) in create_static_call_sections()
538 struct instruction *insn; in create_mcount_loc_sections() local
552 list_for_each_entry(insn, &file->mcount_loc_list, mcount_loc_node) in create_mcount_loc_sections()
560 list_for_each_entry(insn, &file->mcount_loc_list, mcount_loc_node) { in create_mcount_loc_sections()
568 insn->sec, insn->offset)) in create_mcount_loc_sections()
582 struct instruction *insn; in add_ignores() local
608 func_for_each_insn(file, func, insn) in add_ignores()
609 insn->ignore = true; in add_ignores()
783 struct instruction *insn; in add_ignore_alternatives() local
795 insn = find_insn(file, reloc->sym->sec, reloc->addend); in add_ignore_alternatives()
796 if (!insn) { in add_ignore_alternatives()
801 insn->ignore_alts = true; in add_ignore_alternatives()
814 static struct reloc *insn_reloc(struct objtool_file *file, struct instruction *insn) in insn_reloc() argument
816 if (insn->reloc == NEGATIVE_RELOC) in insn_reloc()
819 if (!insn->reloc) { in insn_reloc()
820 insn->reloc = find_reloc_by_dest_range(file->elf, insn->sec, in insn_reloc()
821 insn->offset, insn->len); in insn_reloc()
822 if (!insn->reloc) { in insn_reloc()
823 insn->reloc = NEGATIVE_RELOC; in insn_reloc()
828 return insn->reloc; in insn_reloc()
836 struct instruction *insn; in add_jump_destinations() local
841 for_each_insn(file, insn) { in add_jump_destinations()
842 if (!is_static_jump(insn)) in add_jump_destinations()
845 reloc = insn_reloc(file, insn); in add_jump_destinations()
847 dest_sec = insn->sec; in add_jump_destinations()
848 dest_off = arch_jump_destination(insn); in add_jump_destinations()
857 if (insn->type == INSN_JUMP_UNCONDITIONAL) in add_jump_destinations()
858 insn->type = INSN_JUMP_DYNAMIC; in add_jump_destinations()
860 insn->type = INSN_JUMP_DYNAMIC_CONDITIONAL; in add_jump_destinations()
862 list_add_tail(&insn->call_node, in add_jump_destinations()
865 insn->retpoline_safe = true; in add_jump_destinations()
867 } else if (insn->func) { in add_jump_destinations()
869 insn->call_dest = reloc->sym; in add_jump_destinations()
870 if (insn->call_dest->static_call_tramp) { in add_jump_destinations()
871 list_add_tail(&insn->call_node, in add_jump_destinations()
884 insn->jump_dest = find_insn(file, dest_sec, dest_off); in add_jump_destinations()
885 if (!insn->jump_dest) { in add_jump_destinations()
892 if (!strcmp(insn->sec->name, ".altinstr_replacement")) in add_jump_destinations()
896 insn->sec, insn->offset, dest_sec->name, in add_jump_destinations()
904 if (insn->func && insn->jump_dest->func && in add_jump_destinations()
905 insn->func != insn->jump_dest->func) { in add_jump_destinations()
922 if (!strstr(insn->func->name, ".cold") && in add_jump_destinations()
923 strstr(insn->jump_dest->func->name, ".cold")) { in add_jump_destinations()
924 insn->func->cfunc = insn->jump_dest->func; in add_jump_destinations()
925 insn->jump_dest->func->pfunc = insn->func; in add_jump_destinations()
927 } else if (insn->jump_dest->func->pfunc != insn->func->pfunc && in add_jump_destinations()
928 insn->jump_dest->offset == insn->jump_dest->func->offset) { in add_jump_destinations()
931 insn->call_dest = insn->jump_dest->func; in add_jump_destinations()
932 if (insn->call_dest->static_call_tramp) { in add_jump_destinations()
933 list_add_tail(&insn->call_node, in add_jump_destinations()
943 static void remove_insn_ops(struct instruction *insn) in remove_insn_ops() argument
947 list_for_each_entry_safe(op, tmp, &insn->stack_ops, list) { in remove_insn_ops()
969 struct instruction *insn; in add_call_destinations() local
973 for_each_insn(file, insn) { in add_call_destinations()
974 if (insn->type != INSN_CALL) in add_call_destinations()
977 reloc = insn_reloc(file, insn); in add_call_destinations()
979 dest_off = arch_jump_destination(insn); in add_call_destinations()
980 insn->call_dest = find_call_destination(insn->sec, dest_off); in add_call_destinations()
982 if (insn->ignore) in add_call_destinations()
985 if (!insn->call_dest) { in add_call_destinations()
986 WARN_FUNC("unannotated intra-function call", insn->sec, insn->offset); in add_call_destinations()
990 if (insn->func && insn->call_dest->type != STT_FUNC) { in add_call_destinations()
992 insn->sec, insn->offset); in add_call_destinations()
998 insn->call_dest = find_call_destination(reloc->sym->sec, in add_call_destinations()
1000 if (!insn->call_dest) { in add_call_destinations()
1002 insn->sec, insn->offset, in add_call_destinations()
1013 insn->type = INSN_CALL_DYNAMIC; in add_call_destinations()
1014 insn->retpoline_safe = true; in add_call_destinations()
1016 list_add_tail(&insn->call_node, in add_call_destinations()
1019 remove_insn_ops(insn); in add_call_destinations()
1023 insn->call_dest = reloc->sym; in add_call_destinations()
1025 if (insn->call_dest && insn->call_dest->static_call_tramp) { in add_call_destinations()
1026 list_add_tail(&insn->call_node, in add_call_destinations()
1035 if (insn->sec->noinstr && in add_call_destinations()
1036 !strncmp(insn->call_dest->name, "__sanitizer_cov_", 16)) { in add_call_destinations()
1042 elf_write_insn(file->elf, insn->sec, in add_call_destinations()
1043 insn->offset, insn->len, in add_call_destinations()
1044 arch_nop_insn(insn->len)); in add_call_destinations()
1045 insn->type = INSN_NOP; in add_call_destinations()
1048 if (mcount && !strcmp(insn->call_dest->name, "__fentry__")) { in add_call_destinations()
1054 elf_write_insn(file->elf, insn->sec, in add_call_destinations()
1055 insn->offset, insn->len, in add_call_destinations()
1056 arch_nop_insn(insn->len)); in add_call_destinations()
1058 insn->type = INSN_NOP; in add_call_destinations()
1060 list_add_tail(&insn->mcount_loc_node, in add_call_destinations()
1071 remove_insn_ops(insn); in add_call_destinations()
1086 struct instruction *last_orig_insn, *last_new_insn = NULL, *insn, *nop = NULL; in handle_group_alt() local
1104 insn = orig_insn; in handle_group_alt()
1105 sec_for_each_insn_from(file, insn) { in handle_group_alt()
1106 if (insn->offset >= special_alt->orig_off + special_alt->orig_len) in handle_group_alt()
1109 insn->alt_group = orig_alt_group; in handle_group_alt()
1110 last_orig_insn = insn; in handle_group_alt()
1155 insn = *new_insn; in handle_group_alt()
1156 sec_for_each_insn_from(file, insn) { in handle_group_alt()
1159 if (insn->offset >= special_alt->new_off + special_alt->new_len) in handle_group_alt()
1162 last_new_insn = insn; in handle_group_alt()
1164 insn->ignore = orig_insn->ignore_alts; in handle_group_alt()
1165 insn->func = orig_insn->func; in handle_group_alt()
1166 insn->alt_group = new_alt_group; in handle_group_alt()
1176 alt_reloc = insn_reloc(file, insn); in handle_group_alt()
1178 !arch_support_alt_relocation(special_alt, insn, alt_reloc)) { in handle_group_alt()
1181 insn->sec, insn->offset); in handle_group_alt()
1185 if (!is_static_jump(insn)) in handle_group_alt()
1188 if (!insn->immediate) in handle_group_alt()
1191 dest_off = arch_jump_destination(insn); in handle_group_alt()
1193 insn->jump_dest = next_insn_same_sec(file, last_orig_insn); in handle_group_alt()
1195 if (!insn->jump_dest) { in handle_group_alt()
1197 insn->sec, insn->offset); in handle_group_alt()
1334 alt->insn = new_insn; in add_special_section_alts()
1353 static int add_jump_table(struct objtool_file *file, struct instruction *insn, in add_jump_table() argument
1359 struct symbol *pfunc = insn->func->pfunc; in add_jump_table()
1395 alt->insn = dest_insn; in add_jump_table()
1396 list_add_tail(&alt->list, &insn->alts); in add_jump_table()
1402 insn->sec, insn->offset); in add_jump_table()
1415 struct instruction *insn) in find_jump_table() argument
1418 struct instruction *dest_insn, *orig_insn = insn; in find_jump_table()
1426 insn && insn->func && insn->func->pfunc == func; in find_jump_table()
1427 insn = insn->first_jump_src ?: prev_insn_same_sym(file, insn)) { in find_jump_table()
1429 if (insn != orig_insn && insn->type == INSN_JUMP_DYNAMIC) in find_jump_table()
1433 if (insn->type == INSN_JUMP_UNCONDITIONAL && in find_jump_table()
1434 insn->jump_dest && in find_jump_table()
1435 (insn->jump_dest->offset <= insn->offset || in find_jump_table()
1436 insn->jump_dest->offset > orig_insn->offset)) in find_jump_table()
1439 table_reloc = arch_find_switch_table(file, insn); in find_jump_table()
1459 struct instruction *insn, *last = NULL; in mark_func_jump_tables() local
1462 func_for_each_insn(file, func, insn) { in mark_func_jump_tables()
1464 last = insn; in mark_func_jump_tables()
1471 if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest && in mark_func_jump_tables()
1472 insn->offset > last->offset && in mark_func_jump_tables()
1473 insn->jump_dest->offset > insn->offset && in mark_func_jump_tables()
1474 !insn->jump_dest->first_jump_src) { in mark_func_jump_tables()
1476 insn->jump_dest->first_jump_src = insn; in mark_func_jump_tables()
1477 last = insn->jump_dest; in mark_func_jump_tables()
1480 if (insn->type != INSN_JUMP_DYNAMIC) in mark_func_jump_tables()
1483 reloc = find_jump_table(file, func, insn); in mark_func_jump_tables()
1486 insn->jump_table = reloc; in mark_func_jump_tables()
1494 struct instruction *insn; in add_func_jump_tables() local
1497 func_for_each_insn(file, func, insn) { in add_func_jump_tables()
1498 if (!insn->jump_table) in add_func_jump_tables()
1501 ret = add_jump_table(file, insn, insn->jump_table); in add_func_jump_tables()
1551 struct instruction *insn; in read_unwind_hints() local
1580 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_unwind_hints()
1581 if (!insn) { in read_unwind_hints()
1586 insn->hint = true; in read_unwind_hints()
1589 set_func_state(&insn->cfi); in read_unwind_hints()
1593 if (arch_decode_hint_reg(insn, hint->sp_reg)) { in read_unwind_hints()
1595 insn->sec, insn->offset, hint->sp_reg); in read_unwind_hints()
1599 insn->cfi.cfa.offset = bswap_if_needed(hint->sp_offset); in read_unwind_hints()
1600 insn->cfi.type = hint->type; in read_unwind_hints()
1601 insn->cfi.end = hint->end; in read_unwind_hints()
1610 struct instruction *insn; in read_retpoline_hints() local
1623 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_retpoline_hints()
1624 if (!insn) { in read_retpoline_hints()
1629 if (insn->type != INSN_JUMP_DYNAMIC && in read_retpoline_hints()
1630 insn->type != INSN_CALL_DYNAMIC) { in read_retpoline_hints()
1632 insn->sec, insn->offset); in read_retpoline_hints()
1636 insn->retpoline_safe = true; in read_retpoline_hints()
1645 struct instruction *insn; in read_instr_hints() local
1658 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_instr_hints()
1659 if (!insn) { in read_instr_hints()
1664 insn->instr--; in read_instr_hints()
1677 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_instr_hints()
1678 if (!insn) { in read_instr_hints()
1683 insn->instr++; in read_instr_hints()
1691 struct instruction *insn; in read_intra_function_calls() local
1708 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_intra_function_calls()
1709 if (!insn) { in read_intra_function_calls()
1714 if (insn->type != INSN_CALL) { in read_intra_function_calls()
1716 insn->sec, insn->offset); in read_intra_function_calls()
1725 insn->type = INSN_JUMP_UNCONDITIONAL; in read_intra_function_calls()
1727 dest_off = insn->offset + insn->len + insn->immediate; in read_intra_function_calls()
1728 insn->jump_dest = find_insn(file, insn->sec, dest_off); in read_intra_function_calls()
1729 if (!insn->jump_dest) { in read_intra_function_calls()
1731 insn->sec, insn->offset, in read_intra_function_calls()
1732 insn->sec->name, dest_off); in read_intra_function_calls()
1868 static bool is_fentry_call(struct instruction *insn) in is_fentry_call() argument
1870 if (insn->type == INSN_CALL && insn->call_dest && in is_fentry_call()
1871 insn->call_dest->type == STT_NOTYPE && in is_fentry_call()
1872 !strcmp(insn->call_dest->name, "__fentry__")) in is_fentry_call()
1878 static bool has_modified_stack_frame(struct instruction *insn, struct insn_state *state) in has_modified_stack_frame() argument
1923 static int update_cfi_state_regs(struct instruction *insn, in update_cfi_state_regs() argument
2016 static int update_cfi_state(struct instruction *insn, in update_cfi_state() argument
2025 if (insn->func) { in update_cfi_state()
2026 WARN_FUNC("undefined stack state", insn->sec, insn->offset); in update_cfi_state()
2034 return update_cfi_state_regs(insn, cfi, op); in update_cfi_state()
2221 insn->sec, insn->offset); in update_cfi_state()
2232 insn->sec, insn->offset); in update_cfi_state()
2328 insn->sec, insn->offset); in update_cfi_state()
2371 if (!no_fp && insn->func && op->src.reg == CFI_BP && in update_cfi_state()
2418 insn->sec, insn->offset); in update_cfi_state()
2431 insn->sec, insn->offset); in update_cfi_state()
2447 static int propagate_alt_cfi(struct objtool_file *file, struct instruction *insn) in propagate_alt_cfi() argument
2452 if (!insn->alt_group) in propagate_alt_cfi()
2455 alt_cfi = insn->alt_group->cfi; in propagate_alt_cfi()
2456 group_off = insn->offset - insn->alt_group->first_insn->offset; in propagate_alt_cfi()
2459 alt_cfi[group_off] = &insn->cfi; in propagate_alt_cfi()
2461 if (memcmp(alt_cfi[group_off], &insn->cfi, sizeof(struct cfi_state))) { in propagate_alt_cfi()
2463 insn->sec, insn->offset); in propagate_alt_cfi()
2471 static int handle_insn_ops(struct instruction *insn, in handle_insn_ops() argument
2477 list_for_each_entry(op, &insn->stack_ops, list) { in handle_insn_ops()
2479 if (update_cfi_state(insn, next_insn, &state->cfi, op)) in handle_insn_ops()
2482 if (!insn->alt_group) in handle_insn_ops()
2490 insn->sec, insn->offset); in handle_insn_ops()
2510 static bool insn_cfi_match(struct instruction *insn, struct cfi_state *cfi2) in insn_cfi_match() argument
2512 struct cfi_state *cfi1 = &insn->cfi; in insn_cfi_match()
2518 insn->sec, insn->offset, in insn_cfi_match()
2529 insn->sec, insn->offset, in insn_cfi_match()
2538 insn->sec, insn->offset, cfi1->type, cfi2->type); in insn_cfi_match()
2545 insn->sec, insn->offset, in insn_cfi_match()
2563 static inline const char *call_dest_name(struct instruction *insn) in call_dest_name() argument
2565 if (insn->call_dest) in call_dest_name()
2566 return insn->call_dest->name; in call_dest_name()
2597 static int validate_call(struct instruction *insn, struct insn_state *state) in validate_call() argument
2600 !noinstr_call_dest(insn->call_dest)) { in validate_call()
2602 insn->sec, insn->offset, call_dest_name(insn)); in validate_call()
2606 if (state->uaccess && !func_uaccess_safe(insn->call_dest)) { in validate_call()
2608 insn->sec, insn->offset, call_dest_name(insn)); in validate_call()
2614 insn->sec, insn->offset, call_dest_name(insn)); in validate_call()
2621 static int validate_sibling_call(struct instruction *insn, struct insn_state *state) in validate_sibling_call() argument
2623 if (has_modified_stack_frame(insn, state)) { in validate_sibling_call()
2625 insn->sec, insn->offset); in validate_sibling_call()
2629 return validate_call(insn, state); in validate_sibling_call()
2632 static int validate_return(struct symbol *func, struct instruction *insn, struct insn_state *state) in validate_return() argument
2636 insn->sec, insn->offset); in validate_return()
2642 insn->sec, insn->offset); in validate_return()
2648 insn->sec, insn->offset); in validate_return()
2654 insn->sec, insn->offset); in validate_return()
2658 if (func && has_modified_stack_frame(insn, state)) { in validate_return()
2660 insn->sec, insn->offset); in validate_return()
2666 insn->sec, insn->offset); in validate_return()
2674 struct instruction *insn) in next_insn_to_validate() argument
2676 struct alt_group *alt_group = insn->alt_group; in next_insn_to_validate()
2683 if (alt_group && insn == alt_group->last_insn && alt_group->orig_group) in next_insn_to_validate()
2686 return next_insn_same_sec(file, insn); in next_insn_to_validate()
2696 struct instruction *insn, struct insn_state state) in validate_branch() argument
2704 sec = insn->sec; in validate_branch()
2707 next_insn = next_insn_to_validate(file, insn); in validate_branch()
2709 if (file->c_file && func && insn->func && func != insn->func->pfunc) { in validate_branch()
2711 func->name, insn->func->name); in validate_branch()
2715 if (func && insn->ignore) { in validate_branch()
2717 sec, insn->offset); in validate_branch()
2722 if (insn->visited) { in validate_branch()
2723 if (!insn->hint && !insn_cfi_match(insn, &state.cfi)) in validate_branch()
2726 if (insn->visited & visited) in validate_branch()
2731 state.instr += insn->instr; in validate_branch()
2733 if (insn->hint) in validate_branch()
2734 state.cfi = insn->cfi; in validate_branch()
2736 insn->cfi = state.cfi; in validate_branch()
2738 insn->visited |= visited; in validate_branch()
2740 if (propagate_alt_cfi(file, insn)) in validate_branch()
2743 if (!insn->ignore_alts && !list_empty(&insn->alts)) { in validate_branch()
2746 list_for_each_entry(alt, &insn->alts, list) { in validate_branch()
2750 ret = validate_branch(file, func, alt->insn, state); in validate_branch()
2753 BT_FUNC("(alt)", insn); in validate_branch()
2762 if (handle_insn_ops(insn, next_insn, &state)) in validate_branch()
2765 switch (insn->type) { in validate_branch()
2768 return validate_return(func, insn, &state); in validate_branch()
2772 ret = validate_call(insn, &state); in validate_branch()
2776 if (!no_fp && func && !is_fentry_call(insn) && in validate_branch()
2779 sec, insn->offset); in validate_branch()
2783 if (dead_end_function(file, insn->call_dest)) in validate_branch()
2790 if (is_sibling_call(insn)) { in validate_branch()
2791 ret = validate_sibling_call(insn, &state); in validate_branch()
2795 } else if (insn->jump_dest) { in validate_branch()
2797 insn->jump_dest, state); in validate_branch()
2800 BT_FUNC("(branch)", insn); in validate_branch()
2805 if (insn->type == INSN_JUMP_UNCONDITIONAL) in validate_branch()
2812 if (is_sibling_call(insn)) { in validate_branch()
2813 ret = validate_sibling_call(insn, &state); in validate_branch()
2818 if (insn->type == INSN_JUMP_DYNAMIC) in validate_branch()
2826 sec, insn->offset); in validate_branch()
2833 WARN_FUNC("recursive UACCESS enable", sec, insn->offset); in validate_branch()
2842 WARN_FUNC("redundant UACCESS disable", sec, insn->offset); in validate_branch()
2847 WARN_FUNC("UACCESS-safe disables UACCESS", sec, insn->offset); in validate_branch()
2856 WARN_FUNC("recursive STD", sec, insn->offset); in validate_branch()
2865 WARN_FUNC("redundant CLD", sec, insn->offset); in validate_branch()
2876 if (insn->dead_end) in validate_branch()
2886 insn = next_insn; in validate_branch()
2894 struct instruction *insn; in validate_unwind_hints() local
2904 insn = find_insn(file, sec, 0); in validate_unwind_hints()
2905 if (!insn) in validate_unwind_hints()
2908 insn = list_first_entry(&file->insn_list, typeof(*insn), list); in validate_unwind_hints()
2911 while (&insn->list != &file->insn_list && (!sec || insn->sec == sec)) { in validate_unwind_hints()
2912 if (insn->hint && !insn->visited) { in validate_unwind_hints()
2913 ret = validate_branch(file, insn->func, insn, state); in validate_unwind_hints()
2915 BT_FUNC("<=== (hint)", insn); in validate_unwind_hints()
2919 insn = list_next_entry(insn, list); in validate_unwind_hints()
2927 struct instruction *insn; in validate_retpoline() local
2930 for_each_insn(file, insn) { in validate_retpoline()
2931 if (insn->type != INSN_JUMP_DYNAMIC && in validate_retpoline()
2932 insn->type != INSN_CALL_DYNAMIC) in validate_retpoline()
2935 if (insn->retpoline_safe) in validate_retpoline()
2944 if (!strcmp(insn->sec->name, ".init.text") && !module) in validate_retpoline()
2948 insn->sec, insn->offset, in validate_retpoline()
2949 insn->type == INSN_JUMP_DYNAMIC ? "jump" : "call"); in validate_retpoline()
2957 static bool is_kasan_insn(struct instruction *insn) in is_kasan_insn() argument
2959 return (insn->type == INSN_CALL && in is_kasan_insn()
2960 !strcmp(insn->call_dest->name, "__asan_handle_no_return")); in is_kasan_insn()
2963 static bool is_ubsan_insn(struct instruction *insn) in is_ubsan_insn() argument
2965 return (insn->type == INSN_CALL && in is_ubsan_insn()
2966 !strcmp(insn->call_dest->name, in is_ubsan_insn()
2970 static bool ignore_unreachable_insn(struct objtool_file *file, struct instruction *insn) in ignore_unreachable_insn() argument
2975 if (insn->ignore || insn->type == INSN_NOP) in ignore_unreachable_insn()
2985 if (!strcmp(insn->sec->name, ".fixup") || in ignore_unreachable_insn()
2986 !strcmp(insn->sec->name, ".altinstr_replacement") || in ignore_unreachable_insn()
2987 !strcmp(insn->sec->name, ".altinstr_aux")) in ignore_unreachable_insn()
2990 if (!insn->func) in ignore_unreachable_insn()
3001 prev_insn = list_prev_entry(insn, list); in ignore_unreachable_insn()
3003 (insn->type == INSN_BUG || in ignore_unreachable_insn()
3004 (insn->type == INSN_JUMP_UNCONDITIONAL && in ignore_unreachable_insn()
3005 insn->jump_dest && insn->jump_dest->type == INSN_BUG))) in ignore_unreachable_insn()
3016 if (is_kasan_insn(insn) || is_ubsan_insn(insn)) in ignore_unreachable_insn()
3019 if (insn->type == INSN_JUMP_UNCONDITIONAL) { in ignore_unreachable_insn()
3020 if (insn->jump_dest && in ignore_unreachable_insn()
3021 insn->jump_dest->func == insn->func) { in ignore_unreachable_insn()
3022 insn = insn->jump_dest; in ignore_unreachable_insn()
3029 if (insn->offset + insn->len >= insn->func->offset + insn->func->len) in ignore_unreachable_insn()
3032 insn = list_next_entry(insn, list); in ignore_unreachable_insn()
3041 struct instruction *insn; in validate_symbol() local
3052 insn = find_insn(file, sec, sym->offset); in validate_symbol()
3053 if (!insn || insn->ignore || insn->visited) in validate_symbol()
3058 ret = validate_branch(file, insn->func, insn, *state); in validate_symbol()
3060 BT_FUNC("<=== (sym)", insn); in validate_symbol()
3120 struct instruction *insn; in validate_reachable_instructions() local
3125 for_each_insn(file, insn) { in validate_reachable_instructions()
3126 if (insn->visited || ignore_unreachable_insn(file, insn)) in validate_reachable_instructions()
3129 WARN_FUNC("unreachable instruction", insn->sec, insn->offset); in validate_reachable_instructions()