Lines Matching refs:insn

26 	struct instruction *insn;  member
39 struct instruction *insn; in find_insn() local
41 hash_for_each_possible(file->insn_hash, insn, hash, sec_offset_hash(sec, offset)) { in find_insn()
42 if (insn->sec == sec && insn->offset == offset) in find_insn()
43 return insn; in find_insn()
50 struct instruction *insn) in next_insn_same_sec() argument
52 struct instruction *next = list_next_entry(insn, list); in next_insn_same_sec()
54 if (!next || &next->list == &file->insn_list || next->sec != insn->sec) in next_insn_same_sec()
61 struct instruction *insn) in next_insn_same_func() argument
63 struct instruction *next = list_next_entry(insn, list); in next_insn_same_func()
64 struct symbol *func = insn->func; in next_insn_same_func()
81 struct instruction *insn) in prev_insn_same_sym() argument
83 struct instruction *prev = list_prev_entry(insn, list); in prev_insn_same_sym()
85 if (&prev->list != &file->insn_list && prev->func == insn->func) in prev_insn_same_sym()
91 #define func_for_each_insn(file, func, insn) \ argument
92 for (insn = find_insn(file, func->sec, func->offset); \
93 insn; \
94 insn = next_insn_same_func(file, insn))
96 #define sym_for_each_insn(file, sym, insn) \ argument
97 for (insn = find_insn(file, sym->sec, sym->offset); \
98 insn && &insn->list != &file->insn_list && \
99 insn->sec == sym->sec && \
100 insn->offset < sym->offset + sym->len; \
101 insn = list_next_entry(insn, list))
103 #define sym_for_each_insn_continue_reverse(file, sym, insn) \ argument
104 for (insn = list_prev_entry(insn, list); \
105 &insn->list != &file->insn_list && \
106 insn->sec == sym->sec && insn->offset >= sym->offset; \
107 insn = list_prev_entry(insn, list))
109 #define sec_for_each_insn_from(file, insn) \ argument
110 for (; insn; insn = next_insn_same_sec(file, insn))
112 #define sec_for_each_insn_continue(file, insn) \ argument
113 for (insn = next_insn_same_sec(file, insn); insn; \
114 insn = next_insn_same_sec(file, insn))
116 static bool is_jump_table_jump(struct instruction *insn) in is_jump_table_jump() argument
118 struct alt_group *alt_group = insn->alt_group; in is_jump_table_jump()
120 if (insn->jump_table) in is_jump_table_jump()
128 static bool is_sibling_call(struct instruction *insn) in is_sibling_call() argument
135 if (!insn->func) in is_sibling_call()
139 if (insn->type == INSN_JUMP_DYNAMIC) in is_sibling_call()
140 return !is_jump_table_jump(insn); in is_sibling_call()
143 return (is_static_jump(insn) && insn->call_dest); in is_sibling_call()
159 struct instruction *insn; in __dead_end_function() local
198 insn = find_insn(file, func->sec, func->offset); in __dead_end_function()
199 if (!insn->func) in __dead_end_function()
202 func_for_each_insn(file, func, insn) { in __dead_end_function()
205 if (insn->type == INSN_RETURN) in __dead_end_function()
217 func_for_each_insn(file, func, insn) { in __dead_end_function()
218 if (is_sibling_call(insn)) { in __dead_end_function()
219 struct instruction *dest = insn->jump_dest; in __dead_end_function()
355 struct instruction *insn; in decode_instructions() local
373 for (offset = 0; offset < sec->len; offset += insn->len) { in decode_instructions()
374 insn = malloc(sizeof(*insn)); in decode_instructions()
375 if (!insn) { in decode_instructions()
379 memset(insn, 0, sizeof(*insn)); in decode_instructions()
380 INIT_LIST_HEAD(&insn->alts); in decode_instructions()
381 INIT_LIST_HEAD(&insn->stack_ops); in decode_instructions()
383 insn->sec = sec; in decode_instructions()
384 insn->offset = offset; in decode_instructions()
388 &insn->len, &insn->type, in decode_instructions()
389 &insn->immediate, in decode_instructions()
390 &insn->stack_ops); in decode_instructions()
394 hash_add(file->insn_hash, &insn->hash, sec_offset_hash(sec, insn->offset)); in decode_instructions()
395 list_add_tail(&insn->list, &file->insn_list); in decode_instructions()
409 sym_for_each_insn(file, func, insn) in decode_instructions()
410 insn->func = func; in decode_instructions()
420 free(insn); in decode_instructions()
427 struct instruction *insn = NULL; in find_last_insn() local
431 for (offset = sec->len - 1; offset >= end && !insn; offset--) in find_last_insn()
432 insn = find_insn(file, sec, offset); in find_last_insn()
434 return insn; in find_last_insn()
444 struct instruction *insn; in add_dead_ends() local
450 for_each_insn(file, insn) in add_dead_ends()
451 if (insn->type == INSN_BUG) in add_dead_ends()
452 insn->dead_end = true; in add_dead_ends()
466 insn = find_insn(file, reloc->sym->sec, reloc->addend); in add_dead_ends()
467 if (insn) in add_dead_ends()
468 insn = list_prev_entry(insn, list); in add_dead_ends()
470 insn = find_last_insn(file, reloc->sym->sec); in add_dead_ends()
471 if (!insn) { in add_dead_ends()
482 insn->dead_end = true; in add_dead_ends()
501 insn = find_insn(file, reloc->sym->sec, reloc->addend); in add_dead_ends()
502 if (insn) in add_dead_ends()
503 insn = list_prev_entry(insn, list); in add_dead_ends()
505 insn = find_last_insn(file, reloc->sym->sec); in add_dead_ends()
506 if (!insn) { in add_dead_ends()
517 insn->dead_end = false; in add_dead_ends()
527 struct instruction *insn; in create_static_call_sections() local
543 list_for_each_entry(insn, &file->static_call_list, call_node) in create_static_call_sections()
552 list_for_each_entry(insn, &file->static_call_list, call_node) { in create_static_call_sections()
561 insn->sec, insn->offset)) in create_static_call_sections()
565 key_name = strdup(insn->call_dest->name); in create_static_call_sections()
594 key_sym = insn->call_dest; in create_static_call_sections()
602 is_sibling_call(insn) * STATIC_CALL_SITE_TAIL)) in create_static_call_sections()
613 struct instruction *insn; in create_retpoline_sites_sections() local
624 list_for_each_entry(insn, &file->retpoline_call_list, call_node) in create_retpoline_sites_sections()
638 list_for_each_entry(insn, &file->retpoline_call_list, call_node) { in create_retpoline_sites_sections()
646 insn->sec, insn->offset)) { in create_retpoline_sites_sections()
659 struct instruction *insn; in create_return_sites_sections() local
670 list_for_each_entry(insn, &file->return_thunk_list, call_node) in create_return_sites_sections()
684 list_for_each_entry(insn, &file->return_thunk_list, call_node) { in create_return_sites_sections()
692 insn->sec, insn->offset)) { in create_return_sites_sections()
707 struct instruction *insn; in create_mcount_loc_sections() local
721 list_for_each_entry(insn, &file->mcount_loc_list, mcount_loc_node) in create_mcount_loc_sections()
729 list_for_each_entry(insn, &file->mcount_loc_list, mcount_loc_node) { in create_mcount_loc_sections()
737 insn->sec, insn->offset)) in create_mcount_loc_sections()
751 struct instruction *insn; in add_ignores() local
777 func_for_each_insn(file, func, insn) in add_ignores()
778 insn->ignore = true; in add_ignores()
952 struct instruction *insn; in add_ignore_alternatives() local
964 insn = find_insn(file, reloc->sym->sec, reloc->addend); in add_ignore_alternatives()
965 if (!insn) { in add_ignore_alternatives()
970 insn->ignore_alts = true; in add_ignore_alternatives()
988 static struct reloc *insn_reloc(struct objtool_file *file, struct instruction *insn) in insn_reloc() argument
990 if (insn->reloc == NEGATIVE_RELOC) in insn_reloc()
993 if (!insn->reloc) { in insn_reloc()
994 insn->reloc = find_reloc_by_dest_range(file->elf, insn->sec, in insn_reloc()
995 insn->offset, insn->len); in insn_reloc()
996 if (!insn->reloc) { in insn_reloc()
997 insn->reloc = NEGATIVE_RELOC; in insn_reloc()
1002 return insn->reloc; in insn_reloc()
1005 static void remove_insn_ops(struct instruction *insn) in remove_insn_ops() argument
1009 list_for_each_entry_safe(op, tmp, &insn->stack_ops, list) { in remove_insn_ops()
1016 struct instruction *insn, bool sibling) in annotate_call_site() argument
1018 struct reloc *reloc = insn_reloc(file, insn); in annotate_call_site()
1019 struct symbol *sym = insn->call_dest; in annotate_call_site()
1030 if (!strcmp(insn->sec->name, ".altinstr_replacement")) in annotate_call_site()
1034 list_add_tail(&insn->call_node, &file->static_call_list); in annotate_call_site()
1039 list_add_tail(&insn->call_node, &file->retpoline_call_list); in annotate_call_site()
1048 if (insn->sec->noinstr && sym->kcov) { in annotate_call_site()
1054 elf_write_insn(file->elf, insn->sec, in annotate_call_site()
1055 insn->offset, insn->len, in annotate_call_site()
1056 sibling ? arch_ret_insn(insn->len) in annotate_call_site()
1057 : arch_nop_insn(insn->len)); in annotate_call_site()
1059 insn->type = sibling ? INSN_RETURN : INSN_NOP; in annotate_call_site()
1068 insn->retpoline_safe = true; in annotate_call_site()
1075 static void add_call_dest(struct objtool_file *file, struct instruction *insn, in add_call_dest() argument
1078 insn->call_dest = dest; in add_call_dest()
1089 remove_insn_ops(insn); in add_call_dest()
1091 annotate_call_site(file, insn, sibling); in add_call_dest()
1094 static void add_retpoline_call(struct objtool_file *file, struct instruction *insn) in add_retpoline_call() argument
1100 switch (insn->type) { in add_retpoline_call()
1102 insn->type = INSN_CALL_DYNAMIC; in add_retpoline_call()
1105 insn->type = INSN_JUMP_DYNAMIC; in add_retpoline_call()
1108 insn->type = INSN_JUMP_DYNAMIC_CONDITIONAL; in add_retpoline_call()
1114 insn->retpoline_safe = true; in add_retpoline_call()
1123 remove_insn_ops(insn); in add_retpoline_call()
1125 annotate_call_site(file, insn, false); in add_retpoline_call()
1128 static void add_return_call(struct objtool_file *file, struct instruction *insn, bool add) in add_return_call() argument
1134 insn->type = INSN_RETURN; in add_return_call()
1135 insn->retpoline_safe = true; in add_return_call()
1138 if (add && insn->sec->text) in add_return_call()
1139 list_add_tail(&insn->call_node, &file->return_thunk_list); in add_return_call()
1160 struct instruction *insn; in add_cfi_jumptables() local
1167 sym_for_each_insn(file, func, insn) in add_cfi_jumptables()
1168 insn->ignore = true; in add_cfi_jumptables()
1178 struct instruction *insn; in add_jump_destinations() local
1183 for_each_insn(file, insn) { in add_jump_destinations()
1184 if (!is_static_jump(insn)) in add_jump_destinations()
1187 reloc = insn_reloc(file, insn); in add_jump_destinations()
1189 dest_sec = insn->sec; in add_jump_destinations()
1190 dest_off = arch_jump_destination(insn); in add_jump_destinations()
1195 add_retpoline_call(file, insn); in add_jump_destinations()
1198 add_return_call(file, insn, true); in add_jump_destinations()
1200 } else if (insn->func) { in add_jump_destinations()
1202 add_call_dest(file, insn, reloc->sym, true); in add_jump_destinations()
1213 insn->jump_dest = find_insn(file, dest_sec, dest_off); in add_jump_destinations()
1215 if (!insn->jump_dest && dest_sec->len == dest_off) in add_jump_destinations()
1216 insn->jump_dest = find_last_insn(file, dest_sec); in add_jump_destinations()
1218 if (!insn->jump_dest) { in add_jump_destinations()
1226 if (!strcmp(insn->sec->name, ".altinstr_replacement")) in add_jump_destinations()
1229 if (is_cfi_section(insn->sec)) in add_jump_destinations()
1241 add_return_call(file, insn, false); in add_jump_destinations()
1246 insn->sec, insn->offset, dest_sec->name, in add_jump_destinations()
1254 if (insn->func && insn->jump_dest->func && in add_jump_destinations()
1255 insn->func != insn->jump_dest->func) { in add_jump_destinations()
1272 if (!strstr(insn->func->name, ".cold") && in add_jump_destinations()
1273 strstr(insn->jump_dest->func->name, ".cold")) { in add_jump_destinations()
1274 insn->func->cfunc = insn->jump_dest->func; in add_jump_destinations()
1275 insn->jump_dest->func->pfunc = insn->func; in add_jump_destinations()
1277 } else if (insn->jump_dest->func->pfunc != insn->func->pfunc && in add_jump_destinations()
1278 insn->jump_dest->offset == insn->jump_dest->func->offset) { in add_jump_destinations()
1280 add_call_dest(file, insn, insn->jump_dest->func, true); in add_jump_destinations()
1304 struct instruction *insn; in add_call_destinations() local
1309 for_each_insn(file, insn) { in add_call_destinations()
1310 if (insn->type != INSN_CALL) in add_call_destinations()
1313 reloc = insn_reloc(file, insn); in add_call_destinations()
1315 dest_off = arch_jump_destination(insn); in add_call_destinations()
1316 dest = find_call_destination(insn->sec, dest_off); in add_call_destinations()
1318 add_call_dest(file, insn, dest, false); in add_call_destinations()
1320 if (insn->ignore) in add_call_destinations()
1323 if (!insn->call_dest) { in add_call_destinations()
1324 WARN_FUNC("unannotated intra-function call", insn->sec, insn->offset); in add_call_destinations()
1328 if (insn->func && insn->call_dest->type != STT_FUNC) { in add_call_destinations()
1330 insn->sec, insn->offset); in add_call_destinations()
1342 insn->sec, insn->offset, in add_call_destinations()
1348 add_call_dest(file, insn, dest, false); in add_call_destinations()
1351 add_retpoline_call(file, insn); in add_call_destinations()
1354 add_call_dest(file, insn, reloc->sym, false); in add_call_destinations()
1369 struct instruction *last_orig_insn, *last_new_insn = NULL, *insn, *nop = NULL; in handle_group_alt() local
1387 insn = orig_insn; in handle_group_alt()
1388 sec_for_each_insn_from(file, insn) { in handle_group_alt()
1389 if (insn->offset >= special_alt->orig_off + special_alt->orig_len) in handle_group_alt()
1392 insn->alt_group = orig_alt_group; in handle_group_alt()
1393 last_orig_insn = insn; in handle_group_alt()
1437 insn = *new_insn; in handle_group_alt()
1438 sec_for_each_insn_from(file, insn) { in handle_group_alt()
1441 if (insn->offset >= special_alt->new_off + special_alt->new_len) in handle_group_alt()
1444 last_new_insn = insn; in handle_group_alt()
1446 insn->ignore = orig_insn->ignore_alts; in handle_group_alt()
1447 insn->func = orig_insn->func; in handle_group_alt()
1448 insn->alt_group = new_alt_group; in handle_group_alt()
1458 alt_reloc = insn_reloc(file, insn); in handle_group_alt()
1460 !arch_support_alt_relocation(special_alt, insn, alt_reloc)) { in handle_group_alt()
1463 insn->sec, insn->offset); in handle_group_alt()
1467 if (!is_static_jump(insn)) in handle_group_alt()
1470 if (!insn->immediate) in handle_group_alt()
1473 dest_off = arch_jump_destination(insn); in handle_group_alt()
1475 insn->jump_dest = next_insn_same_sec(file, last_orig_insn); in handle_group_alt()
1477 if (!insn->jump_dest) { in handle_group_alt()
1479 insn->sec, insn->offset); in handle_group_alt()
1590 alt->insn = new_insn; in add_special_section_alts()
1603 static int add_jump_table(struct objtool_file *file, struct instruction *insn, in add_jump_table() argument
1609 struct symbol *pfunc = insn->func->pfunc; in add_jump_table()
1645 alt->insn = dest_insn; in add_jump_table()
1646 list_add_tail(&alt->list, &insn->alts); in add_jump_table()
1652 insn->sec, insn->offset); in add_jump_table()
1665 struct instruction *insn) in find_jump_table() argument
1668 struct instruction *dest_insn, *orig_insn = insn; in find_jump_table()
1676 insn && insn->func && insn->func->pfunc == func; in find_jump_table()
1677 insn = insn->first_jump_src ?: prev_insn_same_sym(file, insn)) { in find_jump_table()
1679 if (insn != orig_insn && insn->type == INSN_JUMP_DYNAMIC) in find_jump_table()
1683 if (insn->type == INSN_JUMP_UNCONDITIONAL && in find_jump_table()
1684 insn->jump_dest && in find_jump_table()
1685 (insn->jump_dest->offset <= insn->offset || in find_jump_table()
1686 insn->jump_dest->offset > orig_insn->offset)) in find_jump_table()
1689 table_reloc = arch_find_switch_table(file, insn); in find_jump_table()
1709 struct instruction *insn, *last = NULL; in mark_func_jump_tables() local
1712 func_for_each_insn(file, func, insn) { in mark_func_jump_tables()
1714 last = insn; in mark_func_jump_tables()
1721 if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest && in mark_func_jump_tables()
1722 insn->offset > last->offset && in mark_func_jump_tables()
1723 insn->jump_dest->offset > insn->offset && in mark_func_jump_tables()
1724 !insn->jump_dest->first_jump_src) { in mark_func_jump_tables()
1726 insn->jump_dest->first_jump_src = insn; in mark_func_jump_tables()
1727 last = insn->jump_dest; in mark_func_jump_tables()
1730 if (insn->type != INSN_JUMP_DYNAMIC) in mark_func_jump_tables()
1733 reloc = find_jump_table(file, func, insn); in mark_func_jump_tables()
1736 insn->jump_table = reloc; in mark_func_jump_tables()
1744 struct instruction *insn; in add_func_jump_tables() local
1747 func_for_each_insn(file, func, insn) { in add_func_jump_tables()
1748 if (!insn->jump_table) in add_func_jump_tables()
1751 ret = add_jump_table(file, insn, insn->jump_table); in add_func_jump_tables()
1801 struct instruction *insn; in read_unwind_hints() local
1831 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_unwind_hints()
1832 if (!insn) { in read_unwind_hints()
1837 insn->hint = true; in read_unwind_hints()
1840 insn->hint = false; in read_unwind_hints()
1841 insn->save = true; in read_unwind_hints()
1846 insn->restore = true; in read_unwind_hints()
1851 struct symbol *sym = find_symbol_by_offset(insn->sec, insn->offset); in read_unwind_hints()
1854 insn->entry = 1; in read_unwind_hints()
1860 insn->entry = 1; in read_unwind_hints()
1864 insn->cfi = &func_cfi; in read_unwind_hints()
1868 if (insn->cfi) in read_unwind_hints()
1869 cfi = *(insn->cfi); in read_unwind_hints()
1873 insn->sec, insn->offset, hint->sp_reg); in read_unwind_hints()
1881 insn->cfi = cfi_hash_find_or_add(&cfi); in read_unwind_hints()
1890 struct instruction *insn; in read_retpoline_hints() local
1903 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_retpoline_hints()
1904 if (!insn) { in read_retpoline_hints()
1909 if (insn->type != INSN_JUMP_DYNAMIC && in read_retpoline_hints()
1910 insn->type != INSN_CALL_DYNAMIC && in read_retpoline_hints()
1911 insn->type != INSN_RETURN && in read_retpoline_hints()
1912 insn->type != INSN_NOP) { in read_retpoline_hints()
1914 insn->sec, insn->offset); in read_retpoline_hints()
1918 insn->retpoline_safe = true; in read_retpoline_hints()
1927 struct instruction *insn; in read_instr_hints() local
1940 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_instr_hints()
1941 if (!insn) { in read_instr_hints()
1946 insn->instr--; in read_instr_hints()
1959 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_instr_hints()
1960 if (!insn) { in read_instr_hints()
1965 insn->instr++; in read_instr_hints()
1973 struct instruction *insn; in read_intra_function_calls() local
1990 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_intra_function_calls()
1991 if (!insn) { in read_intra_function_calls()
1996 if (insn->type != INSN_CALL) { in read_intra_function_calls()
1998 insn->sec, insn->offset); in read_intra_function_calls()
2007 insn->type = INSN_JUMP_UNCONDITIONAL; in read_intra_function_calls()
2009 dest_off = insn->offset + insn->len + insn->immediate; in read_intra_function_calls()
2010 insn->jump_dest = find_insn(file, insn->sec, dest_off); in read_intra_function_calls()
2011 if (!insn->jump_dest) { in read_intra_function_calls()
2013 insn->sec, insn->offset, in read_intra_function_calls()
2014 insn->sec->name, dest_off); in read_intra_function_calls()
2151 static bool is_fentry_call(struct instruction *insn) in is_fentry_call() argument
2153 if (insn->type == INSN_CALL && in is_fentry_call()
2154 insn->call_dest && in is_fentry_call()
2155 insn->call_dest->fentry) in is_fentry_call()
2161 static bool has_modified_stack_frame(struct instruction *insn, struct insn_state *state) in has_modified_stack_frame() argument
2198 static int update_cfi_state_regs(struct instruction *insn, in update_cfi_state_regs() argument
2291 static int update_cfi_state(struct instruction *insn, struct cfi_state *cfi, in update_cfi_state() argument
2299 if (insn->func) { in update_cfi_state()
2300 WARN_FUNC("undefined stack state", insn->sec, insn->offset); in update_cfi_state()
2308 return update_cfi_state_regs(insn, cfi, op); in update_cfi_state()
2439 insn->sec, insn->offset); in update_cfi_state()
2450 insn->sec, insn->offset); in update_cfi_state()
2525 insn->sec, insn->offset); in update_cfi_state()
2568 if (!no_fp && insn->func && op->src.reg == CFI_BP && in update_cfi_state()
2604 insn->sec, insn->offset); in update_cfi_state()
2623 insn->sec, insn->offset); in update_cfi_state()
2636 insn->sec, insn->offset); in update_cfi_state()
2652 static int propagate_alt_cfi(struct objtool_file *file, struct instruction *insn) in propagate_alt_cfi() argument
2657 if (!insn->alt_group) in propagate_alt_cfi()
2660 if (!insn->cfi) { in propagate_alt_cfi()
2665 alt_cfi = insn->alt_group->cfi; in propagate_alt_cfi()
2666 group_off = insn->offset - insn->alt_group->first_insn->offset; in propagate_alt_cfi()
2669 alt_cfi[group_off] = insn->cfi; in propagate_alt_cfi()
2671 if (cficmp(alt_cfi[group_off], insn->cfi)) { in propagate_alt_cfi()
2673 insn->sec, insn->offset); in propagate_alt_cfi()
2681 static int handle_insn_ops(struct instruction *insn, struct insn_state *state) in handle_insn_ops() argument
2685 list_for_each_entry(op, &insn->stack_ops, list) { in handle_insn_ops()
2687 if (update_cfi_state(insn, &state->cfi, op)) in handle_insn_ops()
2695 insn->sec, insn->offset); in handle_insn_ops()
2715 static bool insn_cfi_match(struct instruction *insn, struct cfi_state *cfi2) in insn_cfi_match() argument
2717 struct cfi_state *cfi1 = insn->cfi; in insn_cfi_match()
2728 insn->sec, insn->offset, in insn_cfi_match()
2739 insn->sec, insn->offset, in insn_cfi_match()
2748 insn->sec, insn->offset, cfi1->type, cfi2->type); in insn_cfi_match()
2755 insn->sec, insn->offset, in insn_cfi_match()
2773 static inline const char *call_dest_name(struct instruction *insn) in call_dest_name() argument
2775 if (insn->call_dest) in call_dest_name()
2776 return insn->call_dest->name; in call_dest_name()
2807 static int validate_call(struct instruction *insn, struct insn_state *state) in validate_call() argument
2810 !noinstr_call_dest(insn->call_dest)) { in validate_call()
2812 insn->sec, insn->offset, call_dest_name(insn)); in validate_call()
2816 if (state->uaccess && !func_uaccess_safe(insn->call_dest)) { in validate_call()
2818 insn->sec, insn->offset, call_dest_name(insn)); in validate_call()
2824 insn->sec, insn->offset, call_dest_name(insn)); in validate_call()
2831 static int validate_sibling_call(struct instruction *insn, struct insn_state *state) in validate_sibling_call() argument
2833 if (has_modified_stack_frame(insn, state)) { in validate_sibling_call()
2835 insn->sec, insn->offset); in validate_sibling_call()
2839 return validate_call(insn, state); in validate_sibling_call()
2842 static int validate_return(struct symbol *func, struct instruction *insn, struct insn_state *state) in validate_return() argument
2846 insn->sec, insn->offset); in validate_return()
2852 insn->sec, insn->offset); in validate_return()
2858 insn->sec, insn->offset); in validate_return()
2864 insn->sec, insn->offset); in validate_return()
2868 if (func && has_modified_stack_frame(insn, state)) { in validate_return()
2870 insn->sec, insn->offset); in validate_return()
2876 insn->sec, insn->offset); in validate_return()
2884 struct instruction *insn) in next_insn_to_validate() argument
2886 struct alt_group *alt_group = insn->alt_group; in next_insn_to_validate()
2893 if (alt_group && insn == alt_group->last_insn && alt_group->orig_group) in next_insn_to_validate()
2896 return next_insn_same_sec(file, insn); in next_insn_to_validate()
2906 struct instruction *insn, struct insn_state state) in validate_branch() argument
2914 sec = insn->sec; in validate_branch()
2917 next_insn = next_insn_to_validate(file, insn); in validate_branch()
2919 if (file->c_file && func && insn->func && func != insn->func->pfunc) { in validate_branch()
2921 func->name, insn->func->name); in validate_branch()
2925 if (func && insn->ignore) { in validate_branch()
2927 sec, insn->offset); in validate_branch()
2932 if (insn->visited & VISITED_BRANCH_MASK) { in validate_branch()
2933 if (!insn->hint && !insn_cfi_match(insn, &state.cfi)) in validate_branch()
2936 if (insn->visited & visited) in validate_branch()
2943 state.instr += insn->instr; in validate_branch()
2945 if (insn->hint) { in validate_branch()
2946 if (insn->restore) { in validate_branch()
2949 i = insn; in validate_branch()
2961 sec, insn->offset); in validate_branch()
2967 sec, insn->offset); in validate_branch()
2971 insn->cfi = save_insn->cfi; in validate_branch()
2975 state.cfi = *insn->cfi; in validate_branch()
2980 insn->cfi = prev_insn->cfi; in validate_branch()
2983 insn->cfi = cfi_hash_find_or_add(&state.cfi); in validate_branch()
2987 insn->visited |= visited; in validate_branch()
2989 if (propagate_alt_cfi(file, insn)) in validate_branch()
2992 if (!insn->ignore_alts && !list_empty(&insn->alts)) { in validate_branch()
2995 list_for_each_entry(alt, &insn->alts, list) { in validate_branch()
2999 ret = validate_branch(file, func, alt->insn, state); in validate_branch()
3002 BT_FUNC("(alt)", insn); in validate_branch()
3011 if (handle_insn_ops(insn, &state)) in validate_branch()
3014 switch (insn->type) { in validate_branch()
3017 if (sls && !insn->retpoline_safe && in validate_branch()
3020 insn->sec, insn->offset); in validate_branch()
3022 return validate_return(func, insn, &state); in validate_branch()
3026 ret = validate_call(insn, &state); in validate_branch()
3030 if (!no_fp && func && !is_fentry_call(insn) && in validate_branch()
3033 sec, insn->offset); in validate_branch()
3037 if (dead_end_function(file, insn->call_dest)) in validate_branch()
3044 if (is_sibling_call(insn)) { in validate_branch()
3045 ret = validate_sibling_call(insn, &state); in validate_branch()
3049 } else if (insn->jump_dest) { in validate_branch()
3051 insn->jump_dest, state); in validate_branch()
3054 BT_FUNC("(branch)", insn); in validate_branch()
3059 if (insn->type == INSN_JUMP_UNCONDITIONAL) in validate_branch()
3065 if (sls && !insn->retpoline_safe && in validate_branch()
3068 insn->sec, insn->offset); in validate_branch()
3073 if (is_sibling_call(insn)) { in validate_branch()
3074 ret = validate_sibling_call(insn, &state); in validate_branch()
3079 if (insn->type == INSN_JUMP_DYNAMIC) in validate_branch()
3087 sec, insn->offset); in validate_branch()
3094 WARN_FUNC("recursive UACCESS enable", sec, insn->offset); in validate_branch()
3103 WARN_FUNC("redundant UACCESS disable", sec, insn->offset); in validate_branch()
3108 WARN_FUNC("UACCESS-safe disables UACCESS", sec, insn->offset); in validate_branch()
3117 WARN_FUNC("recursive STD", sec, insn->offset); in validate_branch()
3126 WARN_FUNC("redundant CLD", sec, insn->offset); in validate_branch()
3137 if (insn->dead_end) in validate_branch()
3147 prev_insn = insn; in validate_branch()
3148 insn = next_insn; in validate_branch()
3156 struct instruction *insn; in validate_unwind_hints() local
3166 insn = find_insn(file, sec, 0); in validate_unwind_hints()
3167 if (!insn) in validate_unwind_hints()
3170 insn = list_first_entry(&file->insn_list, typeof(*insn), list); in validate_unwind_hints()
3173 while (&insn->list != &file->insn_list && (!sec || insn->sec == sec)) { in validate_unwind_hints()
3174 if (insn->hint && !insn->visited) { in validate_unwind_hints()
3175 ret = validate_branch(file, insn->func, insn, state); in validate_unwind_hints()
3177 BT_FUNC("<=== (hint)", insn); in validate_unwind_hints()
3181 insn = list_next_entry(insn, list); in validate_unwind_hints()
3193 static int validate_entry(struct objtool_file *file, struct instruction *insn) in validate_entry() argument
3199 next = next_insn_to_validate(file, insn); in validate_entry()
3201 if (insn->visited & VISITED_ENTRY) in validate_entry()
3204 insn->visited |= VISITED_ENTRY; in validate_entry()
3206 if (!insn->ignore_alts && !list_empty(&insn->alts)) { in validate_entry()
3210 list_for_each_entry(alt, &insn->alts, list) { in validate_entry()
3214 ret = validate_entry(file, alt->insn); in validate_entry()
3217 BT_FUNC("(alt)", insn); in validate_entry()
3226 switch (insn->type) { in validate_entry()
3231 WARN_FUNC("early indirect call", insn->sec, insn->offset); in validate_entry()
3236 if (!is_sibling_call(insn)) { in validate_entry()
3237 if (!insn->jump_dest) { in validate_entry()
3239 insn->sec, insn->offset); in validate_entry()
3242 ret = validate_entry(file, insn->jump_dest); in validate_entry()
3245 BT_FUNC("(branch%s)", insn, in validate_entry()
3246 insn->type == INSN_JUMP_CONDITIONAL ? "-cond" : ""); in validate_entry()
3251 if (insn->type == INSN_JUMP_UNCONDITIONAL) in validate_entry()
3259 dest = find_insn(file, insn->call_dest->sec, in validate_entry()
3260 insn->call_dest->offset); in validate_entry()
3263 insn->call_dest->name); in validate_entry()
3270 BT_FUNC("(call)", insn); in validate_entry()
3280 WARN_FUNC("RET before UNTRAIN", insn->sec, insn->offset); in validate_entry()
3284 if (insn->retpoline_safe) in validate_entry()
3293 WARN_FUNC("teh end!", insn->sec, insn->offset); in validate_entry()
3296 insn = next; in validate_entry()
3308 struct instruction *insn; in validate_unret() local
3311 for_each_insn(file, insn) { in validate_unret()
3312 if (!insn->entry) in validate_unret()
3315 ret = validate_entry(file, insn); in validate_unret()
3317 WARN_FUNC("Failed UNRET validation", insn->sec, insn->offset); in validate_unret()
3328 struct instruction *insn; in validate_retpoline() local
3331 for_each_insn(file, insn) { in validate_retpoline()
3332 if (insn->type != INSN_JUMP_DYNAMIC && in validate_retpoline()
3333 insn->type != INSN_CALL_DYNAMIC && in validate_retpoline()
3334 insn->type != INSN_RETURN) in validate_retpoline()
3337 if (insn->retpoline_safe) in validate_retpoline()
3346 if (!strcmp(insn->sec->name, ".init.text") && !module) in validate_retpoline()
3349 if (insn->type == INSN_RETURN) { in validate_retpoline()
3352 insn->sec, insn->offset); in validate_retpoline()
3357 insn->sec, insn->offset, in validate_retpoline()
3358 insn->type == INSN_JUMP_DYNAMIC ? "jump" : "call"); in validate_retpoline()
3367 static bool is_kasan_insn(struct instruction *insn) in is_kasan_insn() argument
3369 return (insn->type == INSN_CALL && in is_kasan_insn()
3370 !strcmp(insn->call_dest->name, "__asan_handle_no_return")); in is_kasan_insn()
3373 static bool is_ubsan_insn(struct instruction *insn) in is_ubsan_insn() argument
3375 return (insn->type == INSN_CALL && in is_ubsan_insn()
3376 !strcmp(insn->call_dest->name, in is_ubsan_insn()
3380 static bool ignore_unreachable_insn(struct objtool_file *file, struct instruction *insn) in ignore_unreachable_insn() argument
3385 if (insn->ignore || insn->type == INSN_NOP || insn->type == INSN_TRAP) in ignore_unreachable_insn()
3395 if (!strcmp(insn->sec->name, ".fixup") || in ignore_unreachable_insn()
3396 !strcmp(insn->sec->name, ".altinstr_replacement") || in ignore_unreachable_insn()
3397 !strcmp(insn->sec->name, ".altinstr_aux")) in ignore_unreachable_insn()
3400 if (!insn->func) in ignore_unreachable_insn()
3411 prev_insn = list_prev_entry(insn, list); in ignore_unreachable_insn()
3413 (insn->type == INSN_BUG || in ignore_unreachable_insn()
3414 (insn->type == INSN_JUMP_UNCONDITIONAL && in ignore_unreachable_insn()
3415 insn->jump_dest && insn->jump_dest->type == INSN_BUG))) in ignore_unreachable_insn()
3426 if (is_kasan_insn(insn) || is_ubsan_insn(insn)) in ignore_unreachable_insn()
3429 if (insn->type == INSN_JUMP_UNCONDITIONAL) { in ignore_unreachable_insn()
3430 if (insn->jump_dest && in ignore_unreachable_insn()
3431 insn->jump_dest->func == insn->func) { in ignore_unreachable_insn()
3432 insn = insn->jump_dest; in ignore_unreachable_insn()
3439 if (insn->offset + insn->len >= insn->func->offset + insn->func->len) in ignore_unreachable_insn()
3442 insn = list_next_entry(insn, list); in ignore_unreachable_insn()
3451 struct instruction *insn; in validate_symbol() local
3462 insn = find_insn(file, sec, sym->offset); in validate_symbol()
3463 if (!insn || insn->ignore || insn->visited) in validate_symbol()
3468 ret = validate_branch(file, insn->func, insn, *state); in validate_symbol()
3470 BT_FUNC("<=== (sym)", insn); in validate_symbol()
3530 struct instruction *insn; in validate_reachable_instructions() local
3535 for_each_insn(file, insn) { in validate_reachable_instructions()
3536 if (insn->visited || ignore_unreachable_insn(file, insn)) in validate_reachable_instructions()
3539 WARN_FUNC("unreachable instruction", insn->sec, insn->offset); in validate_reachable_instructions()