Lines Matching refs:file
37 struct instruction *find_insn(struct objtool_file *file,
42 hash_for_each_possible(file->insn_hash, insn, hash, sec_offset_hash(sec, offset)) {
50 struct instruction *next_insn_same_sec(struct objtool_file *file,
54 return find_insn(file, insn->sec, insn->offset + insn->len);
63 static struct instruction *next_insn_same_func(struct objtool_file *file,
66 struct instruction *next = next_insn_same_sec(file, insn);
80 return find_insn(file, func->cfunc->sec, func->cfunc->offset);
83 static struct instruction *prev_insn_same_sec(struct objtool_file *file,
88 return find_insn(file, insn->sec, insn->offset - insn->prev_len);
95 static struct instruction *prev_insn_same_sym(struct objtool_file *file,
98 struct instruction *prev = prev_insn_same_sec(file, insn);
106 #define for_each_insn(file, insn) \
109 for_each_sec(file, __sec) \
110 sec_for_each_insn(file, __sec, insn)
112 #define func_for_each_insn(file, func, insn) \
113 for (insn = find_insn(file, func->sec, func->offset); \
115 insn = next_insn_same_func(file, insn))
117 #define sym_for_each_insn(file, sym, insn) \
118 for (insn = find_insn(file, sym->sec, sym->offset); \
120 insn = next_insn_same_sec(file, insn))
122 #define sym_for_each_insn_continue_reverse(file, sym, insn) \
123 for (insn = prev_insn_same_sec(file, insn); \
125 insn = prev_insn_same_sec(file, insn))
127 #define sec_for_each_insn_from(file, insn) \
128 for (; insn; insn = next_insn_same_sec(file, insn))
130 #define sec_for_each_insn_continue(file, insn) \
131 for (insn = next_insn_same_sec(file, insn); insn; \
132 insn = next_insn_same_sec(file, insn))
242 * For global functions which are outside the scope of this object file, we
248 static bool __dead_end_function(struct objtool_file *file, struct symbol *func,
279 insn = find_insn(file, func->sec, func->offset);
283 func_for_each_insn(file, func, insn) {
298 func_for_each_insn(file, func, insn) {
303 /* sibling call to another file */
316 return __dead_end_function(file, insn_func(dest), recursion+1);
323 static bool dead_end_function(struct objtool_file *file, struct symbol *func)
325 return __dead_end_function(file, func, 0);
341 static void init_insn_state(struct objtool_file *file, struct insn_state *state,
427 static int decode_instructions(struct objtool_file *file)
435 for_each_sec(file, sec) {
482 ret = arch_decode_instruction(file, sec, offset,
498 hash_add(file->insn_hash, &insn->hash, sec_offset_hash(sec, insn->offset));
517 if (!find_insn(file, sec, func->offset)) {
522 sym_for_each_insn(file, func, insn) {
528 list_add_tail(&insn->call_node, &file->endbr_list);
529 file->nr_endbr++;
531 file->nr_endbr_int++;
547 static int add_pv_ops(struct objtool_file *file, const char *symname)
554 sym = find_symbol_by_name(file->elf, symname);
561 reloc = find_reloc_by_dest_range(file->elf, sym->sec, off, end - off);
577 if (objtool_pv_add(file, idx, func))
589 * Allocate and initialize file->pv_ops[].
591 static int init_pv_ops(struct objtool_file *file)
607 file->pv_ops = NULL;
609 sym = find_symbol_by_name(file->elf, "pv_ops");
614 file->pv_ops = calloc(sizeof(struct pv_state), nr);
615 if (!file->pv_ops) {
621 INIT_LIST_HEAD(&file->pv_ops[idx].targets);
624 ret = add_pv_ops(file, pv_ops);
632 static int create_static_call_sections(struct objtool_file *file)
641 sec = find_section_by_name(file->elf, ".static_call_sites");
643 INIT_LIST_HEAD(&file->static_call_list);
644 WARN("file already has .static_call_sites section, skipping");
648 if (list_empty(&file->static_call_list))
652 list_for_each_entry(insn, &file->static_call_list, call_node)
655 sec = elf_create_section_pair(file->elf, ".static_call_sites",
664 list_for_each_entry(insn, &file->static_call_list, call_node) {
667 if (!elf_init_reloc_text_sym(file->elf, sec,
686 key_sym = find_symbol_by_name(file->elf, tmp);
706 if (!elf_init_reloc_data_sym(file->elf, sec,
718 static int create_retpoline_sites_sections(struct objtool_file *file)
724 sec = find_section_by_name(file->elf, ".retpoline_sites");
726 WARN("file already has .retpoline_sites, skipping");
731 list_for_each_entry(insn, &file->retpoline_call_list, call_node)
737 sec = elf_create_section_pair(file->elf, ".retpoline_sites",
743 list_for_each_entry(insn, &file->retpoline_call_list, call_node) {
745 if (!elf_init_reloc_text_sym(file->elf, sec,
756 static int create_return_sites_sections(struct objtool_file *file)
762 sec = find_section_by_name(file->elf, ".return_sites");
764 WARN("file already has .return_sites, skipping");
769 list_for_each_entry(insn, &file->return_thunk_list, call_node)
775 sec = elf_create_section_pair(file->elf, ".return_sites",
781 list_for_each_entry(insn, &file->return_thunk_list, call_node) {
783 if (!elf_init_reloc_text_sym(file->elf, sec,
794 static int create_ibt_endbr_seal_sections(struct objtool_file *file)
800 sec = find_section_by_name(file->elf, ".ibt_endbr_seal");
802 WARN("file already has .ibt_endbr_seal, skipping");
807 list_for_each_entry(insn, &file->endbr_list, call_node)
811 printf("ibt: ENDBR at function start: %d\n", file->nr_endbr);
812 printf("ibt: ENDBR inside functions: %d\n", file->nr_endbr_int);
819 sec = elf_create_section_pair(file->elf, ".ibt_endbr_seal",
825 list_for_each_entry(insn, &file->endbr_list, call_node) {
840 if (!elf_init_reloc_text_sym(file->elf, sec,
851 static int create_cfi_sections(struct objtool_file *file)
857 sec = find_section_by_name(file->elf, ".cfi_sites");
859 INIT_LIST_HEAD(&file->call_list);
860 WARN("file already has .cfi_sites section, skipping");
865 for_each_sym(file, sym) {
875 sec = elf_create_section_pair(file->elf, ".cfi_sites",
881 for_each_sym(file, sym) {
888 if (!elf_init_reloc_text_sym(file->elf, sec,
899 static int create_mcount_loc_sections(struct objtool_file *file)
901 size_t addr_size = elf_addr_size(file->elf);
906 sec = find_section_by_name(file->elf, "__mcount_loc");
908 INIT_LIST_HEAD(&file->mcount_loc_list);
909 WARN("file already has __mcount_loc section, skipping");
913 if (list_empty(&file->mcount_loc_list))
917 list_for_each_entry(insn, &file->mcount_loc_list, call_node)
920 sec = elf_create_section_pair(file->elf, "__mcount_loc", addr_size,
928 list_for_each_entry(insn, &file->mcount_loc_list, call_node) {
932 reloc = elf_init_reloc_text_sym(file->elf, sec, idx * addr_size, idx,
937 set_reloc_type(file->elf, reloc, addr_size == 8 ? R_ABS64 : R_ABS32);
945 static int create_direct_call_sections(struct objtool_file *file)
951 sec = find_section_by_name(file->elf, ".call_sites");
953 INIT_LIST_HEAD(&file->call_list);
954 WARN("file already has .call_sites section, skipping");
958 if (list_empty(&file->call_list))
962 list_for_each_entry(insn, &file->call_list, call_node)
965 sec = elf_create_section_pair(file->elf, ".call_sites",
971 list_for_each_entry(insn, &file->call_list, call_node) {
973 if (!elf_init_reloc_text_sym(file->elf, sec,
987 static int add_ignores(struct objtool_file *file)
993 rsec = find_section_by_name(file->elf, ".rela.discard.func_stack_frame_non_standard");
1213 static void add_uaccess_safe(struct objtool_file *file)
1222 func = find_symbol_by_name(file->elf, *name);
1257 static struct reloc *insn_reloc(struct objtool_file *file, struct instruction *insn)
1264 if (!file)
1267 reloc = find_reloc_by_dest_range(file->elf, insn->sec,
1288 static int annotate_call_site(struct objtool_file *file,
1291 struct reloc *reloc = insn_reloc(file, insn);
1298 list_add_tail(&insn->call_node, &file->static_call_list);
1303 list_add_tail(&insn->call_node, &file->retpoline_call_list);
1314 set_reloc_type(file->elf, reloc, R_NONE);
1316 if (elf_write_insn(file->elf, insn->sec,
1343 set_reloc_type(file->elf, reloc, R_NONE);
1345 if (elf_write_insn(file->elf, insn->sec,
1354 list_add_tail(&insn->call_node, &file->mcount_loc_list);
1360 list_add_tail(&insn->call_node, &file->call_list);
1362 if (!sibling && dead_end_function(file, sym))
1368 static int add_call_dest(struct objtool_file *file, struct instruction *insn,
1384 return annotate_call_site(file, insn, sibling);
1387 static int add_retpoline_call(struct objtool_file *file, struct instruction *insn)
1418 return annotate_call_site(file, insn, false);
1421 static void add_return_call(struct objtool_file *file, struct instruction *insn, bool add)
1431 list_add_tail(&insn->call_node, &file->return_thunk_list);
1434 static bool is_first_func_insn(struct objtool_file *file,
1442 struct instruction *prev = prev_insn_same_sym(file, insn);
1456 static bool jump_is_sibling_call(struct objtool_file *file,
1467 if (!is_first_func_insn(file, to, ts))
1481 static int add_jump_destinations(struct objtool_file *file)
1489 for_each_insn(file, insn) {
1502 reloc = insn_reloc(file, insn);
1510 ret = add_retpoline_call(file, insn);
1515 add_return_call(file, insn, true);
1522 ret = add_call_dest(file, insn, reloc->sym, true);
1531 /* non-func asm code jumping to another file */
1535 jump_dest = find_insn(file, dest_sec, dest_off);
1548 add_return_call(file, insn, false);
1556 if (file->ignore_unreachables && func &&
1573 ret = add_retpoline_call(file, insn);
1579 add_return_call(file, insn, true);
1611 if (jump_is_sibling_call(file, insn, jump_dest)) {
1616 ret = add_call_dest(file, insn, insn_func(jump_dest), true);
1642 static int add_call_destinations(struct objtool_file *file)
1650 for_each_insn(file, insn) {
1655 reloc = insn_reloc(file, insn);
1660 ret = add_call_dest(file, insn, dest, false);
1686 ret = add_call_dest(file, insn, dest, false);
1691 ret = add_retpoline_call(file, insn);
1696 ret = add_call_dest(file, insn, reloc->sym, false);
1709 static int handle_group_alt(struct objtool_file *file,
1735 sec_for_each_insn_from(file, insn) {
1794 sec_for_each_insn_from(file, insn) {
1813 alt_reloc = insn_reloc(file, insn);
1829 insn->jump_dest = next_insn_same_sec(file, orig_alt_group->last_insn);
1858 static int handle_jump_alt(struct objtool_file *file,
1871 struct reloc *reloc = insn_reloc(file, orig_insn);
1874 set_reloc_type(file->elf, reloc, R_NONE);
1876 if (elf_write_insn(file->elf, orig_insn->sec,
1887 file->jl_nop_short++;
1889 file->jl_nop_long++;
1895 file->jl_short++;
1897 file->jl_long++;
1899 *new_insn = next_insn_same_sec(file, orig_insn);
1909 static int add_special_section_alts(struct objtool_file *file)
1917 if (special_get_alts(file->elf, &special_alts))
1922 orig_insn = find_insn(file, special_alt->orig_sec,
1932 new_insn = find_insn(file, special_alt->new_sec,
1947 ret = handle_group_alt(file, special_alt, orig_insn,
1953 ret = handle_jump_alt(file, special_alt, orig_insn,
1975 printf("short:\t%ld\t%ld\n", file->jl_nop_short, file->jl_short);
1976 printf("long:\t%ld\t%ld\n", file->jl_nop_long, file->jl_long);
1987 static int add_jump_table(struct objtool_file *file, struct instruction *insn)
2028 dest_insn = find_insn(file, reloc->sym->sec, sym_offset);
2061 static void find_jump_table(struct objtool_file *file, struct symbol *func,
2076 insn = insn->first_jump_src ?: prev_insn_same_sym(file, insn)) {
2088 table_reloc = arch_find_switch_table(file, insn, &table_size);
2094 dest_insn = find_insn(file, table_reloc->sym->sec, sym_offset);
2110 static void mark_func_jump_tables(struct objtool_file *file,
2115 func_for_each_insn(file, func, insn) {
2136 find_jump_table(file, func, insn);
2140 static int add_func_jump_tables(struct objtool_file *file,
2146 func_for_each_insn(file, func, insn) {
2150 ret = add_jump_table(file, insn);
2163 static int add_jump_table_alts(struct objtool_file *file)
2168 if (!file->rodata)
2171 for_each_sym(file, func) {
2175 mark_func_jump_tables(file, func);
2176 ret = add_func_jump_tables(file, func);
2193 static int read_unwind_hints(struct objtool_file *file)
2203 sec = find_section_by_name(file->elf, ".discard.unwind_hints");
2217 file->hints = true;
2222 reloc = find_reloc_by_dest(file->elf, sec, i * sizeof(*hint));
2237 insn = find_insn(file, reloc->sym->sec, offset);
2285 cfi.cfa.offset = bswap_if_needed(file->elf, hint->sp_offset);
2295 static int read_annotate(struct objtool_file *file,
2296 int (*func)(struct objtool_file *file, int type, struct instruction *insn))
2304 sec = find_section_by_name(file->elf, ".discard.annotate_insn");
2322 type = bswap_if_needed(file->elf, type);
2325 insn = find_insn(file, reloc->sym->sec, offset);
2332 ret = func(file, type, insn);
2340 static int __annotate_early(struct objtool_file *file, int type, struct instruction *insn)
2363 static int __annotate_ifc(struct objtool_file *file, int type, struct instruction *insn)
2383 insn->jump_dest = find_insn(file, insn->sec, dest_off);
2393 static int __annotate_late(struct objtool_file *file, int type, struct instruction *insn)
2469 static int classify_symbols(struct objtool_file *file)
2473 for_each_sym(file, func) {
2503 static void mark_rodata(struct objtool_file *file)
2518 for_each_sec(file, sec) {
2527 file->rodata = found;
2530 static int decode_sections(struct objtool_file *file)
2534 mark_rodata(file);
2536 ret = init_pv_ops(file);
2543 ret = classify_symbols(file);
2547 ret = decode_instructions(file);
2551 ret = add_ignores(file);
2555 add_uaccess_safe(file);
2557 ret = read_annotate(file, __annotate_early);
2566 ret = add_special_section_alts(file);
2571 ret = add_jump_destinations(file);
2579 ret = read_annotate(file, __annotate_ifc);
2583 ret = add_call_destinations(file);
2587 ret = add_jump_table_alts(file);
2591 ret = read_unwind_hints(file);
2599 ret = read_annotate(file, __annotate_late);
3195 static int propagate_alt_cfi(struct objtool_file *file, struct instruction *insn)
3345 static bool pv_call_dest(struct objtool_file *file, struct instruction *insn)
3351 reloc = insn_reloc(file, insn);
3357 if (file->pv_ops[idx].clean)
3360 file->pv_ops[idx].clean = true;
3362 list_for_each_entry(target, &file->pv_ops[idx].targets, pv_target) {
3365 file->pv_ops[idx].clean = false;
3369 return file->pv_ops[idx].clean;
3372 static inline bool noinstr_call_dest(struct objtool_file *file,
3381 if (file->pv_ops)
3382 return pv_call_dest(file, insn);
3410 static int validate_call(struct objtool_file *file,
3415 !noinstr_call_dest(file, insn, insn_call_dest(insn))) {
3433 static int validate_sibling_call(struct objtool_file *file,
3442 return validate_call(file, insn, state);
3480 static struct instruction *next_insn_to_validate(struct objtool_file *file,
3507 return next_insn_same_sec(file, insn);
3510 return next_insn_same_sec(file, alt_group->orig_group->last_insn);
3527 * requested not to do that to avoid hurting .s file readability
3547 static int validate_branch(struct objtool_file *file, struct symbol *func,
3562 next_insn = next_insn_to_validate(file, insn);
3570 if (file->ignore_unreachables)
3601 sym_for_each_insn_continue_reverse(file, func, i) {
3648 if (propagate_alt_cfi(file, insn))
3653 ret = validate_branch(file, func, alt->insn, state);
3674 ret = validate_call(file, insn, &state);
3689 ret = validate_sibling_call(file, insn, &state);
3694 ret = validate_branch(file, func,
3710 ret = validate_sibling_call(file, insn, &state);
3793 if (file->ignore_unreachables)
3809 static int validate_unwind_hint(struct objtool_file *file,
3814 int ret = validate_branch(file, insn_func(insn), insn, *state);
3823 static int validate_unwind_hints(struct objtool_file *file, struct section *sec)
3829 if (!file->hints)
3832 init_insn_state(file, &state, sec);
3835 sec_for_each_insn(file, sec, insn)
3836 warnings += validate_unwind_hint(file, insn, &state);
3838 for_each_insn(file, insn)
3839 warnings += validate_unwind_hint(file, insn, &state);
3851 static int validate_unret(struct objtool_file *file, struct instruction *insn)
3857 next = next_insn_to_validate(file, insn);
3867 ret = validate_unret(file, alt->insn);
3890 ret = validate_unret(file, insn->jump_dest);
3905 dest = find_insn(file, insn_call_dest(insn)->sec,
3913 ret = validate_unret(file, dest);
3960 static int validate_unrets(struct objtool_file *file)
3965 for_each_insn(file, insn) {
3969 warnings += validate_unret(file, insn);
3975 static int validate_retpoline(struct objtool_file *file)
3980 for_each_insn(file, insn) {
4021 static bool ignore_unreachable_insn(struct objtool_file *file, struct instruction *insn)
4056 sec_for_each_insn_continue(file, insn) {
4093 prev_insn = prev_insn_same_sec(file, insn);
4124 insn = next_insn_same_sec(file, insn);
4130 static int add_prefix_symbol(struct objtool_file *file, struct symbol *func)
4135 insn = find_insn(file, func->sec, func->offset);
4139 for (prev = prev_insn_same_sec(file, insn);
4141 prev = prev_insn_same_sec(file, prev)) {
4155 elf_create_prefix_symbol(file->elf, func, opts.prefix);
4172 for (; prev != insn; prev = next_insn_same_sec(file, prev))
4178 static int add_prefix_symbols(struct objtool_file *file)
4183 for_each_sec(file, sec) {
4191 add_prefix_symbol(file, func);
4198 static int validate_symbol(struct objtool_file *file, struct section *sec,
4212 insn = find_insn(file, sec, sym->offset);
4219 ret = validate_branch(file, insn_func(insn), insn, *state);
4225 static int validate_section(struct objtool_file *file, struct section *sec)
4235 init_insn_state(file, &state, sec);
4238 warnings += validate_symbol(file, sec, func, &state);
4244 static int validate_noinstr_sections(struct objtool_file *file)
4249 sec = find_section_by_name(file->elf, ".noinstr.text");
4251 warnings += validate_section(file, sec);
4252 warnings += validate_unwind_hints(file, sec);
4255 sec = find_section_by_name(file->elf, ".entry.text");
4257 warnings += validate_section(file, sec);
4258 warnings += validate_unwind_hints(file, sec);
4261 sec = find_section_by_name(file->elf, ".cpuidle.text");
4263 warnings += validate_section(file, sec);
4264 warnings += validate_unwind_hints(file, sec);
4270 static int validate_functions(struct objtool_file *file)
4275 for_each_sec(file, sec) {
4279 warnings += validate_section(file, sec);
4291 static bool noendbr_range(struct objtool_file *file, struct instruction *insn)
4299 first = find_insn(file, sym->sec, sym->offset);
4309 static int __validate_ibt_insn(struct objtool_file *file, struct instruction *insn,
4347 if (noendbr_range(file, dest))
4354 static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn)
4378 if (!insn_reloc(file, insn)) {
4383 dest = find_insn(file, insn->sec, off);
4389 return __validate_ibt_insn(file, insn, dest);
4397 for (reloc = insn_reloc(file, insn);
4399 reloc = find_reloc_by_dest_range(file->elf, insn->sec,
4410 dest = find_insn(file, reloc->sym->sec, off);
4414 warnings += __validate_ibt_insn(file, insn, dest);
4420 static int validate_ibt_data_reloc(struct objtool_file *file,
4425 dest = find_insn(file, reloc->sym->sec,
4449 static int validate_ibt(struct objtool_file *file)
4456 for_each_insn(file, insn)
4457 warnings += validate_ibt_insn(file, insn);
4459 for_each_sec(file, sec) {
4496 warnings += validate_ibt_data_reloc(file, reloc);
4502 static int validate_sls(struct objtool_file *file)
4507 for_each_insn(file, insn) {
4508 next_insn = next_insn_same_sec(file, insn);
4535 static int validate_reachable_instructions(struct objtool_file *file)
4541 if (file->ignore_unreachables)
4544 for_each_insn(file, insn) {
4545 if (insn->visited || ignore_unreachable_insn(file, insn))
4548 prev_insn = prev_insn_same_sec(file, insn);
4616 static void disas_warned_funcs(struct objtool_file *file)
4621 for_each_sym(file, sym) {
4653 * Reduce peak RSS usage by freeing insns memory before writing the ELF file,
4657 static void free_insns(struct objtool_file *file)
4662 for_each_insn(file, insn) {
4675 int check(struct objtool_file *file)
4686 if (!cfi_hash_alloc(1UL << (file->elf->symbol_bits - 3))) {
4694 ret = decode_sections(file);
4702 warnings += validate_retpoline(file);
4707 w += validate_functions(file);
4708 w += validate_unwind_hints(file, NULL);
4710 w += validate_reachable_instructions(file);
4715 warnings += validate_noinstr_sections(file);
4723 warnings += validate_unrets(file);
4727 warnings += validate_ibt(file);
4730 warnings += validate_sls(file);
4733 ret = create_static_call_sections(file);
4739 ret = create_retpoline_sites_sections(file);
4745 ret = create_cfi_sections(file);
4751 ret = create_return_sites_sections(file);
4756 ret = create_direct_call_sections(file);
4763 ret = create_mcount_loc_sections(file);
4769 ret = add_prefix_symbols(file);
4775 ret = create_ibt_endbr_seal_sections(file);
4781 ret = orc_create(file);
4786 free_insns(file);
4806 disas_warned_funcs(file);