Lines Matching refs:file
36 struct instruction *find_insn(struct objtool_file *file, in find_insn() argument
41 hash_for_each_possible(file->insn_hash, insn, hash, sec_offset_hash(sec, offset)) { in find_insn()
49 static struct instruction *next_insn_same_sec(struct objtool_file *file, in next_insn_same_sec() argument
54 if (!next || &next->list == &file->insn_list || next->sec != insn->sec) in next_insn_same_sec()
60 static struct instruction *next_insn_same_func(struct objtool_file *file, in next_insn_same_func() argument
69 if (&next->list != &file->insn_list && next->func == func) in next_insn_same_func()
77 return find_insn(file, func->cfunc->sec, func->cfunc->offset); in next_insn_same_func()
80 static struct instruction *prev_insn_same_sym(struct objtool_file *file, in prev_insn_same_sym() argument
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); \
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 && \
103 #define sym_for_each_insn_continue_reverse(file, sym, insn) \ argument
105 &insn->list != &file->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))
155 static bool __dead_end_function(struct objtool_file *file, struct symbol *func, in __dead_end_function() argument
198 insn = find_insn(file, func->sec, func->offset); in __dead_end_function()
202 func_for_each_insn(file, func, insn) { in __dead_end_function()
217 func_for_each_insn(file, func, insn) { in __dead_end_function()
235 return __dead_end_function(file, dest->func, recursion+1); in __dead_end_function()
242 static bool dead_end_function(struct objtool_file *file, struct symbol *func) in dead_end_function() argument
244 return __dead_end_function(file, func, 0); in dead_end_function()
350 static int decode_instructions(struct objtool_file *file) in decode_instructions() argument
358 for_each_sec(file, sec) { in decode_instructions()
385 ret = arch_decode_instruction(file, sec, offset, in decode_instructions()
393 hash_add(file->insn_hash, &insn->hash, sec_offset_hash(sec, insn->offset)); in decode_instructions()
394 list_add_tail(&insn->list, &file->insn_list); in decode_instructions()
402 if (!find_insn(file, sec, func->offset)) { in decode_instructions()
408 sym_for_each_insn(file, func, insn) in decode_instructions()
426 static int add_pv_ops(struct objtool_file *file, const char *symname) in add_pv_ops() argument
433 sym = find_symbol_by_name(file->elf, symname); in add_pv_ops()
440 rel = find_reloc_by_dest_range(file->elf, sym->sec, off, end - off); in add_pv_ops()
450 objtool_pv_add(file, idx, func); in add_pv_ops()
463 static int init_pv_ops(struct objtool_file *file) in init_pv_ops() argument
479 file->pv_ops = NULL; in init_pv_ops()
481 sym = find_symbol_by_name(file->elf, "pv_ops"); in init_pv_ops()
486 file->pv_ops = calloc(sizeof(struct pv_state), nr); in init_pv_ops()
487 if (!file->pv_ops) in init_pv_ops()
491 INIT_LIST_HEAD(&file->pv_ops[idx].targets); in init_pv_ops()
494 add_pv_ops(file, pv_ops); in init_pv_ops()
499 static struct instruction *find_last_insn(struct objtool_file *file, in find_last_insn() argument
507 insn = find_insn(file, sec, offset); in find_last_insn()
515 static int add_dead_ends(struct objtool_file *file) in add_dead_ends() argument
525 for_each_insn(file, insn) in add_dead_ends()
532 sec = find_section_by_name(file->elf, ".rela.discard.unreachable"); in add_dead_ends()
541 insn = find_insn(file, reloc->sym->sec, reloc->addend); in add_dead_ends()
545 insn = find_last_insn(file, reloc->sym->sec); in add_dead_ends()
567 sec = find_section_by_name(file->elf, ".rela.discard.reachable"); in add_dead_ends()
576 insn = find_insn(file, reloc->sym->sec, reloc->addend); in add_dead_ends()
580 insn = find_last_insn(file, reloc->sym->sec); in add_dead_ends()
598 static int create_static_call_sections(struct objtool_file *file) in create_static_call_sections() argument
607 sec = find_section_by_name(file->elf, ".static_call_sites"); in create_static_call_sections()
609 INIT_LIST_HEAD(&file->static_call_list); in create_static_call_sections()
614 if (list_empty(&file->static_call_list)) in create_static_call_sections()
618 list_for_each_entry(insn, &file->static_call_list, call_node) in create_static_call_sections()
621 sec = elf_create_section(file->elf, ".static_call_sites", SHF_WRITE, in create_static_call_sections()
627 list_for_each_entry(insn, &file->static_call_list, call_node) { in create_static_call_sections()
633 if (elf_add_reloc_to_insn(file->elf, sec, in create_static_call_sections()
653 key_sym = find_symbol_by_name(file->elf, tmp); in create_static_call_sections()
674 if (elf_add_reloc(file->elf, sec, in create_static_call_sections()
686 static int create_retpoline_sites_sections(struct objtool_file *file) in create_retpoline_sites_sections() argument
692 sec = find_section_by_name(file->elf, ".retpoline_sites"); in create_retpoline_sites_sections()
699 list_for_each_entry(insn, &file->retpoline_call_list, call_node) in create_retpoline_sites_sections()
705 sec = elf_create_section(file->elf, ".retpoline_sites", 0, in create_retpoline_sites_sections()
713 list_for_each_entry(insn, &file->retpoline_call_list, call_node) { in create_retpoline_sites_sections()
718 if (elf_add_reloc_to_insn(file->elf, sec, in create_retpoline_sites_sections()
732 static int create_mcount_loc_sections(struct objtool_file *file) in create_mcount_loc_sections() argument
739 sec = find_section_by_name(file->elf, "__mcount_loc"); in create_mcount_loc_sections()
741 INIT_LIST_HEAD(&file->mcount_loc_list); in create_mcount_loc_sections()
746 if (list_empty(&file->mcount_loc_list)) in create_mcount_loc_sections()
750 list_for_each_entry(insn, &file->mcount_loc_list, call_node) in create_mcount_loc_sections()
753 sec = elf_create_section(file->elf, "__mcount_loc", 0, sizeof(unsigned long), idx); in create_mcount_loc_sections()
758 list_for_each_entry(insn, &file->mcount_loc_list, call_node) { in create_mcount_loc_sections()
763 if (elf_add_reloc_to_insn(file->elf, sec, in create_mcount_loc_sections()
778 static void add_ignores(struct objtool_file *file) in add_ignores() argument
785 sec = find_section_by_name(file->elf, ".rela.discard.func_stack_frame_non_standard"); in add_ignores()
806 func_for_each_insn(file, func, insn) in add_ignores()
954 static void add_uaccess_safe(struct objtool_file *file) in add_uaccess_safe() argument
963 func = find_symbol_by_name(file->elf, *name); in add_uaccess_safe()
977 static int add_ignore_alternatives(struct objtool_file *file) in add_ignore_alternatives() argument
983 sec = find_section_by_name(file->elf, ".rela.discard.ignore_alts"); in add_ignore_alternatives()
993 insn = find_insn(file, reloc->sym->sec, reloc->addend); in add_ignore_alternatives()
1012 static struct reloc *insn_reloc(struct objtool_file *file, struct instruction *insn) in insn_reloc() argument
1018 if (!file) in insn_reloc()
1021 insn->reloc = find_reloc_by_dest_range(file->elf, insn->sec, in insn_reloc()
1042 static void annotate_call_site(struct objtool_file *file, in annotate_call_site() argument
1045 struct reloc *reloc = insn_reloc(file, insn); in annotate_call_site()
1061 list_add_tail(&insn->call_node, &file->static_call_list); in annotate_call_site()
1066 list_add_tail(&insn->call_node, &file->retpoline_call_list); in annotate_call_site()
1078 elf_write_reloc(file->elf, reloc); in annotate_call_site()
1081 elf_write_insn(file->elf, insn->sec, in annotate_call_site()
1096 elf_write_reloc(file->elf, reloc); in annotate_call_site()
1099 elf_write_insn(file->elf, insn->sec, in annotate_call_site()
1105 list_add_tail(&insn->call_node, &file->mcount_loc_list); in annotate_call_site()
1110 static void add_call_dest(struct objtool_file *file, struct instruction *insn, in add_call_dest() argument
1126 annotate_call_site(file, insn, sibling); in add_call_dest()
1129 static void add_retpoline_call(struct objtool_file *file, struct instruction *insn) in add_retpoline_call() argument
1160 annotate_call_site(file, insn, false); in add_retpoline_call()
1165 static int add_jump_destinations(struct objtool_file *file) in add_jump_destinations() argument
1172 for_each_insn(file, insn) { in add_jump_destinations()
1176 reloc = insn_reloc(file, insn); in add_jump_destinations()
1184 add_retpoline_call(file, insn); in add_jump_destinations()
1188 add_call_dest(file, insn, reloc->sym, true); in add_jump_destinations()
1199 insn->jump_dest = find_insn(file, dest_sec, dest_off); in add_jump_destinations()
1245 add_call_dest(file, insn, insn->jump_dest->func, true); in add_jump_destinations()
1267 static int add_call_destinations(struct objtool_file *file) in add_call_destinations() argument
1274 for_each_insn(file, insn) { in add_call_destinations()
1278 reloc = insn_reloc(file, insn); in add_call_destinations()
1283 add_call_dest(file, insn, dest, false); in add_call_destinations()
1310 add_call_dest(file, insn, dest, false); in add_call_destinations()
1313 add_retpoline_call(file, insn); in add_call_destinations()
1316 add_call_dest(file, insn, reloc->sym, false); in add_call_destinations()
1326 static int handle_group_alt(struct objtool_file *file, in handle_group_alt() argument
1350 sec_for_each_insn_from(file, insn) { in handle_group_alt()
1400 sec_for_each_insn_from(file, insn) { in handle_group_alt()
1420 alt_reloc = insn_reloc(file, insn); in handle_group_alt()
1437 insn->jump_dest = next_insn_same_sec(file, last_orig_insn); in handle_group_alt()
1467 static int handle_jump_alt(struct objtool_file *file, in handle_jump_alt() argument
1481 struct reloc *reloc = insn_reloc(file, orig_insn); in handle_jump_alt()
1485 elf_write_reloc(file->elf, reloc); in handle_jump_alt()
1487 elf_write_insn(file->elf, orig_insn->sec, in handle_jump_alt()
1495 file->jl_nop_short++; in handle_jump_alt()
1497 file->jl_nop_long++; in handle_jump_alt()
1503 file->jl_short++; in handle_jump_alt()
1505 file->jl_long++; in handle_jump_alt()
1517 static int add_special_section_alts(struct objtool_file *file) in add_special_section_alts() argument
1525 ret = special_get_alts(file->elf, &special_alts); in add_special_section_alts()
1531 orig_insn = find_insn(file, special_alt->orig_sec, in add_special_section_alts()
1542 new_insn = find_insn(file, special_alt->new_sec, in add_special_section_alts()
1560 ret = handle_group_alt(file, special_alt, orig_insn, in add_special_section_alts()
1565 ret = handle_jump_alt(file, special_alt, orig_insn, in add_special_section_alts()
1589 printf("short:\t%ld\t%ld\n", file->jl_nop_short, file->jl_short); in add_special_section_alts()
1590 printf("long:\t%ld\t%ld\n", file->jl_nop_long, file->jl_long); in add_special_section_alts()
1597 static int add_jump_table(struct objtool_file *file, struct instruction *insn, in add_jump_table() argument
1625 dest_insn = find_insn(file, reloc->sym->sec, reloc->addend); in add_jump_table()
1657 static struct reloc *find_jump_table(struct objtool_file *file, in find_jump_table() argument
1671 insn = insn->first_jump_src ?: prev_insn_same_sym(file, insn)) { in find_jump_table()
1683 table_reloc = arch_find_switch_table(file, insn); in find_jump_table()
1686 dest_insn = find_insn(file, table_reloc->sym->sec, table_reloc->addend); in find_jump_table()
1700 static void mark_func_jump_tables(struct objtool_file *file, in mark_func_jump_tables() argument
1706 func_for_each_insn(file, func, insn) { in mark_func_jump_tables()
1727 reloc = find_jump_table(file, func, insn); in mark_func_jump_tables()
1735 static int add_func_jump_tables(struct objtool_file *file, in add_func_jump_tables() argument
1741 func_for_each_insn(file, func, insn) { in add_func_jump_tables()
1745 ret = add_jump_table(file, insn, insn->jump_table); in add_func_jump_tables()
1758 static int add_jump_table_alts(struct objtool_file *file) in add_jump_table_alts() argument
1764 if (!file->rodata) in add_jump_table_alts()
1767 for_each_sec(file, sec) { in add_jump_table_alts()
1772 mark_func_jump_tables(file, func); in add_jump_table_alts()
1773 ret = add_func_jump_tables(file, func); in add_jump_table_alts()
1790 static int read_unwind_hints(struct objtool_file *file) in read_unwind_hints() argument
1799 sec = find_section_by_name(file->elf, ".discard.unwind_hints"); in read_unwind_hints()
1814 file->hints = true; in read_unwind_hints()
1819 reloc = find_reloc_by_dest(file->elf, sec, i * sizeof(*hint)); in read_unwind_hints()
1825 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_unwind_hints()
1857 static int read_retpoline_hints(struct objtool_file *file) in read_retpoline_hints() argument
1863 sec = find_section_by_name(file->elf, ".rela.discard.retpoline_safe"); in read_retpoline_hints()
1873 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_retpoline_hints()
1892 static int read_instr_hints(struct objtool_file *file) in read_instr_hints() argument
1898 sec = find_section_by_name(file->elf, ".rela.discard.instr_end"); in read_instr_hints()
1908 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_instr_hints()
1917 sec = find_section_by_name(file->elf, ".rela.discard.instr_begin"); in read_instr_hints()
1927 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_instr_hints()
1939 static int read_intra_function_calls(struct objtool_file *file) in read_intra_function_calls() argument
1945 sec = find_section_by_name(file->elf, ".rela.discard.intra_function_calls"); in read_intra_function_calls()
1958 insn = find_insn(file, reloc->sym->sec, reloc->addend); in read_intra_function_calls()
1978 insn->jump_dest = find_insn(file, insn->sec, dest_off); in read_intra_function_calls()
1990 static int classify_symbols(struct objtool_file *file) in classify_symbols() argument
1995 for_each_sec(file, sec) { in classify_symbols()
2018 static void mark_rodata(struct objtool_file *file) in mark_rodata() argument
2033 for_each_sec(file, sec) { in mark_rodata()
2041 file->rodata = found; in mark_rodata()
2044 static int decode_sections(struct objtool_file *file) in decode_sections() argument
2048 mark_rodata(file); in decode_sections()
2050 ret = init_pv_ops(file); in decode_sections()
2054 ret = decode_instructions(file); in decode_sections()
2058 ret = add_dead_ends(file); in decode_sections()
2062 add_ignores(file); in decode_sections()
2063 add_uaccess_safe(file); in decode_sections()
2065 ret = add_ignore_alternatives(file); in decode_sections()
2072 ret = classify_symbols(file); in decode_sections()
2080 ret = add_jump_destinations(file); in decode_sections()
2084 ret = add_special_section_alts(file); in decode_sections()
2092 ret = read_intra_function_calls(file); in decode_sections()
2096 ret = add_call_destinations(file); in decode_sections()
2100 ret = add_jump_table_alts(file); in decode_sections()
2104 ret = read_unwind_hints(file); in decode_sections()
2108 ret = read_retpoline_hints(file); in decode_sections()
2112 ret = read_instr_hints(file); in decode_sections()
2698 static int propagate_alt_cfi(struct objtool_file *file, struct instruction *insn) in propagate_alt_cfi() argument
2843 static bool pv_call_dest(struct objtool_file *file, struct instruction *insn) in pv_call_dest() argument
2849 rel = insn_reloc(file, insn); in pv_call_dest()
2855 if (file->pv_ops[idx].clean) in pv_call_dest()
2858 file->pv_ops[idx].clean = true; in pv_call_dest()
2860 list_for_each_entry(target, &file->pv_ops[idx].targets, pv_target) { in pv_call_dest()
2863 file->pv_ops[idx].clean = false; in pv_call_dest()
2867 return file->pv_ops[idx].clean; in pv_call_dest()
2870 static inline bool noinstr_call_dest(struct objtool_file *file, in noinstr_call_dest() argument
2879 if (file->pv_ops) in noinstr_call_dest()
2880 return pv_call_dest(file, insn); in noinstr_call_dest()
2902 static int validate_call(struct objtool_file *file, in validate_call() argument
2907 !noinstr_call_dest(file, insn, insn->call_dest)) { in validate_call()
2928 static int validate_sibling_call(struct objtool_file *file, in validate_sibling_call() argument
2938 return validate_call(file, insn, state); in validate_sibling_call()
2982 static struct instruction *next_insn_to_validate(struct objtool_file *file, in next_insn_to_validate() argument
2993 return next_insn_same_sec(file, alt_group->orig_group->last_insn); in next_insn_to_validate()
2995 return next_insn_same_sec(file, insn); in next_insn_to_validate()
3004 static int validate_branch(struct objtool_file *file, struct symbol *func, in validate_branch() argument
3016 next_insn = next_insn_to_validate(file, insn); in validate_branch()
3018 if (file->c_file && func && insn->func && func != insn->func->pfunc) { in validate_branch()
3059 if (propagate_alt_cfi(file, insn)) in validate_branch()
3069 ret = validate_branch(file, func, alt->insn, state); in validate_branch()
3091 ret = validate_call(file, insn, &state); in validate_branch()
3102 if (dead_end_function(file, insn->call_dest)) in validate_branch()
3110 ret = validate_sibling_call(file, insn, &state); in validate_branch()
3115 ret = validate_branch(file, func, in validate_branch()
3132 ret = validate_sibling_call(file, insn, &state); in validate_branch()
3212 static int validate_unwind_hints(struct objtool_file *file, struct section *sec) in validate_unwind_hints() argument
3218 if (!file->hints) in validate_unwind_hints()
3224 insn = find_insn(file, sec, 0); in validate_unwind_hints()
3228 insn = list_first_entry(&file->insn_list, typeof(*insn), list); in validate_unwind_hints()
3231 while (&insn->list != &file->insn_list && (!sec || insn->sec == sec)) { in validate_unwind_hints()
3233 ret = validate_branch(file, insn->func, insn, state); in validate_unwind_hints()
3245 static int validate_retpoline(struct objtool_file *file) in validate_retpoline() argument
3250 for_each_insn(file, insn) { in validate_retpoline()
3290 static bool ignore_unreachable_insn(struct objtool_file *file, struct instruction *insn) in ignore_unreachable_insn() argument
3325 if ((prev_insn->dead_end || dead_end_function(file, prev_insn->call_dest)) && in ignore_unreachable_insn()
3361 static int validate_symbol(struct objtool_file *file, struct section *sec, in validate_symbol() argument
3375 insn = find_insn(file, sec, sym->offset); in validate_symbol()
3381 ret = validate_branch(file, insn->func, insn, *state); in validate_symbol()
3387 static int validate_section(struct objtool_file *file, struct section *sec) in validate_section() argument
3400 warnings += validate_symbol(file, sec, func, &state); in validate_section()
3406 static int validate_vmlinux_functions(struct objtool_file *file) in validate_vmlinux_functions() argument
3411 sec = find_section_by_name(file->elf, ".noinstr.text"); in validate_vmlinux_functions()
3413 warnings += validate_section(file, sec); in validate_vmlinux_functions()
3414 warnings += validate_unwind_hints(file, sec); in validate_vmlinux_functions()
3417 sec = find_section_by_name(file->elf, ".entry.text"); in validate_vmlinux_functions()
3419 warnings += validate_section(file, sec); in validate_vmlinux_functions()
3420 warnings += validate_unwind_hints(file, sec); in validate_vmlinux_functions()
3426 static int validate_functions(struct objtool_file *file) in validate_functions() argument
3431 for_each_sec(file, sec) { in validate_functions()
3435 warnings += validate_section(file, sec); in validate_functions()
3441 static int validate_reachable_instructions(struct objtool_file *file) in validate_reachable_instructions() argument
3445 if (file->ignore_unreachables) in validate_reachable_instructions()
3448 for_each_insn(file, insn) { in validate_reachable_instructions()
3449 if (insn->visited || ignore_unreachable_insn(file, insn)) in validate_reachable_instructions()
3459 int check(struct objtool_file *file) in check() argument
3468 if (!cfi_hash_alloc(1UL << (file->elf->symbol_bits - 3))) in check()
3474 ret = decode_sections(file); in check()
3480 if (list_empty(&file->insn_list)) in check()
3484 ret = validate_vmlinux_functions(file); in check()
3493 ret = validate_retpoline(file); in check()
3499 ret = validate_functions(file); in check()
3504 ret = validate_unwind_hints(file, NULL); in check()
3510 ret = validate_reachable_instructions(file); in check()
3516 ret = create_static_call_sections(file); in check()
3522 ret = create_retpoline_sites_sections(file); in check()
3529 ret = create_mcount_loc_sections(file); in check()