Lines Matching refs:insn
33 struct instruction *insn; member
42 struct instruction *insn; in find_insn() local
44 hash_for_each_possible(file->insn_hash, insn, hash, offset) in find_insn()
45 if (insn->sec == sec && insn->offset == offset) in find_insn()
46 return insn; in find_insn()
52 struct instruction *insn) in next_insn_same_sec() argument
54 struct instruction *next = list_next_entry(insn, list); in next_insn_same_sec()
56 if (!next || &next->list == &file->insn_list || next->sec != insn->sec) in next_insn_same_sec()
63 struct instruction *insn) in next_insn_same_func() argument
65 struct instruction *next = list_next_entry(insn, list); in next_insn_same_func()
66 struct symbol *func = insn->func; in next_insn_same_func()
82 #define func_for_each_insn_all(file, func, insn) \ argument
83 for (insn = find_insn(file, func->sec, func->offset); \
84 insn; \
85 insn = next_insn_same_func(file, insn))
87 #define func_for_each_insn(file, func, insn) \ argument
88 for (insn = find_insn(file, func->sec, func->offset); \
89 insn && &insn->list != &file->insn_list && \
90 insn->sec == func->sec && \
91 insn->offset < func->offset + func->len; \
92 insn = list_next_entry(insn, list))
94 #define func_for_each_insn_continue_reverse(file, func, insn) \ argument
95 for (insn = list_prev_entry(insn, list); \
96 &insn->list != &file->insn_list && \
97 insn->sec == func->sec && insn->offset >= func->offset; \
98 insn = list_prev_entry(insn, list))
100 #define sec_for_each_insn_from(file, insn) \ argument
101 for (; insn; insn = next_insn_same_sec(file, insn))
103 #define sec_for_each_insn_continue(file, insn) \ argument
104 for (insn = next_insn_same_sec(file, insn); insn; \
105 insn = next_insn_same_sec(file, insn))
148 struct instruction *insn; in __dead_end_function() local
181 insn = find_insn(file, func->sec, func->offset); in __dead_end_function()
182 if (!insn->func) in __dead_end_function()
185 func_for_each_insn_all(file, func, insn) { in __dead_end_function()
188 if (insn->type == INSN_RETURN) in __dead_end_function()
200 func_for_each_insn_all(file, func, insn) { in __dead_end_function()
201 if (insn->type == INSN_JUMP_UNCONDITIONAL) { in __dead_end_function()
202 struct instruction *dest = insn->jump_dest; in __dead_end_function()
208 if (dest->func && dest->func->pfunc != insn->func->pfunc) { in __dead_end_function()
226 if (insn->type == INSN_JUMP_DYNAMIC && list_empty(&insn->alts)) in __dead_end_function()
262 struct instruction *insn; in decode_instructions() local
275 for (offset = 0; offset < sec->len; offset += insn->len) { in decode_instructions()
276 insn = malloc(sizeof(*insn)); in decode_instructions()
277 if (!insn) { in decode_instructions()
281 memset(insn, 0, sizeof(*insn)); in decode_instructions()
282 INIT_LIST_HEAD(&insn->alts); in decode_instructions()
283 clear_insn_state(&insn->state); in decode_instructions()
285 insn->sec = sec; in decode_instructions()
286 insn->offset = offset; in decode_instructions()
290 &insn->len, &insn->type, in decode_instructions()
291 &insn->immediate, in decode_instructions()
292 &insn->stack_op); in decode_instructions()
296 if (!insn->type || insn->type > INSN_LAST) { in decode_instructions()
298 insn->sec, insn->offset, insn->type); in decode_instructions()
303 hash_add(file->insn_hash, &insn->hash, insn->offset); in decode_instructions()
304 list_add_tail(&insn->list, &file->insn_list); in decode_instructions()
317 func_for_each_insn(file, func, insn) in decode_instructions()
318 if (!insn->func) in decode_instructions()
319 insn->func = func; in decode_instructions()
326 free(insn); in decode_instructions()
337 struct instruction *insn; in add_dead_ends() local
344 for_each_insn(file, insn) in add_dead_ends()
345 if (insn->type == INSN_BUG) in add_dead_ends()
346 insn->dead_end = true; in add_dead_ends()
360 insn = find_insn(file, rela->sym->sec, rela->addend); in add_dead_ends()
361 if (insn) in add_dead_ends()
362 insn = list_prev_entry(insn, list); in add_dead_ends()
365 list_for_each_entry_reverse(insn, &file->insn_list, list) { in add_dead_ends()
366 if (insn->sec == rela->sym->sec) { in add_dead_ends()
383 insn->dead_end = true; in add_dead_ends()
402 insn = find_insn(file, rela->sym->sec, rela->addend); in add_dead_ends()
403 if (insn) in add_dead_ends()
404 insn = list_prev_entry(insn, list); in add_dead_ends()
407 list_for_each_entry_reverse(insn, &file->insn_list, list) { in add_dead_ends()
408 if (insn->sec == rela->sym->sec) { in add_dead_ends()
425 insn->dead_end = false; in add_dead_ends()
436 struct instruction *insn; in add_ignores() local
448 func_for_each_insn_all(file, func, insn) in add_ignores()
449 insn->ignore = true; in add_ignores()
464 struct instruction *insn; in add_nospec_ignores() local
476 insn = find_insn(file, rela->sym->sec, rela->addend); in add_nospec_ignores()
477 if (!insn) { in add_nospec_ignores()
482 insn->ignore_alts = true; in add_nospec_ignores()
493 struct instruction *insn; in add_jump_destinations() local
498 for_each_insn(file, insn) { in add_jump_destinations()
499 if (insn->type != INSN_JUMP_CONDITIONAL && in add_jump_destinations()
500 insn->type != INSN_JUMP_UNCONDITIONAL) in add_jump_destinations()
503 if (insn->ignore) in add_jump_destinations()
506 rela = find_rela_by_dest_range(insn->sec, insn->offset, in add_jump_destinations()
507 insn->len); in add_jump_destinations()
509 dest_sec = insn->sec; in add_jump_destinations()
510 dest_off = insn->offset + insn->len + insn->immediate; in add_jump_destinations()
522 insn->type = INSN_JUMP_DYNAMIC; in add_jump_destinations()
523 insn->retpoline_safe = true; in add_jump_destinations()
527 insn->jump_dest = 0; in add_jump_destinations()
531 insn->jump_dest = find_insn(file, dest_sec, dest_off); in add_jump_destinations()
532 if (!insn->jump_dest) { in add_jump_destinations()
539 if (!strcmp(insn->sec->name, ".altinstr_replacement")) in add_jump_destinations()
543 insn->sec, insn->offset, dest_sec->name, in add_jump_destinations()
562 if (insn->func && insn->jump_dest->func && in add_jump_destinations()
563 insn->func != insn->jump_dest->func && in add_jump_destinations()
564 !strstr(insn->func->name, ".cold.") && in add_jump_destinations()
565 strstr(insn->jump_dest->func->name, ".cold.")) { in add_jump_destinations()
566 insn->func->cfunc = insn->jump_dest->func; in add_jump_destinations()
567 insn->jump_dest->func->pfunc = insn->func; in add_jump_destinations()
579 struct instruction *insn; in add_call_destinations() local
583 for_each_insn(file, insn) { in add_call_destinations()
584 if (insn->type != INSN_CALL) in add_call_destinations()
587 rela = find_rela_by_dest_range(insn->sec, insn->offset, in add_call_destinations()
588 insn->len); in add_call_destinations()
590 dest_off = insn->offset + insn->len + insn->immediate; in add_call_destinations()
591 insn->call_dest = find_symbol_by_offset(insn->sec, in add_call_destinations()
594 if (!insn->call_dest && !insn->ignore) { in add_call_destinations()
596 insn->sec, insn->offset); in add_call_destinations()
603 insn->call_dest = find_symbol_by_offset(rela->sym->sec, in add_call_destinations()
605 if (!insn->call_dest || in add_call_destinations()
606 insn->call_dest->type != STT_FUNC) { in add_call_destinations()
608 insn->sec, insn->offset, in add_call_destinations()
614 insn->call_dest = rela->sym; in add_call_destinations()
645 struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump = NULL; in handle_group_alt() local
649 insn = orig_insn; in handle_group_alt()
650 sec_for_each_insn_from(file, insn) { in handle_group_alt()
651 if (insn->offset >= special_alt->orig_off + special_alt->orig_len) in handle_group_alt()
655 insn->type = INSN_NOP; in handle_group_alt()
657 insn->alt_group = true; in handle_group_alt()
658 last_orig_insn = insn; in handle_group_alt()
690 insn = *new_insn; in handle_group_alt()
691 sec_for_each_insn_from(file, insn) { in handle_group_alt()
692 if (insn->offset >= special_alt->new_off + special_alt->new_len) in handle_group_alt()
695 last_new_insn = insn; in handle_group_alt()
697 insn->ignore = orig_insn->ignore_alts; in handle_group_alt()
699 if (insn->type != INSN_JUMP_CONDITIONAL && in handle_group_alt()
700 insn->type != INSN_JUMP_UNCONDITIONAL) in handle_group_alt()
703 if (!insn->immediate) in handle_group_alt()
706 dest_off = insn->offset + insn->len + insn->immediate; in handle_group_alt()
713 insn->jump_dest = fake_jump; in handle_group_alt()
716 if (!insn->jump_dest) { in handle_group_alt()
718 insn->sec, insn->offset); in handle_group_alt()
819 alt->insn = new_insn; in add_special_section_alts()
830 static int add_switch_table(struct objtool_file *file, struct instruction *insn, in add_switch_table() argument
836 struct symbol *pfunc = insn->func->pfunc; in add_switch_table()
866 alt->insn = alt_insn; in add_switch_table()
867 list_add_tail(&alt->list, &insn->alts); in add_switch_table()
873 insn->sec, insn->offset); in add_switch_table()
925 struct instruction *insn) in find_switch_table() argument
928 struct instruction *orig_insn = insn; in find_switch_table()
937 &insn->list != &file->insn_list && in find_switch_table()
938 insn->sec == func->sec && in find_switch_table()
939 insn->offset >= func->offset; in find_switch_table()
941 insn = insn->first_jump_src ?: list_prev_entry(insn, list)) { in find_switch_table()
943 if (insn != orig_insn && insn->type == INSN_JUMP_DYNAMIC) in find_switch_table()
947 if (insn->type == INSN_JUMP_UNCONDITIONAL && in find_switch_table()
948 insn->jump_dest && in find_switch_table()
949 (insn->jump_dest->offset <= insn->offset || in find_switch_table()
950 insn->jump_dest->offset > orig_insn->offset)) in find_switch_table()
954 text_rela = find_rela_by_dest_range(insn->sec, insn->offset, in find_switch_table()
955 insn->len); in find_switch_table()
991 struct instruction *insn, *last = NULL, *prev_jump = NULL; in add_func_switch_tables() local
995 func_for_each_insn_all(file, func, insn) { in add_func_switch_tables()
997 last = insn; in add_func_switch_tables()
1004 if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest && in add_func_switch_tables()
1005 insn->offset > last->offset && in add_func_switch_tables()
1006 insn->jump_dest->offset > insn->offset && in add_func_switch_tables()
1007 !insn->jump_dest->first_jump_src) { in add_func_switch_tables()
1009 insn->jump_dest->first_jump_src = insn; in add_func_switch_tables()
1010 last = insn->jump_dest; in add_func_switch_tables()
1013 if (insn->type != INSN_JUMP_DYNAMIC) in add_func_switch_tables()
1016 rela = find_switch_table(file, func, insn); in add_func_switch_tables()
1031 prev_jump = insn; in add_func_switch_tables()
1077 struct instruction *insn; in read_unwind_hints() local
1107 insn = find_insn(file, rela->sym->sec, rela->addend); in read_unwind_hints()
1108 if (!insn) { in read_unwind_hints()
1113 cfa = &insn->state.cfa; in read_unwind_hints()
1116 insn->save = true; in read_unwind_hints()
1120 insn->restore = true; in read_unwind_hints()
1121 insn->hint = true; in read_unwind_hints()
1125 insn->hint = true; in read_unwind_hints()
1154 insn->sec, insn->offset, hint->sp_reg); in read_unwind_hints()
1159 insn->state.type = hint->type; in read_unwind_hints()
1160 insn->state.end = hint->end; in read_unwind_hints()
1169 struct instruction *insn; in read_retpoline_hints() local
1182 insn = find_insn(file, rela->sym->sec, rela->addend); in read_retpoline_hints()
1183 if (!insn) { in read_retpoline_hints()
1188 if (insn->type != INSN_JUMP_DYNAMIC && in read_retpoline_hints()
1189 insn->type != INSN_CALL_DYNAMIC) { in read_retpoline_hints()
1191 insn->sec, insn->offset); in read_retpoline_hints()
1195 insn->retpoline_safe = true; in read_retpoline_hints()
1246 static bool is_fentry_call(struct instruction *insn) in is_fentry_call() argument
1248 if (insn->type == INSN_CALL && in is_fentry_call()
1249 insn->call_dest->type == STT_NOTYPE && in is_fentry_call()
1250 !strcmp(insn->call_dest->name, "__fentry__")) in is_fentry_call()
1286 static int update_insn_state_regs(struct instruction *insn, struct insn_state *state) in update_insn_state_regs() argument
1289 struct stack_op *op = &insn->stack_op; in update_insn_state_regs()
1379 static int update_insn_state(struct instruction *insn, struct insn_state *state) in update_insn_state() argument
1381 struct stack_op *op = &insn->stack_op; in update_insn_state()
1387 if (insn->func) { in update_insn_state()
1388 WARN_FUNC("undefined stack state", insn->sec, insn->offset); in update_insn_state()
1395 return update_insn_state_regs(insn, state); in update_insn_state()
1526 insn->sec, insn->offset); in update_insn_state()
1537 insn->sec, insn->offset); in update_insn_state()
1613 insn->sec, insn->offset); in update_insn_state()
1655 if (!no_fp && insn->func && op->src.reg == CFI_BP && in update_insn_state()
1693 insn->sec, insn->offset); in update_insn_state()
1712 insn->sec, insn->offset); in update_insn_state()
1725 insn->sec, insn->offset); in update_insn_state()
1732 static bool insn_state_match(struct instruction *insn, struct insn_state *state) in insn_state_match() argument
1734 struct insn_state *state1 = &insn->state, *state2 = state; in insn_state_match()
1739 insn->sec, insn->offset, in insn_state_match()
1750 insn->sec, insn->offset, in insn_state_match()
1758 insn->sec, insn->offset, state1->type, state2->type); in insn_state_match()
1764 insn->sec, insn->offset, in insn_state_match()
1784 struct instruction *insn, *next_insn; in validate_branch() local
1789 insn = first; in validate_branch()
1790 sec = insn->sec; in validate_branch()
1792 if (insn->alt_group && list_empty(&insn->alts)) { in validate_branch()
1794 sec, insn->offset); in validate_branch()
1799 next_insn = next_insn_same_sec(file, insn); in validate_branch()
1801 if (file->c_file && func && insn->func && func != insn->func->pfunc) { in validate_branch()
1803 func->name, insn->func->name); in validate_branch()
1807 func = insn->func ? insn->func->pfunc : NULL; in validate_branch()
1809 if (func && insn->ignore) { in validate_branch()
1811 sec, insn->offset); in validate_branch()
1815 if (insn->visited) { in validate_branch()
1816 if (!insn->hint && !insn_state_match(insn, &state)) in validate_branch()
1822 if (insn->hint) { in validate_branch()
1823 if (insn->restore) { in validate_branch()
1826 i = insn; in validate_branch()
1828 func_for_each_insn_continue_reverse(file, insn->func, i) { in validate_branch()
1837 sec, insn->offset); in validate_branch()
1849 if (insn == first) in validate_branch()
1853 sec, insn->offset); in validate_branch()
1857 insn->state = save_insn->state; in validate_branch()
1860 state = insn->state; in validate_branch()
1863 insn->state = state; in validate_branch()
1865 insn->visited = true; in validate_branch()
1867 if (!insn->ignore_alts) { in validate_branch()
1868 list_for_each_entry(alt, &insn->alts, list) { in validate_branch()
1869 ret = validate_branch(file, alt->insn, state); in validate_branch()
1875 switch (insn->type) { in validate_branch()
1880 sec, insn->offset); in validate_branch()
1886 insn->func->name); in validate_branch()
1893 if (is_fentry_call(insn)) in validate_branch()
1896 ret = dead_end_function(file, insn->call_dest); in validate_branch()
1906 sec, insn->offset); in validate_branch()
1913 if (insn->jump_dest && in validate_branch()
1914 (!func || !insn->jump_dest->func || in validate_branch()
1915 insn->jump_dest->func->pfunc == func)) { in validate_branch()
1916 ret = validate_branch(file, insn->jump_dest, in validate_branch()
1923 sec, insn->offset); in validate_branch()
1927 if (insn->type == INSN_JUMP_UNCONDITIONAL) in validate_branch()
1933 if (func && list_empty(&insn->alts) && in validate_branch()
1936 sec, insn->offset); in validate_branch()
1945 sec, insn->offset); in validate_branch()
1951 if (update_insn_state(insn, &state)) in validate_branch()
1960 if (insn->dead_end) in validate_branch()
1970 insn = next_insn; in validate_branch()
1978 struct instruction *insn; in validate_unwind_hints() local
1987 for_each_insn(file, insn) { in validate_unwind_hints()
1988 if (insn->hint && !insn->visited) { in validate_unwind_hints()
1989 ret = validate_branch(file, insn, state); in validate_unwind_hints()
1999 struct instruction *insn; in validate_retpoline() local
2002 for_each_insn(file, insn) { in validate_retpoline()
2003 if (insn->type != INSN_JUMP_DYNAMIC && in validate_retpoline()
2004 insn->type != INSN_CALL_DYNAMIC) in validate_retpoline()
2007 if (insn->retpoline_safe) in validate_retpoline()
2016 if (!strcmp(insn->sec->name, ".init.text") && !module) in validate_retpoline()
2020 insn->sec, insn->offset, in validate_retpoline()
2021 insn->type == INSN_JUMP_DYNAMIC ? "jump" : "call"); in validate_retpoline()
2029 static bool is_kasan_insn(struct instruction *insn) in is_kasan_insn() argument
2031 return (insn->type == INSN_CALL && in is_kasan_insn()
2032 !strcmp(insn->call_dest->name, "__asan_handle_no_return")); in is_kasan_insn()
2035 static bool is_ubsan_insn(struct instruction *insn) in is_ubsan_insn() argument
2037 return (insn->type == INSN_CALL && in is_ubsan_insn()
2038 !strcmp(insn->call_dest->name, in is_ubsan_insn()
2042 static bool ignore_unreachable_insn(struct instruction *insn) in ignore_unreachable_insn() argument
2046 if (insn->ignore || insn->type == INSN_NOP) in ignore_unreachable_insn()
2056 if (!strcmp(insn->sec->name, ".fixup") || in ignore_unreachable_insn()
2057 !strcmp(insn->sec->name, ".altinstr_replacement") || in ignore_unreachable_insn()
2058 !strcmp(insn->sec->name, ".altinstr_aux")) in ignore_unreachable_insn()
2067 if (!insn->func) in ignore_unreachable_insn()
2071 if (is_kasan_insn(insn) || is_ubsan_insn(insn)) in ignore_unreachable_insn()
2074 if (insn->type == INSN_JUMP_UNCONDITIONAL) { in ignore_unreachable_insn()
2075 if (insn->jump_dest && in ignore_unreachable_insn()
2076 insn->jump_dest->func == insn->func) { in ignore_unreachable_insn()
2077 insn = insn->jump_dest; in ignore_unreachable_insn()
2084 if (insn->offset + insn->len >= insn->func->offset + insn->func->len) in ignore_unreachable_insn()
2087 insn = list_next_entry(insn, list); in ignore_unreachable_insn()
2097 struct instruction *insn; in validate_functions() local
2113 insn = find_insn(file, sec, func->offset); in validate_functions()
2114 if (!insn || insn->ignore) in validate_functions()
2117 ret = validate_branch(file, insn, state); in validate_functions()
2127 struct instruction *insn; in validate_reachable_instructions() local
2132 for_each_insn(file, insn) { in validate_reachable_instructions()
2133 if (insn->visited || ignore_unreachable_insn(insn)) in validate_reachable_instructions()
2136 WARN_FUNC("unreachable instruction", insn->sec, insn->offset); in validate_reachable_instructions()
2145 struct instruction *insn, *tmpinsn; in cleanup() local
2148 list_for_each_entry_safe(insn, tmpinsn, &file->insn_list, list) { in cleanup()
2149 list_for_each_entry_safe(alt, tmpalt, &insn->alts, list) { in cleanup()
2153 list_del(&insn->list); in cleanup()
2154 hash_del(&insn->hash); in cleanup()
2155 free(insn); in cleanup()