• Home
  • Raw
  • Download

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
200 insn = find_insn(file, func->sec, func->offset); in __dead_end_function()
201 if (!insn || !insn->func) in __dead_end_function()
204 func_for_each_insn(file, func, insn) { in __dead_end_function()
207 if (insn->type == INSN_RETURN) in __dead_end_function()
219 func_for_each_insn(file, func, insn) { in __dead_end_function()
220 if (is_sibling_call(insn)) { in __dead_end_function()
221 struct instruction *dest = insn->jump_dest; in __dead_end_function()
357 struct instruction *insn; in decode_instructions() local
375 for (offset = 0; offset < sec->len; offset += insn->len) { in decode_instructions()
376 insn = malloc(sizeof(*insn)); in decode_instructions()
377 if (!insn) { in decode_instructions()
381 memset(insn, 0, sizeof(*insn)); in decode_instructions()
382 INIT_LIST_HEAD(&insn->alts); in decode_instructions()
383 INIT_LIST_HEAD(&insn->stack_ops); in decode_instructions()
385 insn->sec = sec; in decode_instructions()
386 insn->offset = offset; in decode_instructions()
390 &insn->len, &insn->type, in decode_instructions()
391 &insn->immediate, in decode_instructions()
392 &insn->stack_ops); in decode_instructions()
396 hash_add(file->insn_hash, &insn->hash, sec_offset_hash(sec, insn->offset)); in decode_instructions()
397 list_add_tail(&insn->list, &file->insn_list); in decode_instructions()
411 sym_for_each_insn(file, func, insn) in decode_instructions()
412 insn->func = func; in decode_instructions()
422 free(insn); in decode_instructions()
429 struct instruction *insn = NULL; in find_last_insn() local
433 for (offset = sec->len - 1; offset >= end && !insn; offset--) in find_last_insn()
434 insn = find_insn(file, sec, offset); in find_last_insn()
436 return insn; in find_last_insn()
446 struct instruction *insn; in add_dead_ends() local
452 for_each_insn(file, insn) in add_dead_ends()
453 if (insn->type == INSN_BUG) in add_dead_ends()
454 insn->dead_end = true; in add_dead_ends()
468 insn = find_insn(file, reloc->sym->sec, reloc->addend); in add_dead_ends()
469 if (insn) in add_dead_ends()
470 insn = list_prev_entry(insn, list); in add_dead_ends()
472 insn = find_last_insn(file, reloc->sym->sec); in add_dead_ends()
473 if (!insn) { in add_dead_ends()
484 insn->dead_end = true; in add_dead_ends()
503 insn = find_insn(file, reloc->sym->sec, reloc->addend); in add_dead_ends()
504 if (insn) in add_dead_ends()
505 insn = list_prev_entry(insn, list); in add_dead_ends()
507 insn = find_last_insn(file, reloc->sym->sec); in add_dead_ends()
508 if (!insn) { in add_dead_ends()
519 insn->dead_end = false; in add_dead_ends()
529 struct instruction *insn; in create_static_call_sections() local
545 list_for_each_entry(insn, &file->static_call_list, call_node) in create_static_call_sections()
554 list_for_each_entry(insn, &file->static_call_list, call_node) { in create_static_call_sections()
563 insn->sec, insn->offset)) in create_static_call_sections()
567 key_name = strdup(insn->call_dest->name); in create_static_call_sections()
598 key_sym = insn->call_dest; in create_static_call_sections()
606 is_sibling_call(insn) * STATIC_CALL_SITE_TAIL)) in create_static_call_sections()
617 struct instruction *insn; in create_retpoline_sites_sections() local
628 list_for_each_entry(insn, &file->retpoline_call_list, call_node) in create_retpoline_sites_sections()
642 list_for_each_entry(insn, &file->retpoline_call_list, call_node) { in create_retpoline_sites_sections()
650 insn->sec, insn->offset)) { in create_retpoline_sites_sections()
663 struct instruction *insn; in create_return_sites_sections() local
674 list_for_each_entry(insn, &file->return_thunk_list, call_node) in create_return_sites_sections()
688 list_for_each_entry(insn, &file->return_thunk_list, call_node) { in create_return_sites_sections()
696 insn->sec, insn->offset)) { in create_return_sites_sections()
711 struct instruction *insn; in create_mcount_loc_sections() local
725 list_for_each_entry(insn, &file->mcount_loc_list, mcount_loc_node) in create_mcount_loc_sections()
733 list_for_each_entry(insn, &file->mcount_loc_list, mcount_loc_node) { in create_mcount_loc_sections()
741 insn->sec, insn->offset)) in create_mcount_loc_sections()
755 struct instruction *insn; in add_ignores() local
781 func_for_each_insn(file, func, insn) in add_ignores()
782 insn->ignore = true; in add_ignores()
968 struct instruction *insn; in add_ignore_alternatives() local
980 insn = find_insn(file, reloc->sym->sec, reloc->addend); in add_ignore_alternatives()
981 if (!insn) { in add_ignore_alternatives()
986 insn->ignore_alts = true; in add_ignore_alternatives()
1021 static struct reloc *insn_reloc(struct objtool_file *file, struct instruction *insn) in insn_reloc() argument
1023 if (insn->reloc == NEGATIVE_RELOC) in insn_reloc()
1026 if (!insn->reloc) { in insn_reloc()
1027 insn->reloc = find_reloc_by_dest_range(file->elf, insn->sec, in insn_reloc()
1028 insn->offset, insn->len); in insn_reloc()
1029 if (!insn->reloc) { in insn_reloc()
1030 insn->reloc = NEGATIVE_RELOC; in insn_reloc()
1035 return insn->reloc; in insn_reloc()
1038 static void remove_insn_ops(struct instruction *insn) in remove_insn_ops() argument
1042 list_for_each_entry_safe(op, tmp, &insn->stack_ops, list) { in remove_insn_ops()
1049 struct instruction *insn, bool sibling) in annotate_call_site() argument
1051 struct reloc *reloc = insn_reloc(file, insn); in annotate_call_site()
1052 struct symbol *sym = insn->call_dest; in annotate_call_site()
1063 if (!strcmp(insn->sec->name, ".altinstr_replacement")) in annotate_call_site()
1067 list_add_tail(&insn->call_node, &file->static_call_list); in annotate_call_site()
1072 list_add_tail(&insn->call_node, &file->retpoline_call_list); in annotate_call_site()
1081 if (insn->sec->noinstr && sym->kcov) { in annotate_call_site()
1087 elf_write_insn(file->elf, insn->sec, in annotate_call_site()
1088 insn->offset, insn->len, in annotate_call_site()
1089 sibling ? arch_ret_insn(insn->len) in annotate_call_site()
1090 : arch_nop_insn(insn->len)); in annotate_call_site()
1092 insn->type = sibling ? INSN_RETURN : INSN_NOP; in annotate_call_site()
1101 insn->retpoline_safe = true; in annotate_call_site()
1108 static void add_call_dest(struct objtool_file *file, struct instruction *insn, in add_call_dest() argument
1111 insn->call_dest = dest; in add_call_dest()
1122 remove_insn_ops(insn); in add_call_dest()
1124 annotate_call_site(file, insn, sibling); in add_call_dest()
1127 static void add_retpoline_call(struct objtool_file *file, struct instruction *insn) in add_retpoline_call() argument
1133 switch (insn->type) { in add_retpoline_call()
1135 insn->type = INSN_CALL_DYNAMIC; in add_retpoline_call()
1138 insn->type = INSN_JUMP_DYNAMIC; in add_retpoline_call()
1141 insn->type = INSN_JUMP_DYNAMIC_CONDITIONAL; in add_retpoline_call()
1147 insn->retpoline_safe = true; in add_retpoline_call()
1156 remove_insn_ops(insn); in add_retpoline_call()
1158 annotate_call_site(file, insn, false); in add_retpoline_call()
1161 static void add_return_call(struct objtool_file *file, struct instruction *insn, bool add) in add_return_call() argument
1167 insn->type = INSN_RETURN; in add_return_call()
1168 insn->retpoline_safe = true; in add_return_call()
1171 if (add && insn->sec->text) in add_return_call()
1172 list_add_tail(&insn->call_node, &file->return_thunk_list); in add_return_call()
1193 struct instruction *insn; in add_cfi_jumptables() local
1200 sym_for_each_insn(file, func, insn) in add_cfi_jumptables()
1201 insn->ignore = true; in add_cfi_jumptables()
1211 struct instruction *insn; in add_jump_destinations() local
1216 for_each_insn(file, insn) { in add_jump_destinations()
1217 if (!is_static_jump(insn)) in add_jump_destinations()
1220 reloc = insn_reloc(file, insn); in add_jump_destinations()
1222 dest_sec = insn->sec; in add_jump_destinations()
1223 dest_off = arch_jump_destination(insn); in add_jump_destinations()
1228 add_retpoline_call(file, insn); in add_jump_destinations()
1231 add_return_call(file, insn, true); in add_jump_destinations()
1233 } else if (insn->func) { in add_jump_destinations()
1235 add_call_dest(file, insn, reloc->sym, true); in add_jump_destinations()
1246 insn->jump_dest = find_insn(file, dest_sec, dest_off); in add_jump_destinations()
1248 if (!insn->jump_dest && dest_sec->len == dest_off) in add_jump_destinations()
1249 insn->jump_dest = find_last_insn(file, dest_sec); in add_jump_destinations()
1251 if (!insn->jump_dest) { in add_jump_destinations()
1259 if (!strcmp(insn->sec->name, ".altinstr_replacement")) in add_jump_destinations()
1262 if (is_cfi_section(insn->sec)) in add_jump_destinations()
1274 add_return_call(file, insn, false); in add_jump_destinations()
1279 insn->sec, insn->offset, dest_sec->name, in add_jump_destinations()
1287 if (insn->func && insn->jump_dest->func && in add_jump_destinations()
1288 insn->func != insn->jump_dest->func) { in add_jump_destinations()
1305 if (!strstr(insn->func->name, ".cold") && in add_jump_destinations()
1306 strstr(insn->jump_dest->func->name, ".cold")) { in add_jump_destinations()
1307 insn->func->cfunc = insn->jump_dest->func; in add_jump_destinations()
1308 insn->jump_dest->func->pfunc = insn->func; in add_jump_destinations()
1310 } else if (insn->jump_dest->func->pfunc != insn->func->pfunc && in add_jump_destinations()
1311 insn->jump_dest->offset == insn->jump_dest->func->offset) { in add_jump_destinations()
1313 add_call_dest(file, insn, insn->jump_dest->func, true); in add_jump_destinations()
1337 struct instruction *insn; in add_call_destinations() local
1342 for_each_insn(file, insn) { in add_call_destinations()
1343 if (insn->type != INSN_CALL) in add_call_destinations()
1346 reloc = insn_reloc(file, insn); in add_call_destinations()
1348 dest_off = arch_jump_destination(insn); in add_call_destinations()
1349 dest = find_call_destination(insn->sec, dest_off); in add_call_destinations()
1351 add_call_dest(file, insn, dest, false); in add_call_destinations()
1353 if (insn->ignore) in add_call_destinations()
1356 if (!insn->call_dest) { in add_call_destinations()
1357 WARN_FUNC("unannotated intra-function call", insn->sec, insn->offset); in add_call_destinations()
1361 if (insn->func && insn->call_dest->type != STT_FUNC) { in add_call_destinations()
1363 insn->sec, insn->offset); in add_call_destinations()
1375 insn->sec, insn->offset, in add_call_destinations()
1381 add_call_dest(file, insn, dest, false); in add_call_destinations()
1384 add_retpoline_call(file, insn); in add_call_destinations()
1387 add_call_dest(file, insn, reloc->sym, false); in add_call_destinations()
1402 struct instruction *last_orig_insn, *last_new_insn = NULL, *insn, *nop = NULL; in handle_group_alt() local
1420 insn = orig_insn; in handle_group_alt()
1421 sec_for_each_insn_from(file, insn) { in handle_group_alt()
1422 if (insn->offset >= special_alt->orig_off + special_alt->orig_len) in handle_group_alt()
1425 insn->alt_group = orig_alt_group; in handle_group_alt()
1426 last_orig_insn = insn; in handle_group_alt()
1470 insn = *new_insn; in handle_group_alt()
1471 sec_for_each_insn_from(file, insn) { in handle_group_alt()
1474 if (insn->offset >= special_alt->new_off + special_alt->new_len) in handle_group_alt()
1477 last_new_insn = insn; in handle_group_alt()
1479 insn->ignore = orig_insn->ignore_alts; in handle_group_alt()
1480 insn->func = orig_insn->func; in handle_group_alt()
1481 insn->alt_group = new_alt_group; in handle_group_alt()
1491 alt_reloc = insn_reloc(file, insn); in handle_group_alt()
1493 !arch_support_alt_relocation(special_alt, insn, alt_reloc)) { in handle_group_alt()
1496 insn->sec, insn->offset); in handle_group_alt()
1500 if (!is_static_jump(insn)) in handle_group_alt()
1503 if (!insn->immediate) in handle_group_alt()
1506 dest_off = arch_jump_destination(insn); in handle_group_alt()
1508 insn->jump_dest = next_insn_same_sec(file, last_orig_insn); in handle_group_alt()
1510 if (!insn->jump_dest) { in handle_group_alt()
1512 insn->sec, insn->offset); in handle_group_alt()
1623 alt->insn = new_insn; in add_special_section_alts()
1636 static int add_jump_table(struct objtool_file *file, struct instruction *insn, in add_jump_table() argument
1642 struct symbol *pfunc = insn->func->pfunc; in add_jump_table()
1678 alt->insn = dest_insn; in add_jump_table()
1679 list_add_tail(&alt->list, &insn->alts); in add_jump_table()
1685 insn->sec, insn->offset); in add_jump_table()
1698 struct instruction *insn) in find_jump_table() argument
1701 struct instruction *dest_insn, *orig_insn = insn; in find_jump_table()
1709 insn && insn->func && insn->func->pfunc == func; in find_jump_table()
1710 insn = insn->first_jump_src ?: prev_insn_same_sym(file, insn)) { in find_jump_table()
1712 if (insn != orig_insn && insn->type == INSN_JUMP_DYNAMIC) in find_jump_table()
1716 if (insn->type == INSN_JUMP_UNCONDITIONAL && in find_jump_table()
1717 insn->jump_dest && in find_jump_table()
1718 (insn->jump_dest->offset <= insn->offset || in find_jump_table()
1719 insn->jump_dest->offset > orig_insn->offset)) in find_jump_table()
1722 table_reloc = arch_find_switch_table(file, insn); in find_jump_table()
1742 struct instruction *insn, *last = NULL; in mark_func_jump_tables() local
1745 func_for_each_insn(file, func, insn) { in mark_func_jump_tables()
1747 last = insn; in mark_func_jump_tables()
1754 if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest && in mark_func_jump_tables()
1755 insn->offset > last->offset && in mark_func_jump_tables()
1756 insn->jump_dest->offset > insn->offset && in mark_func_jump_tables()
1757 !insn->jump_dest->first_jump_src) { in mark_func_jump_tables()
1759 insn->jump_dest->first_jump_src = insn; in mark_func_jump_tables()
1760 last = insn->jump_dest; in mark_func_jump_tables()
1763 if (insn->type != INSN_JUMP_DYNAMIC) in mark_func_jump_tables()
1766 reloc = find_jump_table(file, func, insn); in mark_func_jump_tables()
1769 insn->jump_table = reloc; in mark_func_jump_tables()
1777 struct instruction *insn; in add_func_jump_tables() local
1780 func_for_each_insn(file, func, insn) { in add_func_jump_tables()
1781 if (!insn->jump_table) in add_func_jump_tables()
1784 ret = add_jump_table(file, insn, insn->jump_table); in add_func_jump_tables()
1834 struct instruction *insn; in read_unwind_hints() local
1864 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_unwind_hints()
1865 if (!insn) { in read_unwind_hints()
1870 insn->hint = true; in read_unwind_hints()
1873 insn->hint = false; in read_unwind_hints()
1874 insn->save = true; in read_unwind_hints()
1879 insn->restore = true; in read_unwind_hints()
1884 struct symbol *sym = find_symbol_by_offset(insn->sec, insn->offset); in read_unwind_hints()
1887 insn->entry = 1; in read_unwind_hints()
1893 insn->entry = 1; in read_unwind_hints()
1897 insn->cfi = &func_cfi; in read_unwind_hints()
1901 if (insn->cfi) in read_unwind_hints()
1902 cfi = *(insn->cfi); in read_unwind_hints()
1906 insn->sec, insn->offset, hint->sp_reg); in read_unwind_hints()
1914 insn->cfi = cfi_hash_find_or_add(&cfi); in read_unwind_hints()
1923 struct instruction *insn; in read_retpoline_hints() local
1936 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_retpoline_hints()
1937 if (!insn) { in read_retpoline_hints()
1942 if (insn->type != INSN_JUMP_DYNAMIC && in read_retpoline_hints()
1943 insn->type != INSN_CALL_DYNAMIC && in read_retpoline_hints()
1944 insn->type != INSN_RETURN && in read_retpoline_hints()
1945 insn->type != INSN_NOP) { in read_retpoline_hints()
1947 insn->sec, insn->offset); in read_retpoline_hints()
1951 insn->retpoline_safe = true; in read_retpoline_hints()
1960 struct instruction *insn; in read_instr_hints() local
1973 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_instr_hints()
1974 if (!insn) { in read_instr_hints()
1979 insn->instr--; in read_instr_hints()
1992 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_instr_hints()
1993 if (!insn) { in read_instr_hints()
1998 insn->instr++; in read_instr_hints()
2006 struct instruction *insn; in read_intra_function_calls() local
2023 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_intra_function_calls()
2024 if (!insn) { in read_intra_function_calls()
2029 if (insn->type != INSN_CALL) { in read_intra_function_calls()
2031 insn->sec, insn->offset); in read_intra_function_calls()
2040 insn->type = INSN_JUMP_UNCONDITIONAL; in read_intra_function_calls()
2042 dest_off = insn->offset + insn->len + insn->immediate; in read_intra_function_calls()
2043 insn->jump_dest = find_insn(file, insn->sec, dest_off); in read_intra_function_calls()
2044 if (!insn->jump_dest) { in read_intra_function_calls()
2046 insn->sec, insn->offset, in read_intra_function_calls()
2047 insn->sec->name, dest_off); in read_intra_function_calls()
2187 static bool is_special_call(struct instruction *insn) in is_special_call() argument
2189 if (insn->type == INSN_CALL) { in is_special_call()
2190 struct symbol *dest = insn->call_dest; in is_special_call()
2202 static bool has_modified_stack_frame(struct instruction *insn, struct insn_state *state) in has_modified_stack_frame() argument
2239 static int update_cfi_state_regs(struct instruction *insn, in update_cfi_state_regs() argument
2332 static int update_cfi_state(struct instruction *insn, struct cfi_state *cfi, in update_cfi_state() argument
2340 if (insn->func) { in update_cfi_state()
2341 WARN_FUNC("undefined stack state", insn->sec, insn->offset); in update_cfi_state()
2349 return update_cfi_state_regs(insn, cfi, op); in update_cfi_state()
2480 insn->sec, insn->offset); in update_cfi_state()
2491 insn->sec, insn->offset); in update_cfi_state()
2566 insn->sec, insn->offset); in update_cfi_state()
2609 if (!no_fp && insn->func && op->src.reg == CFI_BP && in update_cfi_state()
2645 insn->sec, insn->offset); in update_cfi_state()
2664 insn->sec, insn->offset); in update_cfi_state()
2677 insn->sec, insn->offset); in update_cfi_state()
2693 static int propagate_alt_cfi(struct objtool_file *file, struct instruction *insn) in propagate_alt_cfi() argument
2698 if (!insn->alt_group) in propagate_alt_cfi()
2701 if (!insn->cfi) { in propagate_alt_cfi()
2706 alt_cfi = insn->alt_group->cfi; in propagate_alt_cfi()
2707 group_off = insn->offset - insn->alt_group->first_insn->offset; in propagate_alt_cfi()
2710 alt_cfi[group_off] = insn->cfi; in propagate_alt_cfi()
2712 if (cficmp(alt_cfi[group_off], insn->cfi)) { in propagate_alt_cfi()
2714 insn->sec, insn->offset); in propagate_alt_cfi()
2722 static int handle_insn_ops(struct instruction *insn, struct insn_state *state) in handle_insn_ops() argument
2726 list_for_each_entry(op, &insn->stack_ops, list) { in handle_insn_ops()
2728 if (update_cfi_state(insn, &state->cfi, op)) in handle_insn_ops()
2736 insn->sec, insn->offset); in handle_insn_ops()
2756 static bool insn_cfi_match(struct instruction *insn, struct cfi_state *cfi2) in insn_cfi_match() argument
2758 struct cfi_state *cfi1 = insn->cfi; in insn_cfi_match()
2769 insn->sec, insn->offset, in insn_cfi_match()
2780 insn->sec, insn->offset, in insn_cfi_match()
2789 insn->sec, insn->offset, cfi1->type, cfi2->type); in insn_cfi_match()
2796 insn->sec, insn->offset, in insn_cfi_match()
2814 static inline const char *call_dest_name(struct instruction *insn) in call_dest_name() argument
2816 if (insn->call_dest) in call_dest_name()
2817 return insn->call_dest->name; in call_dest_name()
2848 static int validate_call(struct instruction *insn, struct insn_state *state) in validate_call() argument
2851 !noinstr_call_dest(insn->call_dest)) { in validate_call()
2853 insn->sec, insn->offset, call_dest_name(insn)); in validate_call()
2857 if (state->uaccess && !func_uaccess_safe(insn->call_dest)) { in validate_call()
2859 insn->sec, insn->offset, call_dest_name(insn)); in validate_call()
2865 insn->sec, insn->offset, call_dest_name(insn)); in validate_call()
2872 static int validate_sibling_call(struct instruction *insn, struct insn_state *state) in validate_sibling_call() argument
2874 if (has_modified_stack_frame(insn, state)) { in validate_sibling_call()
2876 insn->sec, insn->offset); in validate_sibling_call()
2880 return validate_call(insn, state); in validate_sibling_call()
2883 static int validate_return(struct symbol *func, struct instruction *insn, struct insn_state *state) in validate_return() argument
2887 insn->sec, insn->offset); in validate_return()
2893 insn->sec, insn->offset); in validate_return()
2899 insn->sec, insn->offset); in validate_return()
2905 insn->sec, insn->offset); in validate_return()
2909 if (func && has_modified_stack_frame(insn, state)) { in validate_return()
2911 insn->sec, insn->offset); in validate_return()
2917 insn->sec, insn->offset); in validate_return()
2925 struct instruction *insn) in next_insn_to_validate() argument
2927 struct alt_group *alt_group = insn->alt_group; in next_insn_to_validate()
2934 if (alt_group && insn == alt_group->last_insn && alt_group->orig_group) in next_insn_to_validate()
2937 return next_insn_same_sec(file, insn); in next_insn_to_validate()
2947 struct instruction *insn, struct insn_state state) in validate_branch() argument
2955 sec = insn->sec; in validate_branch()
2958 next_insn = next_insn_to_validate(file, insn); in validate_branch()
2960 if (file->c_file && func && insn->func && func != insn->func->pfunc) { in validate_branch()
2962 func->name, insn->func->name); in validate_branch()
2966 if (func && insn->ignore) { in validate_branch()
2968 sec, insn->offset); in validate_branch()
2973 if (insn->visited & VISITED_BRANCH_MASK) { in validate_branch()
2974 if (!insn->hint && !insn_cfi_match(insn, &state.cfi)) in validate_branch()
2977 if (insn->visited & visited) in validate_branch()
2984 state.instr += insn->instr; in validate_branch()
2986 if (insn->hint) { in validate_branch()
2987 if (insn->restore) { in validate_branch()
2990 i = insn; in validate_branch()
3002 sec, insn->offset); in validate_branch()
3008 sec, insn->offset); in validate_branch()
3012 insn->cfi = save_insn->cfi; in validate_branch()
3016 state.cfi = *insn->cfi; in validate_branch()
3021 insn->cfi = prev_insn->cfi; in validate_branch()
3024 insn->cfi = cfi_hash_find_or_add(&state.cfi); in validate_branch()
3028 insn->visited |= visited; in validate_branch()
3030 if (propagate_alt_cfi(file, insn)) in validate_branch()
3033 if (!insn->ignore_alts && !list_empty(&insn->alts)) { in validate_branch()
3036 list_for_each_entry(alt, &insn->alts, list) { in validate_branch()
3040 ret = validate_branch(file, func, alt->insn, state); in validate_branch()
3043 BT_FUNC("(alt)", insn); in validate_branch()
3052 if (handle_insn_ops(insn, &state)) in validate_branch()
3055 switch (insn->type) { in validate_branch()
3058 if (sls && !insn->retpoline_safe && in validate_branch()
3061 insn->sec, insn->offset); in validate_branch()
3063 return validate_return(func, insn, &state); in validate_branch()
3067 ret = validate_call(insn, &state); in validate_branch()
3071 if (!no_fp && func && !is_special_call(insn) && in validate_branch()
3074 sec, insn->offset); in validate_branch()
3078 if (dead_end_function(file, insn->call_dest)) in validate_branch()
3085 if (is_sibling_call(insn)) { in validate_branch()
3086 ret = validate_sibling_call(insn, &state); in validate_branch()
3090 } else if (insn->jump_dest) { in validate_branch()
3092 insn->jump_dest, state); in validate_branch()
3095 BT_FUNC("(branch)", insn); in validate_branch()
3100 if (insn->type == INSN_JUMP_UNCONDITIONAL) in validate_branch()
3106 if (sls && !insn->retpoline_safe && in validate_branch()
3109 insn->sec, insn->offset); in validate_branch()
3114 if (is_sibling_call(insn)) { in validate_branch()
3115 ret = validate_sibling_call(insn, &state); in validate_branch()
3120 if (insn->type == INSN_JUMP_DYNAMIC) in validate_branch()
3128 sec, insn->offset); in validate_branch()
3135 WARN_FUNC("recursive UACCESS enable", sec, insn->offset); in validate_branch()
3144 WARN_FUNC("redundant UACCESS disable", sec, insn->offset); in validate_branch()
3149 WARN_FUNC("UACCESS-safe disables UACCESS", sec, insn->offset); in validate_branch()
3158 WARN_FUNC("recursive STD", sec, insn->offset); in validate_branch()
3167 WARN_FUNC("redundant CLD", sec, insn->offset); in validate_branch()
3178 if (insn->dead_end) in validate_branch()
3188 prev_insn = insn; in validate_branch()
3189 insn = next_insn; in validate_branch()
3197 struct instruction *insn; in validate_unwind_hints() local
3207 insn = find_insn(file, sec, 0); in validate_unwind_hints()
3208 if (!insn) in validate_unwind_hints()
3211 insn = list_first_entry(&file->insn_list, typeof(*insn), list); in validate_unwind_hints()
3214 while (&insn->list != &file->insn_list && (!sec || insn->sec == sec)) { in validate_unwind_hints()
3215 if (insn->hint && !insn->visited) { in validate_unwind_hints()
3216 ret = validate_branch(file, insn->func, insn, state); in validate_unwind_hints()
3218 BT_FUNC("<=== (hint)", insn); in validate_unwind_hints()
3222 insn = list_next_entry(insn, list); in validate_unwind_hints()
3234 static int validate_entry(struct objtool_file *file, struct instruction *insn) in validate_entry() argument
3240 next = next_insn_to_validate(file, insn); in validate_entry()
3242 if (insn->visited & VISITED_ENTRY) in validate_entry()
3245 insn->visited |= VISITED_ENTRY; in validate_entry()
3247 if (!insn->ignore_alts && !list_empty(&insn->alts)) { in validate_entry()
3251 list_for_each_entry(alt, &insn->alts, list) { in validate_entry()
3255 ret = validate_entry(file, alt->insn); in validate_entry()
3258 BT_FUNC("(alt)", insn); in validate_entry()
3267 switch (insn->type) { in validate_entry()
3272 WARN_FUNC("early indirect call", insn->sec, insn->offset); in validate_entry()
3277 if (!is_sibling_call(insn)) { in validate_entry()
3278 if (!insn->jump_dest) { in validate_entry()
3280 insn->sec, insn->offset); in validate_entry()
3283 ret = validate_entry(file, insn->jump_dest); in validate_entry()
3286 BT_FUNC("(branch%s)", insn, in validate_entry()
3287 insn->type == INSN_JUMP_CONDITIONAL ? "-cond" : ""); in validate_entry()
3292 if (insn->type == INSN_JUMP_UNCONDITIONAL) in validate_entry()
3300 dest = find_insn(file, insn->call_dest->sec, in validate_entry()
3301 insn->call_dest->offset); in validate_entry()
3304 insn->call_dest->name); in validate_entry()
3311 BT_FUNC("(call)", insn); in validate_entry()
3321 WARN_FUNC("RET before UNTRAIN", insn->sec, insn->offset); in validate_entry()
3325 if (insn->retpoline_safe) in validate_entry()
3334 WARN_FUNC("teh end!", insn->sec, insn->offset); in validate_entry()
3337 insn = next; in validate_entry()
3349 struct instruction *insn; in validate_unret() local
3352 for_each_insn(file, insn) { in validate_unret()
3353 if (!insn->entry) in validate_unret()
3356 ret = validate_entry(file, insn); in validate_unret()
3358 WARN_FUNC("Failed UNRET validation", insn->sec, insn->offset); in validate_unret()
3369 struct instruction *insn; in validate_retpoline() local
3372 for_each_insn(file, insn) { in validate_retpoline()
3373 if (insn->type != INSN_JUMP_DYNAMIC && in validate_retpoline()
3374 insn->type != INSN_CALL_DYNAMIC && in validate_retpoline()
3375 insn->type != INSN_RETURN) in validate_retpoline()
3378 if (insn->retpoline_safe) in validate_retpoline()
3387 if (!strcmp(insn->sec->name, ".init.text") && !module) in validate_retpoline()
3390 if (insn->type == INSN_RETURN) { in validate_retpoline()
3393 insn->sec, insn->offset); in validate_retpoline()
3398 insn->sec, insn->offset, in validate_retpoline()
3399 insn->type == INSN_JUMP_DYNAMIC ? "jump" : "call"); in validate_retpoline()
3408 static bool is_kasan_insn(struct instruction *insn) in is_kasan_insn() argument
3410 return (insn->type == INSN_CALL && in is_kasan_insn()
3411 !strcmp(insn->call_dest->name, "__asan_handle_no_return")); in is_kasan_insn()
3414 static bool is_ubsan_insn(struct instruction *insn) in is_ubsan_insn() argument
3416 return (insn->type == INSN_CALL && in is_ubsan_insn()
3417 !strcmp(insn->call_dest->name, in is_ubsan_insn()
3421 static bool ignore_unreachable_insn(struct objtool_file *file, struct instruction *insn) in ignore_unreachable_insn() argument
3426 if (insn->ignore || insn->type == INSN_NOP || insn->type == INSN_TRAP) in ignore_unreachable_insn()
3436 if (!strcmp(insn->sec->name, ".fixup") || in ignore_unreachable_insn()
3437 !strcmp(insn->sec->name, ".altinstr_replacement") || in ignore_unreachable_insn()
3438 !strcmp(insn->sec->name, ".altinstr_aux")) in ignore_unreachable_insn()
3441 if (!insn->func) in ignore_unreachable_insn()
3452 prev_insn = list_prev_entry(insn, list); in ignore_unreachable_insn()
3454 (insn->type == INSN_BUG || in ignore_unreachable_insn()
3455 (insn->type == INSN_JUMP_UNCONDITIONAL && in ignore_unreachable_insn()
3456 insn->jump_dest && insn->jump_dest->type == INSN_BUG))) in ignore_unreachable_insn()
3467 if (is_kasan_insn(insn) || is_ubsan_insn(insn)) in ignore_unreachable_insn()
3470 if (insn->type == INSN_JUMP_UNCONDITIONAL) { in ignore_unreachable_insn()
3471 if (insn->jump_dest && in ignore_unreachable_insn()
3472 insn->jump_dest->func == insn->func) { in ignore_unreachable_insn()
3473 insn = insn->jump_dest; in ignore_unreachable_insn()
3480 if (insn->offset + insn->len >= insn->func->offset + insn->func->len) in ignore_unreachable_insn()
3483 insn = list_next_entry(insn, list); in ignore_unreachable_insn()
3492 struct instruction *insn; in validate_symbol() local
3503 insn = find_insn(file, sec, sym->offset); in validate_symbol()
3504 if (!insn || insn->ignore || insn->visited) in validate_symbol()
3509 ret = validate_branch(file, insn->func, insn, *state); in validate_symbol()
3511 BT_FUNC("<=== (sym)", insn); in validate_symbol()
3571 struct instruction *insn; in validate_reachable_instructions() local
3576 for_each_insn(file, insn) { in validate_reachable_instructions()
3577 if (insn->visited || ignore_unreachable_insn(file, insn)) in validate_reachable_instructions()
3580 WARN_FUNC("unreachable instruction", insn->sec, insn->offset); in validate_reachable_instructions()