Lines Matching refs:file

38 struct instruction *find_insn(struct objtool_file *file,
43 hash_for_each_possible(file->insn_hash, insn, hash, sec_offset_hash(sec, offset)) {
51 struct instruction *next_insn_same_sec(struct objtool_file *file,
55 return find_insn(file, insn->sec, insn->offset + insn->len);
64 static struct instruction *next_insn_same_func(struct objtool_file *file,
67 struct instruction *next = next_insn_same_sec(file, insn);
81 return find_insn(file, func->cfunc->sec, func->cfunc->offset);
84 static struct instruction *prev_insn_same_sec(struct objtool_file *file,
89 return find_insn(file, insn->sec, insn->offset - insn->prev_len);
96 static struct instruction *prev_insn_same_sym(struct objtool_file *file,
99 struct instruction *prev = prev_insn_same_sec(file, insn);
107 #define for_each_insn(file, insn) \
110 for_each_sec(file, __sec) \
111 sec_for_each_insn(file, __sec, insn)
113 #define func_for_each_insn(file, func, insn) \
114 for (insn = find_insn(file, func->sec, func->offset); \
116 insn = next_insn_same_func(file, insn))
118 #define sym_for_each_insn(file, sym, insn) \
119 for (insn = find_insn(file, sym->sec, sym->offset); \
121 insn = next_insn_same_sec(file, insn))
123 #define sym_for_each_insn_continue_reverse(file, sym, insn) \
124 for (insn = prev_insn_same_sec(file, insn); \
126 insn = prev_insn_same_sec(file, insn))
128 #define sec_for_each_insn_from(file, insn) \
129 for (; insn; insn = next_insn_same_sec(file, insn))
131 #define sec_for_each_insn_continue(file, insn) \
132 for (insn = next_insn_same_sec(file, insn); insn; \
133 insn = next_insn_same_sec(file, insn))
183 * For global functions which are outside the scope of this object file, we
189 static bool __dead_end_function(struct objtool_file *file, struct symbol *func,
216 insn = find_insn(file, func->sec, func->offset);
220 func_for_each_insn(file, func, insn) {
235 func_for_each_insn(file, func, insn) {
240 /* sibling call to another file */
253 return __dead_end_function(file, insn_func(dest), recursion+1);
260 static bool dead_end_function(struct objtool_file *file, struct symbol *func)
262 return __dead_end_function(file, func, 0);
278 static void init_insn_state(struct objtool_file *file, struct insn_state *state,
369 static int decode_instructions(struct objtool_file *file)
377 for_each_sec(file, sec) {
424 ret = arch_decode_instruction(file, sec, offset,
440 hash_add(file->insn_hash, &insn->hash, sec_offset_hash(sec, insn->offset));
462 if (!find_insn(file, sec, func->offset)) {
468 sym_for_each_insn(file, func, insn) {
474 list_add_tail(&insn->call_node, &file->endbr_list);
475 file->nr_endbr++;
477 file->nr_endbr_int++;
493 static int add_pv_ops(struct objtool_file *file, const char *symname)
500 sym = find_symbol_by_name(file->elf, symname);
507 reloc = find_reloc_by_dest_range(file->elf, sym->sec, off, end - off);
518 objtool_pv_add(file, idx, func);
529 * Allocate and initialize file->pv_ops[].
531 static int init_pv_ops(struct objtool_file *file)
547 file->pv_ops = NULL;
549 sym = find_symbol_by_name(file->elf, "pv_ops");
554 file->pv_ops = calloc(sizeof(struct pv_state), nr);
555 if (!file->pv_ops)
559 INIT_LIST_HEAD(&file->pv_ops[idx].targets);
562 add_pv_ops(file, pv_ops);
567 static struct instruction *find_last_insn(struct objtool_file *file,
575 insn = find_insn(file, sec, offset);
583 static int add_dead_ends(struct objtool_file *file)
593 rsec = find_section_by_name(file->elf, ".rela.discard.unreachable");
607 insn = find_insn(file, reloc->sym->sec, offset);
609 insn = prev_insn_same_sec(file, insn);
611 insn = find_last_insn(file, reloc->sym->sec);
633 rsec = find_section_by_name(file->elf, ".rela.discard.reachable");
647 insn = find_insn(file, reloc->sym->sec, offset);
649 insn = prev_insn_same_sec(file, insn);
651 insn = find_last_insn(file, reloc->sym->sec);
669 static int create_static_call_sections(struct objtool_file *file)
678 sec = find_section_by_name(file->elf, ".static_call_sites");
680 INIT_LIST_HEAD(&file->static_call_list);
681 WARN("file already has .static_call_sites section, skipping");
685 if (list_empty(&file->static_call_list))
689 list_for_each_entry(insn, &file->static_call_list, call_node)
692 sec = elf_create_section_pair(file->elf, ".static_call_sites",
701 list_for_each_entry(insn, &file->static_call_list, call_node) {
704 if (!elf_init_reloc_text_sym(file->elf, sec,
724 key_sym = find_symbol_by_name(file->elf, tmp);
746 if (!elf_init_reloc_data_sym(file->elf, sec,
758 static int create_retpoline_sites_sections(struct objtool_file *file)
764 sec = find_section_by_name(file->elf, ".retpoline_sites");
766 WARN("file already has .retpoline_sites, skipping");
771 list_for_each_entry(insn, &file->retpoline_call_list, call_node)
777 sec = elf_create_section_pair(file->elf, ".retpoline_sites",
783 list_for_each_entry(insn, &file->retpoline_call_list, call_node) {
785 if (!elf_init_reloc_text_sym(file->elf, sec,
796 static int create_return_sites_sections(struct objtool_file *file)
802 sec = find_section_by_name(file->elf, ".return_sites");
804 WARN("file already has .return_sites, skipping");
809 list_for_each_entry(insn, &file->return_thunk_list, call_node)
815 sec = elf_create_section_pair(file->elf, ".return_sites",
821 list_for_each_entry(insn, &file->return_thunk_list, call_node) {
823 if (!elf_init_reloc_text_sym(file->elf, sec,
834 static int create_ibt_endbr_seal_sections(struct objtool_file *file)
840 sec = find_section_by_name(file->elf, ".ibt_endbr_seal");
842 WARN("file already has .ibt_endbr_seal, skipping");
847 list_for_each_entry(insn, &file->endbr_list, call_node)
851 printf("ibt: ENDBR at function start: %d\n", file->nr_endbr);
852 printf("ibt: ENDBR inside functions: %d\n", file->nr_endbr_int);
859 sec = elf_create_section_pair(file->elf, ".ibt_endbr_seal",
865 list_for_each_entry(insn, &file->endbr_list, call_node) {
877 if (!elf_init_reloc_text_sym(file->elf, sec,
888 static int create_cfi_sections(struct objtool_file *file)
894 sec = find_section_by_name(file->elf, ".cfi_sites");
896 INIT_LIST_HEAD(&file->call_list);
897 WARN("file already has .cfi_sites section, skipping");
902 for_each_sym(file, sym) {
912 sec = elf_create_section_pair(file->elf, ".cfi_sites",
918 for_each_sym(file, sym) {
925 if (!elf_init_reloc_text_sym(file->elf, sec,
936 static int create_mcount_loc_sections(struct objtool_file *file)
938 size_t addr_size = elf_addr_size(file->elf);
943 sec = find_section_by_name(file->elf, "__mcount_loc");
945 INIT_LIST_HEAD(&file->mcount_loc_list);
946 WARN("file already has __mcount_loc section, skipping");
950 if (list_empty(&file->mcount_loc_list))
954 list_for_each_entry(insn, &file->mcount_loc_list, call_node)
957 sec = elf_create_section_pair(file->elf, "__mcount_loc", addr_size,
965 list_for_each_entry(insn, &file->mcount_loc_list, call_node) {
969 reloc = elf_init_reloc_text_sym(file->elf, sec, idx * addr_size, idx,
974 set_reloc_type(file->elf, reloc, addr_size == 8 ? R_ABS64 : R_ABS32);
982 static int create_direct_call_sections(struct objtool_file *file)
988 sec = find_section_by_name(file->elf, ".call_sites");
990 INIT_LIST_HEAD(&file->call_list);
991 WARN("file already has .call_sites section, skipping");
995 if (list_empty(&file->call_list))
999 list_for_each_entry(insn, &file->call_list, call_node)
1002 sec = elf_create_section_pair(file->elf, ".call_sites",
1008 list_for_each_entry(insn, &file->call_list, call_node) {
1010 if (!elf_init_reloc_text_sym(file->elf, sec,
1024 static void add_ignores(struct objtool_file *file)
1031 rsec = find_section_by_name(file->elf, ".rela.discard.func_stack_frame_non_standard");
1053 func_for_each_insn(file, func, insn)
1243 static void add_uaccess_safe(struct objtool_file *file)
1252 func = find_symbol_by_name(file->elf, *name);
1266 static int add_ignore_alternatives(struct objtool_file *file)
1272 rsec = find_section_by_name(file->elf, ".rela.discard.ignore_alts");
1282 insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
1321 static struct reloc *insn_reloc(struct objtool_file *file, struct instruction *insn)
1328 if (!file)
1331 reloc = find_reloc_by_dest_range(file->elf, insn->sec,
1352 static void annotate_call_site(struct objtool_file *file,
1355 struct reloc *reloc = insn_reloc(file, insn);
1371 list_add_tail(&insn->call_node, &file->static_call_list);
1376 list_add_tail(&insn->call_node, &file->retpoline_call_list);
1387 set_reloc_type(file->elf, reloc, R_NONE);
1389 elf_write_insn(file->elf, insn->sec,
1414 set_reloc_type(file->elf, reloc, R_NONE);
1416 elf_write_insn(file->elf, insn->sec,
1423 list_add_tail(&insn->call_node, &file->mcount_loc_list);
1428 list_add_tail(&insn->call_node, &file->call_list);
1430 if (!sibling && dead_end_function(file, sym))
1434 static void add_call_dest(struct objtool_file *file, struct instruction *insn,
1450 annotate_call_site(file, insn, sibling);
1453 static void add_retpoline_call(struct objtool_file *file, struct instruction *insn)
1484 annotate_call_site(file, insn, false);
1487 static void add_return_call(struct objtool_file *file, struct instruction *insn, bool add)
1497 list_add_tail(&insn->call_node, &file->return_thunk_list);
1500 static bool is_first_func_insn(struct objtool_file *file,
1508 struct instruction *prev = prev_insn_same_sym(file, insn);
1522 static bool jump_is_sibling_call(struct objtool_file *file,
1533 if (!is_first_func_insn(file, to, ts))
1547 static int add_jump_destinations(struct objtool_file *file)
1554 for_each_insn(file, insn) {
1565 reloc = insn_reloc(file, insn);
1573 add_retpoline_call(file, insn);
1576 add_return_call(file, insn, true);
1583 add_call_dest(file, insn, reloc->sym, true);
1590 /* non-func asm code jumping to another file */
1594 jump_dest = find_insn(file, dest_sec, dest_off);
1607 add_return_call(file, insn, false);
1623 add_retpoline_call(file, insn);
1627 add_return_call(file, insn, true);
1660 if (jump_is_sibling_call(file, insn, jump_dest)) {
1665 add_call_dest(file, insn, insn_func(jump_dest), true);
1689 static int add_call_destinations(struct objtool_file *file)
1696 for_each_insn(file, insn) {
1700 reloc = insn_reloc(file, insn);
1705 add_call_dest(file, insn, dest, false);
1729 add_call_dest(file, insn, dest, false);
1732 add_retpoline_call(file, insn);
1735 add_call_dest(file, insn, reloc->sym, false);
1745 static int handle_group_alt(struct objtool_file *file,
1771 sec_for_each_insn_from(file, insn) {
1830 sec_for_each_insn_from(file, insn) {
1850 alt_reloc = insn_reloc(file, insn);
1866 insn->jump_dest = next_insn_same_sec(file, orig_alt_group->last_insn);
1894 static int handle_jump_alt(struct objtool_file *file,
1907 struct reloc *reloc = insn_reloc(file, orig_insn);
1910 set_reloc_type(file->elf, reloc, R_NONE);
1911 elf_write_insn(file->elf, orig_insn->sec,
1919 file->jl_nop_short++;
1921 file->jl_nop_long++;
1927 file->jl_short++;
1929 file->jl_long++;
1931 *new_insn = next_insn_same_sec(file, orig_insn);
1941 static int add_special_section_alts(struct objtool_file *file)
1949 ret = special_get_alts(file->elf, &special_alts);
1955 orig_insn = find_insn(file, special_alt->orig_sec,
1966 new_insn = find_insn(file, special_alt->new_sec,
1983 ret = handle_group_alt(file, special_alt, orig_insn,
1988 ret = handle_jump_alt(file, special_alt, orig_insn,
2013 printf("short:\t%ld\t%ld\n", file->jl_nop_short, file->jl_short);
2014 printf("long:\t%ld\t%ld\n", file->jl_nop_long, file->jl_long);
2021 static int add_jump_table(struct objtool_file *file, struct instruction *insn,
2050 dest_insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
2082 static struct reloc *find_jump_table(struct objtool_file *file,
2096 insn = insn->first_jump_src ?: prev_insn_same_sym(file, insn)) {
2108 table_reloc = arch_find_switch_table(file, insn);
2111 dest_insn = find_insn(file, table_reloc->sym->sec, reloc_addend(table_reloc));
2125 static void mark_func_jump_tables(struct objtool_file *file,
2131 func_for_each_insn(file, func, insn) {
2152 reloc = find_jump_table(file, func, insn);
2158 static int add_func_jump_tables(struct objtool_file *file,
2164 func_for_each_insn(file, func, insn) {
2175 ret = add_jump_table(file, insn_t1, insn_jump_table(insn_t2));
2183 ret = add_jump_table(file, insn_t1, NULL);
2193 static int add_jump_table_alts(struct objtool_file *file)
2198 if (!file->rodata)
2201 for_each_sym(file, func) {
2205 mark_func_jump_tables(file, func);
2206 ret = add_func_jump_tables(file, func);
2223 static int read_unwind_hints(struct objtool_file *file)
2233 sec = find_section_by_name(file->elf, ".discard.unwind_hints");
2247 file->hints = true;
2252 reloc = find_reloc_by_dest(file->elf, sec, i * sizeof(*hint));
2267 insn = find_insn(file, reloc->sym->sec, offset);
2314 cfi.cfa.offset = bswap_if_needed(file->elf, hint->sp_offset);
2324 static int read_noendbr_hints(struct objtool_file *file)
2330 rsec = find_section_by_name(file->elf, ".rela.discard.noendbr");
2335 insn = find_insn(file, reloc->sym->sec,
2348 static int read_retpoline_hints(struct objtool_file *file)
2354 rsec = find_section_by_name(file->elf, ".rela.discard.retpoline_safe");
2364 insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
2384 static int read_instr_hints(struct objtool_file *file)
2390 rsec = find_section_by_name(file->elf, ".rela.discard.instr_end");
2400 insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
2409 rsec = find_section_by_name(file->elf, ".rela.discard.instr_begin");
2419 insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
2431 static int read_validate_unret_hints(struct objtool_file *file)
2437 rsec = find_section_by_name(file->elf, ".rela.discard.validate_unret");
2447 insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
2459 static int read_intra_function_calls(struct objtool_file *file)
2465 rsec = find_section_by_name(file->elf, ".rela.discard.intra_function_calls");
2478 insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
2497 insn->jump_dest = find_insn(file, insn->sec, dest_off);
2533 static int classify_symbols(struct objtool_file *file)
2537 for_each_sym(file, func) {
2567 static void mark_rodata(struct objtool_file *file)
2582 for_each_sec(file, sec) {
2590 file->rodata = found;
2593 static int decode_sections(struct objtool_file *file)
2597 mark_rodata(file);
2599 ret = init_pv_ops(file);
2606 ret = classify_symbols(file);
2610 ret = decode_instructions(file);
2614 add_ignores(file);
2615 add_uaccess_safe(file);
2617 ret = add_ignore_alternatives(file);
2624 ret = read_noendbr_hints(file);
2633 ret = add_special_section_alts(file);
2638 ret = add_jump_destinations(file);
2646 ret = read_intra_function_calls(file);
2650 ret = add_call_destinations(file);
2658 ret = add_dead_ends(file);
2662 ret = add_jump_table_alts(file);
2666 ret = read_unwind_hints(file);
2670 ret = read_retpoline_hints(file);
2674 ret = read_instr_hints(file);
2678 ret = read_validate_unret_hints(file);
3257 static int propagate_alt_cfi(struct objtool_file *file, struct instruction *insn)
3401 static bool pv_call_dest(struct objtool_file *file, struct instruction *insn)
3407 reloc = insn_reloc(file, insn);
3413 if (file->pv_ops[idx].clean)
3416 file->pv_ops[idx].clean = true;
3418 list_for_each_entry(target, &file->pv_ops[idx].targets, pv_target) {
3421 file->pv_ops[idx].clean = false;
3425 return file->pv_ops[idx].clean;
3428 static inline bool noinstr_call_dest(struct objtool_file *file,
3437 if (file->pv_ops)
3438 return pv_call_dest(file, insn);
3466 static int validate_call(struct objtool_file *file,
3471 !noinstr_call_dest(file, insn, insn_call_dest(insn))) {
3489 static int validate_sibling_call(struct objtool_file *file,
3498 return validate_call(file, insn, state);
3536 static struct instruction *next_insn_to_validate(struct objtool_file *file,
3563 return next_insn_same_sec(file, insn);
3566 return next_insn_same_sec(file, alt_group->orig_group->last_insn);
3575 static int validate_branch(struct objtool_file *file, struct symbol *func,
3587 next_insn = next_insn_to_validate(file, insn);
3626 sym_for_each_insn_continue_reverse(file, func, i) {
3673 if (propagate_alt_cfi(file, insn))
3683 ret = validate_branch(file, func, alt->insn, state);
3704 ret = validate_call(file, insn, &state);
3722 ret = validate_sibling_call(file, insn, &state);
3727 ret = validate_branch(file, func,
3743 ret = validate_sibling_call(file, insn, &state);
3822 static int validate_unwind_hint(struct objtool_file *file,
3827 int ret = validate_branch(file, insn_func(insn), insn, *state);
3836 static int validate_unwind_hints(struct objtool_file *file, struct section *sec)
3842 if (!file->hints)
3845 init_insn_state(file, &state, sec);
3848 sec_for_each_insn(file, sec, insn)
3849 warnings += validate_unwind_hint(file, insn, &state);
3851 for_each_insn(file, insn)
3852 warnings += validate_unwind_hint(file, insn, &state);
3864 static int validate_unret(struct objtool_file *file, struct instruction *insn)
3870 next = next_insn_to_validate(file, insn);
3885 ret = validate_unret(file, alt->insn);
3911 ret = validate_unret(file, insn->jump_dest);
3926 dest = find_insn(file, insn_call_dest(insn)->sec,
3934 ret = validate_unret(file, dest);
3972 static int validate_unrets(struct objtool_file *file)
3977 for_each_insn(file, insn) {
3981 ret = validate_unret(file, insn);
3992 static int validate_retpoline(struct objtool_file *file)
3997 for_each_insn(file, insn) {
4038 static bool ignore_unreachable_insn(struct objtool_file *file, struct instruction *insn)
4072 sec_for_each_insn_continue(file, insn) {
4089 func_for_each_insn(file, insn_func(dest), dest)
4111 prev_insn = prev_insn_same_sec(file, insn);
4142 insn = next_insn_same_sec(file, insn);
4148 static int add_prefix_symbol(struct objtool_file *file, struct symbol *func)
4153 insn = find_insn(file, func->sec, func->offset);
4157 for (prev = prev_insn_same_sec(file, insn);
4159 prev = prev_insn_same_sec(file, prev)) {
4173 elf_create_prefix_symbol(file->elf, func, opts.prefix);
4190 for (; prev != insn; prev = next_insn_same_sec(file, prev))
4196 static int add_prefix_symbols(struct objtool_file *file)
4201 for_each_sec(file, sec) {
4209 add_prefix_symbol(file, func);
4216 static int validate_symbol(struct objtool_file *file, struct section *sec,
4230 insn = find_insn(file, sec, sym->offset);
4236 ret = validate_branch(file, insn_func(insn), insn, *state);
4242 static int validate_section(struct objtool_file *file, struct section *sec)
4252 init_insn_state(file, &state, sec);
4255 warnings += validate_symbol(file, sec, func, &state);
4261 static int validate_noinstr_sections(struct objtool_file *file)
4266 sec = find_section_by_name(file->elf, ".noinstr.text");
4268 warnings += validate_section(file, sec);
4269 warnings += validate_unwind_hints(file, sec);
4272 sec = find_section_by_name(file->elf, ".entry.text");
4274 warnings += validate_section(file, sec);
4275 warnings += validate_unwind_hints(file, sec);
4278 sec = find_section_by_name(file->elf, ".cpuidle.text");
4280 warnings += validate_section(file, sec);
4281 warnings += validate_unwind_hints(file, sec);
4287 static int validate_functions(struct objtool_file *file)
4292 for_each_sec(file, sec) {
4296 warnings += validate_section(file, sec);
4308 static bool noendbr_range(struct objtool_file *file, struct instruction *insn)
4316 first = find_insn(file, sym->sec, sym->offset);
4326 static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn)
4351 for (reloc = insn_reloc(file, insn);
4353 reloc = find_reloc_by_dest_range(file->elf, insn->sec,
4371 dest = find_insn(file, reloc->sym->sec, off);
4410 if (noendbr_range(file, dest))
4421 static int validate_ibt_data_reloc(struct objtool_file *file,
4426 dest = find_insn(file, reloc->sym->sec,
4451 static int validate_ibt(struct objtool_file *file)
4458 for_each_insn(file, insn)
4459 warnings += validate_ibt_insn(file, insn);
4461 for_each_sec(file, sec) {
4495 warnings += validate_ibt_data_reloc(file, reloc);
4501 static int validate_sls(struct objtool_file *file)
4506 for_each_insn(file, insn) {
4507 next_insn = next_insn_same_sec(file, insn);
4549 * - read the .config file
4563 static int validate_reachable_instructions(struct objtool_file *file)
4569 if (file->ignore_unreachables)
4572 for_each_insn(file, insn) {
4573 if (insn->visited || ignore_unreachable_insn(file, insn))
4576 prev_insn = prev_insn_same_sec(file, insn);
4644 static int disas_warned_funcs(struct objtool_file *file)
4649 for_each_sym(file, sym) {
4675 * Reduce peak RSS usage by freeing insns memory before writing the ELF file,
4679 static void free_insns(struct objtool_file *file)
4684 for_each_insn(file, insn) {
4697 int check(struct objtool_file *file)
4708 if (!cfi_hash_alloc(1UL << (file->elf->symbol_bits - 3)))
4714 ret = decode_sections(file);
4724 ret = validate_retpoline(file);
4731 ret = validate_functions(file);
4736 ret = validate_unwind_hints(file, NULL);
4742 ret = validate_reachable_instructions(file);
4749 ret = validate_noinstr_sections(file);
4760 ret = validate_unrets(file);
4767 ret = validate_ibt(file);
4774 ret = validate_sls(file);
4781 ret = create_static_call_sections(file);
4788 ret = create_retpoline_sites_sections(file);
4795 ret = create_cfi_sections(file);
4802 ret = create_return_sites_sections(file);
4808 ret = create_direct_call_sections(file);
4816 ret = create_mcount_loc_sections(file);
4823 ret = add_prefix_symbols(file);
4830 ret = create_ibt_endbr_seal_sections(file);
4837 ret = orc_create(file);
4843 free_insns(file);
4846 disas_warned_funcs(file);