Lines Matching refs:insn
26 struct instruction *insn;
40 struct instruction *insn;
42 hash_for_each_possible(file->insn_hash, insn, hash, sec_offset_hash(sec, offset)) {
43 if (insn->sec == sec && insn->offset == offset)
44 return insn;
51 struct instruction *insn)
53 if (insn->idx == INSN_CHUNK_MAX)
54 return find_insn(file, insn->sec, insn->offset + insn->len);
56 insn++;
57 if (!insn->len)
60 return insn;
64 struct instruction *insn)
66 struct instruction *next = next_insn_same_sec(file, insn);
67 struct symbol *func = insn_func(insn);
84 struct instruction *insn)
86 if (insn->idx == 0) {
87 if (insn->prev_len)
88 return find_insn(file, insn->sec, insn->offset - insn->prev_len);
92 return insn - 1;
96 struct instruction *insn)
98 struct instruction *prev = prev_insn_same_sec(file, insn);
100 if (prev && insn_func(prev) == insn_func(insn))
106 #define for_each_insn(file, insn) \
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); \
114 insn; \
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); \
119 insn && insn->offset < sym->offset + sym->len; \
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); \
124 insn && insn->offset >= sym->offset; \
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))
134 static inline struct symbol *insn_call_dest(struct instruction *insn)
136 if (insn->type == INSN_JUMP_DYNAMIC ||
137 insn->type == INSN_CALL_DYNAMIC)
140 return insn->_call_dest;
143 static inline struct reloc *insn_jump_table(struct instruction *insn)
145 if (insn->type == INSN_JUMP_DYNAMIC ||
146 insn->type == INSN_CALL_DYNAMIC)
147 return insn->_jump_table;
152 static bool is_jump_table_jump(struct instruction *insn)
154 struct alt_group *alt_group = insn->alt_group;
156 if (insn_jump_table(insn))
164 static bool is_sibling_call(struct instruction *insn)
169 if (insn_func(insn)) {
171 if (insn->type == INSN_JUMP_DYNAMIC)
172 return !is_jump_table_jump(insn);
175 /* add_jump_destinations() sets insn_call_dest(insn) for sibling calls. */
176 return (is_static_jump(insn) && insn_call_dest(insn));
192 struct instruction *insn;
215 insn = find_insn(file, func->sec, func->offset);
216 if (!insn || !insn_func(insn))
219 func_for_each_insn(file, func, insn) {
222 if (insn->type == INSN_RETURN)
234 func_for_each_insn(file, func, insn) {
235 if (is_sibling_call(insn)) {
236 struct instruction *dest = insn->jump_dest;
285 * not correctly determine insn_call_dest(insn)->sec (external symbols
373 struct instruction *insn;
404 for (offset = 0; offset < sec->sh.sh_size; offset += insn->len) {
406 insns = calloc(sizeof(*insn), INSN_CHUNK_SIZE);
415 insn = &insns[idx];
416 insn->idx = idx;
418 INIT_LIST_HEAD(&insn->call_node);
419 insn->sec = sec;
420 insn->offset = offset;
421 insn->prev_len = prev_len;
425 insn);
429 prev_len = insn->len;
436 if (insn->type == INSN_BUG)
437 insn->dead_end = true;
439 hash_add(file->insn_hash, &insn->hash, sec_offset_hash(sec, insn->offset));
467 sym_for_each_insn(file, func, insn) {
468 insn->sym = func;
470 insn->type == INSN_ENDBR &&
471 list_empty(&insn->call_node)) {
472 if (insn->offset == func->offset) {
473 list_add_tail(&insn->call_node, &file->endbr_list);
569 struct instruction *insn = NULL;
573 for (offset = sec->sh.sh_size - 1; offset >= end && !insn; offset--)
574 insn = find_insn(file, sec, offset);
576 return insn;
586 struct instruction *insn;
605 insn = find_insn(file, reloc->sym->sec, addend);
606 if (insn)
607 insn = prev_insn_same_sec(file, insn);
609 insn = find_last_insn(file, reloc->sym->sec);
610 if (!insn) {
611 WARN("can't find unreachable insn at %s+0x%" PRIx64,
616 WARN("can't find unreachable insn at %s+0x%" PRIx64,
621 insn->dead_end = true;
644 insn = find_insn(file, reloc->sym->sec, addend);
645 if (insn)
646 insn = prev_insn_same_sec(file, insn);
648 insn = find_last_insn(file, reloc->sym->sec);
649 if (!insn) {
650 WARN("can't find reachable insn at %s+0x%" PRIx64,
655 WARN("can't find reachable insn at %s+0x%" PRIx64,
660 insn->dead_end = false;
670 struct instruction *insn;
686 list_for_each_entry(insn, &file->static_call_list, call_node)
698 list_for_each_entry(insn, &file->static_call_list, call_node) {
703 insn->sec, insn->offset))
707 key_name = strdup(insn_call_dest(insn)->name);
738 key_sym = insn_call_dest(insn);
746 is_sibling_call(insn) * STATIC_CALL_SITE_TAIL))
757 struct instruction *insn;
768 list_for_each_entry(insn, &file->retpoline_call_list, call_node)
780 list_for_each_entry(insn, &file->retpoline_call_list, call_node) {
784 insn->sec, insn->offset))
795 struct instruction *insn;
806 list_for_each_entry(insn, &file->return_thunk_list, call_node)
818 list_for_each_entry(insn, &file->return_thunk_list, call_node) {
822 insn->sec, insn->offset))
833 struct instruction *insn;
844 list_for_each_entry(insn, &file->endbr_list, call_node)
862 list_for_each_entry(insn, &file->endbr_list, call_node) {
865 struct symbol *sym = insn->sym;
869 insn->offset == sym->offset &&
876 insn->sec, insn->offset))
936 struct instruction *insn;
951 list_for_each_entry(insn, &file->mcount_loc_list, call_node)
962 list_for_each_entry(insn, &file->mcount_loc_list, call_node) {
967 insn->sec, insn->offset);
981 struct instruction *insn;
996 list_for_each_entry(insn, &file->call_list, call_node)
1005 list_for_each_entry(insn, &file->call_list, call_node) {
1009 insn->sec, insn->offset))
1023 struct instruction *insn;
1050 func_for_each_insn(file, func, insn)
1051 insn->ignore = true;
1267 struct instruction *insn;
1279 insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
1280 if (!insn) {
1285 insn->ignore_alts = true;
1318 static struct reloc *insn_reloc(struct objtool_file *file, struct instruction *insn)
1322 if (insn->no_reloc)
1328 reloc = find_reloc_by_dest_range(file->elf, insn->sec,
1329 insn->offset, insn->len);
1331 insn->no_reloc = 1;
1338 static void remove_insn_ops(struct instruction *insn)
1342 for (op = insn->stack_ops; op; op = next) {
1346 insn->stack_ops = NULL;
1350 struct instruction *insn, bool sibling)
1352 struct reloc *reloc = insn_reloc(file, insn);
1353 struct symbol *sym = insn_call_dest(insn);
1364 if (!strcmp(insn->sec->name, ".altinstr_replacement"))
1368 list_add_tail(&insn->call_node, &file->static_call_list);
1373 list_add_tail(&insn->call_node, &file->retpoline_call_list);
1382 if (opts.hack_noinstr && insn->sec->noinstr && sym->profiling_func) {
1386 elf_write_insn(file->elf, insn->sec,
1387 insn->offset, insn->len,
1388 sibling ? arch_ret_insn(insn->len)
1389 : arch_nop_insn(insn->len));
1391 insn->type = sibling ? INSN_RETURN : INSN_NOP;
1395 * We've replaced the tail-call JMP insn by two new
1396 * insn: RET; INT3, except we only have a single struct
1397 * insn here. Mark it retpoline_safe to avoid the SLS
1398 * warning, instead of adding another insn.
1400 insn->retpoline_safe = true;
1408 WARN_INSN(insn, "tail call to __fentry__ !?!?");
1413 elf_write_insn(file->elf, insn->sec,
1414 insn->offset, insn->len,
1415 arch_nop_insn(insn->len));
1417 insn->type = INSN_NOP;
1420 list_add_tail(&insn->call_node, &file->mcount_loc_list);
1424 if (insn->type == INSN_CALL && !insn->sec->init)
1425 list_add_tail(&insn->call_node, &file->call_list);
1428 insn->dead_end = true;
1431 static void add_call_dest(struct objtool_file *file, struct instruction *insn,
1434 insn->_call_dest = dest;
1445 remove_insn_ops(insn);
1447 annotate_call_site(file, insn, sibling);
1450 static void add_retpoline_call(struct objtool_file *file, struct instruction *insn)
1456 switch (insn->type) {
1458 insn->type = INSN_CALL_DYNAMIC;
1461 insn->type = INSN_JUMP_DYNAMIC;
1464 insn->type = INSN_JUMP_DYNAMIC_CONDITIONAL;
1470 insn->retpoline_safe = true;
1479 remove_insn_ops(insn);
1481 annotate_call_site(file, insn, false);
1484 static void add_return_call(struct objtool_file *file, struct instruction *insn, bool add)
1490 insn->type = INSN_RETURN;
1491 insn->retpoline_safe = true;
1494 list_add_tail(&insn->call_node, &file->return_thunk_list);
1498 struct instruction *insn, struct symbol *sym)
1500 if (insn->offset == sym->offset)
1505 struct instruction *prev = prev_insn_same_sym(file, insn);
1508 insn->offset == sym->offset + prev->len)
1546 struct instruction *insn, *jump_dest;
1551 for_each_insn(file, insn) {
1552 if (insn->jump_dest) {
1559 if (!is_static_jump(insn))
1562 reloc = insn_reloc(file, insn);
1564 dest_sec = insn->sec;
1565 dest_off = arch_jump_destination(insn);
1570 add_retpoline_call(file, insn);
1573 add_return_call(file, insn, true);
1575 } else if (insn_func(insn)) {
1580 add_call_dest(file, insn, reloc->sym, true);
1604 add_return_call(file, insn, false);
1608 WARN_INSN(insn, "can't find jump dest instruction at %s+0x%lx",
1616 if (insn_func(insn) && insn_func(jump_dest) &&
1617 insn_func(insn) != insn_func(jump_dest)) {
1634 if (!strstr(insn_func(insn)->name, ".cold") &&
1636 insn_func(insn)->cfunc = insn_func(jump_dest);
1637 insn_func(jump_dest)->pfunc = insn_func(insn);
1641 if (jump_is_sibling_call(file, insn, jump_dest)) {
1646 add_call_dest(file, insn, insn_func(jump_dest), true);
1650 insn->jump_dest = jump_dest;
1672 struct instruction *insn;
1677 for_each_insn(file, insn) {
1678 if (insn->type != INSN_CALL)
1681 reloc = insn_reloc(file, insn);
1683 dest_off = arch_jump_destination(insn);
1684 dest = find_call_destination(insn->sec, dest_off);
1686 add_call_dest(file, insn, dest, false);
1688 if (insn->ignore)
1691 if (!insn_call_dest(insn)) {
1692 WARN_INSN(insn, "unannotated intra-function call");
1696 if (insn_func(insn) && insn_call_dest(insn)->type != STT_FUNC) {
1697 WARN_INSN(insn, "unsupported call to non-function");
1705 WARN_INSN(insn, "can't find call dest symbol at %s+0x%lx",
1710 add_call_dest(file, insn, dest, false);
1713 add_retpoline_call(file, insn);
1716 add_call_dest(file, insn, reloc->sym, false);
1731 struct instruction *last_new_insn = NULL, *insn, *nop = NULL;
1751 insn = orig_insn;
1752 sec_for_each_insn_from(file, insn) {
1753 if (insn->offset >= special_alt->orig_off + special_alt->orig_len)
1756 insn->alt_group = orig_alt_group;
1757 last_orig_insn = insn;
1810 insn = *new_insn;
1811 sec_for_each_insn_from(file, insn) {
1814 if (insn->offset >= special_alt->new_off + special_alt->new_len)
1817 last_new_insn = insn;
1819 insn->ignore = orig_insn->ignore_alts;
1820 insn->sym = orig_insn->sym;
1821 insn->alt_group = new_alt_group;
1831 alt_reloc = insn_reloc(file, insn);
1833 !arch_support_alt_relocation(special_alt, insn, alt_reloc)) {
1835 WARN_INSN(insn, "unsupported relocation in alternatives section");
1839 if (!is_static_jump(insn))
1842 if (!insn->immediate)
1845 dest_off = arch_jump_destination(insn);
1847 insn->jump_dest = next_insn_same_sec(file, orig_alt_group->last_insn);
1848 if (!insn->jump_dest) {
1849 WARN_INSN(insn, "can't find alternative jump destination");
1919 * instruction(s) has them added to its insn->alts list, which will be
1982 alt->insn = new_insn;
2002 static int add_jump_table(struct objtool_file *file, struct instruction *insn,
2005 struct symbol *pfunc = insn_func(insn)->pfunc;
2006 struct reloc *table = insn_jump_table(insn);
2045 alt->insn = dest_insn;
2046 alt->next = insn->alts;
2047 insn->alts = alt;
2052 WARN_INSN(insn, "can't find switch jump table");
2065 struct instruction *insn)
2068 struct instruction *dest_insn, *orig_insn = insn;
2076 insn && insn_func(insn) && insn_func(insn)->pfunc == func;
2077 insn = insn->first_jump_src ?: prev_insn_same_sym(file, insn)) {
2079 if (insn != orig_insn && insn->type == INSN_JUMP_DYNAMIC)
2083 if (insn->type == INSN_JUMP_UNCONDITIONAL &&
2084 insn->jump_dest &&
2085 (insn->jump_dest->offset <= insn->offset ||
2086 insn->jump_dest->offset > orig_insn->offset))
2089 table_reloc = arch_find_switch_table(file, insn);
2109 struct instruction *insn, *last = NULL;
2112 func_for_each_insn(file, func, insn) {
2114 last = insn;
2121 if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest &&
2122 insn->offset > last->offset &&
2123 insn->jump_dest->offset > insn->offset &&
2124 !insn->jump_dest->first_jump_src) {
2126 insn->jump_dest->first_jump_src = insn;
2127 last = insn->jump_dest;
2130 if (insn->type != INSN_JUMP_DYNAMIC)
2133 reloc = find_jump_table(file, func, insn);
2135 insn->_jump_table = reloc;
2142 struct instruction *insn, *insn_t1 = NULL, *insn_t2;
2145 func_for_each_insn(file, func, insn) {
2146 if (!insn_jump_table(insn))
2150 insn_t1 = insn;
2154 insn_t2 = insn;
2172 * This finds these jump tables and adds them to the insn->alts lists.
2209 struct instruction *insn;
2238 insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
2239 if (!insn) {
2240 WARN("can't find insn for unwind_hints[%d]", i);
2244 insn->hint = true;
2247 insn->cfi = &force_undefined_cfi;
2252 insn->hint = false;
2253 insn->save = true;
2258 insn->restore = true;
2263 struct symbol *sym = find_symbol_by_offset(insn->sec, insn->offset);
2266 if (opts.ibt && insn->type != INSN_ENDBR && !insn->noendbr) {
2267 WARN_INSN(insn, "UNWIND_HINT_IRET_REGS without ENDBR");
2273 insn->cfi = &func_cfi;
2277 if (insn->cfi)
2278 cfi = *(insn->cfi);
2281 WARN_INSN(insn, "unsupported unwind_hint sp base reg %d", hint->sp_reg);
2289 insn->cfi = cfi_hash_find_or_add(&cfi);
2297 struct instruction *insn;
2306 insn = find_insn(file, reloc->sym->sec,
2308 if (!insn) {
2313 insn->noendbr = 1;
2322 struct instruction *insn;
2335 insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
2336 if (!insn) {
2341 if (insn->type != INSN_JUMP_DYNAMIC &&
2342 insn->type != INSN_CALL_DYNAMIC &&
2343 insn->type != INSN_RETURN &&
2344 insn->type != INSN_NOP) {
2345 WARN_INSN(insn, "retpoline_safe hint not an indirect jump/call/ret/nop");
2349 insn->retpoline_safe = true;
2358 struct instruction *insn;
2371 insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
2372 if (!insn) {
2377 insn->instr--;
2390 insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
2391 if (!insn) {
2396 insn->instr++;
2405 struct instruction *insn;
2418 insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
2419 if (!insn) {
2423 insn->unret = 1;
2432 struct instruction *insn;
2449 insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
2450 if (!insn) {
2455 if (insn->type != INSN_CALL) {
2456 WARN_INSN(insn, "intra_function_call not a direct call");
2465 insn->type = INSN_JUMP_UNCONDITIONAL;
2467 dest_off = arch_jump_destination(insn);
2468 insn->jump_dest = find_insn(file, insn->sec, dest_off);
2469 if (!insn->jump_dest) {
2470 WARN_INSN(insn, "can't find call dest at %s+0x%lx",
2471 insn->sec->name, dest_off);
2590 * Must be before read_unwind_hints() since that needs insn->noendbr.
2653 static bool is_special_call(struct instruction *insn)
2655 if (insn->type == INSN_CALL) {
2656 struct symbol *dest = insn_call_dest(insn);
2668 static bool has_modified_stack_frame(struct instruction *insn, struct insn_state *state)
2713 static int update_cfi_state_regs(struct instruction *insn,
2806 static int update_cfi_state(struct instruction *insn,
2819 if (insn_func(insn)) {
2820 WARN_INSN(insn, "undefined stack state");
2828 return update_cfi_state_regs(insn, cfi, op);
3003 WARN_INSN(insn, "unsupported stack register modification");
3013 WARN_INSN(insn, "unsupported stack pointer realignment");
3108 WARN_INSN(insn, "unknown stack-related instruction");
3151 if (opts.stackval && insn_func(insn) && op->src.reg == CFI_BP &&
3197 WARN_INSN(insn, "unknown stack-related memory operation");
3209 WARN_INSN(insn, "unknown stack-related instruction");
3225 static int propagate_alt_cfi(struct objtool_file *file, struct instruction *insn)
3230 if (!insn->alt_group)
3233 if (!insn->cfi) {
3238 alt_cfi = insn->alt_group->cfi;
3239 group_off = insn->offset - insn->alt_group->first_insn->offset;
3242 alt_cfi[group_off] = insn->cfi;
3244 if (cficmp(alt_cfi[group_off], insn->cfi)) {
3245 struct alt_group *orig_group = insn->alt_group->orig_group ?: insn->alt_group;
3247 char *where = offstr(insn->sec, insn->offset);
3257 static int handle_insn_ops(struct instruction *insn,
3263 for (op = insn->stack_ops; op; op = op->next) {
3265 if (update_cfi_state(insn, next_insn, &state->cfi, op))
3268 if (!insn->alt_group)
3275 WARN_INSN(insn, "PUSHF stack exhausted");
3295 static bool insn_cfi_match(struct instruction *insn, struct cfi_state *cfi2)
3297 struct cfi_state *cfi1 = insn->cfi;
3307 WARN_INSN(insn, "stack state mismatch: cfa1=%d%+d cfa2=%d%+d",
3317 WARN_INSN(insn, "stack state mismatch: reg1[%d]=%d%+d reg2[%d]=%d%+d",
3325 WARN_INSN(insn, "stack state mismatch: type1=%d type2=%d",
3332 WARN_INSN(insn, "stack state mismatch: drap1=%d(%d,%d) drap2=%d(%d,%d)",
3350 static inline const char *call_dest_name(struct instruction *insn)
3356 if (insn_call_dest(insn))
3357 return insn_call_dest(insn)->name;
3359 reloc = insn_reloc(NULL, insn);
3369 static bool pv_call_dest(struct objtool_file *file, struct instruction *insn)
3375 reloc = insn_reloc(file, insn);
3397 struct instruction *insn,
3406 return pv_call_dest(file, insn);
3435 struct instruction *insn,
3439 !noinstr_call_dest(file, insn, insn_call_dest(insn))) {
3440 WARN_INSN(insn, "call to %s() leaves .noinstr.text section", call_dest_name(insn));
3444 if (state->uaccess && !func_uaccess_safe(insn_call_dest(insn))) {
3445 WARN_INSN(insn, "call to %s() with UACCESS enabled", call_dest_name(insn));
3450 WARN_INSN(insn, "call to %s() with DF set", call_dest_name(insn));
3458 struct instruction *insn,
3461 if (insn_func(insn) && has_modified_stack_frame(insn, state)) {
3462 WARN_INSN(insn, "sibling call from callable instruction with modified stack frame");
3466 return validate_call(file, insn, state);
3469 static int validate_return(struct symbol *func, struct instruction *insn, struct insn_state *state)
3472 WARN_INSN(insn, "return with instrumentation enabled");
3477 WARN_INSN(insn, "return with UACCESS enabled");
3482 WARN_INSN(insn, "return with UACCESS disabled from a UACCESS-safe function");
3487 WARN_INSN(insn, "return with DF set");
3491 if (func && has_modified_stack_frame(insn, state)) {
3492 WARN_INSN(insn, "return with modified stack frame");
3497 WARN_INSN(insn, "BP used as a scratch register");
3505 struct instruction *insn)
3507 struct alt_group *alt_group = insn->alt_group;
3514 * insn->alts->insn -> alt_group->first_insn
3522 if (insn == alt_group->last_insn)
3524 if (insn == alt_group->nop)
3527 if (insn == alt_group->last_insn && alt_group->orig_group)
3531 return next_insn_same_sec(file, insn);
3544 struct instruction *insn, struct insn_state state)
3552 sec = insn->sec;
3555 next_insn = next_insn_to_validate(file, insn);
3557 if (func && insn_func(insn) && func != insn_func(insn)->pfunc) {
3564 func->name, insn_func(insn)->name);
3568 if (func && insn->ignore) {
3569 WARN_INSN(insn, "BUG: why am I validating an ignored function?");
3574 if (insn->visited & VISITED_BRANCH_MASK) {
3575 if (!insn->hint && !insn_cfi_match(insn, &state.cfi))
3578 if (insn->visited & visited)
3585 state.instr += insn->instr;
3587 if (insn->hint) {
3588 if (insn->restore) {
3591 i = insn;
3602 WARN_INSN(insn, "no corresponding CFI save for CFI restore");
3608 * If the restore hint insn is at the
3611 * save insn hasn't been visited yet,
3619 WARN_INSN(insn, "objtool isn't smart enough to handle this CFI save/restore combo");
3623 insn->cfi = save_insn->cfi;
3627 state.cfi = *insn->cfi;
3632 insn->cfi = prev_insn->cfi;
3635 insn->cfi = cfi_hash_find_or_add(&state.cfi);
3639 insn->visited |= visited;
3641 if (propagate_alt_cfi(file, insn))
3644 if (!insn->ignore_alts && insn->alts) {
3647 for (alt = insn->alts; alt; alt = alt->next) {
3651 ret = validate_branch(file, func, alt->insn, state);
3653 BT_INSN(insn, "(alt)");
3662 if (handle_insn_ops(insn, next_insn, &state))
3665 switch (insn->type) {
3668 return validate_return(func, insn, &state);
3672 ret = validate_call(file, insn, &state);
3676 if (opts.stackval && func && !is_special_call(insn) &&
3678 WARN_INSN(insn, "call without frame pointer save/setup");
3682 if (insn->dead_end)
3689 if (is_sibling_call(insn)) {
3690 ret = validate_sibling_call(file, insn, &state);
3694 } else if (insn->jump_dest) {
3696 insn->jump_dest, state);
3698 BT_INSN(insn, "(branch)");
3703 if (insn->type == INSN_JUMP_UNCONDITIONAL)
3710 if (is_sibling_call(insn)) {
3711 ret = validate_sibling_call(file, insn, &state);
3716 if (insn->type == INSN_JUMP_DYNAMIC)
3723 WARN_INSN(insn, "unsupported instruction in callable function");
3730 WARN_INSN(insn, "recursive UACCESS enable");
3739 WARN_INSN(insn, "redundant UACCESS disable");
3744 WARN_INSN(insn, "UACCESS-safe disables UACCESS");
3753 WARN_INSN(insn, "recursive STD");
3762 WARN_INSN(insn, "redundant CLD");
3773 if (insn->dead_end)
3783 prev_insn = insn;
3784 insn = next_insn;
3791 struct instruction *insn,
3794 if (insn->hint && !insn->visited && !insn->ignore) {
3795 int ret = validate_branch(file, insn_func(insn), insn, *state);
3797 BT_INSN(insn, "<=== (hint)");
3806 struct instruction *insn;
3816 sec_for_each_insn(file, sec, insn)
3817 warnings += validate_unwind_hint(file, insn, &state);
3819 for_each_insn(file, insn)
3820 warnings += validate_unwind_hint(file, insn, &state);
3832 static int validate_unret(struct objtool_file *file, struct instruction *insn)
3838 next = next_insn_to_validate(file, insn);
3840 if (insn->visited & VISITED_UNRET)
3843 insn->visited |= VISITED_UNRET;
3845 if (!insn->ignore_alts && insn->alts) {
3849 for (alt = insn->alts; alt; alt = alt->next) {
3853 ret = validate_unret(file, alt->insn);
3855 BT_INSN(insn, "(alt)");
3864 switch (insn->type) {
3869 WARN_INSN(insn, "early indirect call");
3874 if (!is_sibling_call(insn)) {
3875 if (!insn->jump_dest) {
3876 WARN_INSN(insn, "unresolved jump target after linking?!?");
3879 ret = validate_unret(file, insn->jump_dest);
3881 BT_INSN(insn, "(branch%s)",
3882 insn->type == INSN_JUMP_CONDITIONAL ? "-cond" : "");
3886 if (insn->type == INSN_JUMP_UNCONDITIONAL)
3894 dest = find_insn(file, insn_call_dest(insn)->sec,
3895 insn_call_dest(insn)->offset);
3898 insn_call_dest(insn)->name);
3904 BT_INSN(insn, "(call)");
3914 WARN_INSN(insn, "RET before UNTRAIN");
3918 if (insn->retpoline_safe)
3927 WARN_INSN(insn, "teh end!");
3930 insn = next;
3942 struct instruction *insn;
3945 for_each_insn(file, insn) {
3946 if (!insn->unret)
3949 ret = validate_unret(file, insn);
3951 WARN_INSN(insn, "Failed UNRET validation");
3962 struct instruction *insn;
3965 for_each_insn(file, insn) {
3966 if (insn->type != INSN_JUMP_DYNAMIC &&
3967 insn->type != INSN_CALL_DYNAMIC &&
3968 insn->type != INSN_RETURN)
3971 if (insn->retpoline_safe)
3974 if (insn->sec->init)
3977 if (insn->type == INSN_RETURN) {
3979 WARN_INSN(insn, "'naked' return found in RETHUNK build");
3983 WARN_INSN(insn, "indirect %s found in RETPOLINE build",
3984 insn->type == INSN_JUMP_DYNAMIC ? "jump" : "call");
3993 static bool is_kasan_insn(struct instruction *insn)
3995 return (insn->type == INSN_CALL &&
3996 !strcmp(insn_call_dest(insn)->name, "__asan_handle_no_return"));
3999 static bool is_ubsan_insn(struct instruction *insn)
4001 return (insn->type == INSN_CALL &&
4002 !strcmp(insn_call_dest(insn)->name,
4006 static bool ignore_unreachable_insn(struct objtool_file *file, struct instruction *insn)
4011 if (insn->ignore || insn->type == INSN_NOP || insn->type == INSN_TRAP)
4018 if (!strcmp(insn->sec->name, ".altinstr_replacement") ||
4019 !strcmp(insn->sec->name, ".altinstr_aux"))
4030 if (opts.link && !insn_func(insn)) {
4031 int size = find_symbol_hole_containing(insn->sec, insn->offset);
4032 unsigned long end = insn->offset + size;
4040 sec_for_each_insn_continue(file, insn) {
4045 if (insn->visited)
4048 if (insn->offset >= end)
4054 if (insn->jump_dest && insn_func(insn->jump_dest) &&
4055 strstr(insn_func(insn->jump_dest)->name, ".cold")) {
4056 struct instruction *dest = insn->jump_dest;
4065 if (!insn_func(insn))
4068 if (insn_func(insn)->static_call_tramp)
4079 prev_insn = prev_insn_same_sec(file, insn);
4081 (insn->type == INSN_BUG ||
4082 (insn->type == INSN_JUMP_UNCONDITIONAL &&
4083 insn->jump_dest && insn->jump_dest->type == INSN_BUG)))
4094 if (is_kasan_insn(insn) || is_ubsan_insn(insn))
4097 if (insn->type == INSN_JUMP_UNCONDITIONAL) {
4098 if (insn->jump_dest &&
4099 insn_func(insn->jump_dest) == insn_func(insn)) {
4100 insn = insn->jump_dest;
4107 if (insn->offset + insn->len >= insn_func(insn)->offset + insn_func(insn)->len)
4110 insn = next_insn_same_sec(file, insn);
4118 struct instruction *insn, *prev;
4121 insn = find_insn(file, func->sec, func->offset);
4122 if (!insn)
4125 for (prev = prev_insn_same_sec(file, insn);
4148 if (!insn->cfi) {
4156 /* Propagate insn->cfi to the prefix code */
4157 cfi = cfi_hash_find_or_add(insn->cfi);
4158 for (; prev != insn; prev = next_insn_same_sec(file, prev))
4187 struct instruction *insn;
4198 insn = find_insn(file, sec, sym->offset);
4199 if (!insn || insn->ignore || insn->visited)
4204 ret = validate_branch(file, insn_func(insn), insn, *state);
4206 BT_INSN(insn, "<=== (sym)");
4270 static void mark_endbr_used(struct instruction *insn)
4272 if (!list_empty(&insn->call_node))
4273 list_del_init(&insn->call_node);
4276 static bool noendbr_range(struct objtool_file *file, struct instruction *insn)
4278 struct symbol *sym = find_symbol_containing(insn->sec, insn->offset-1);
4291 return insn->offset == sym->offset + sym->len;
4294 static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn)
4305 switch (insn->type) {
4319 for (reloc = insn_reloc(file, insn);
4321 reloc = find_reloc_by_dest_range(file->elf, insn->sec,
4323 (insn->offset + insn->len) - (reloc_offset(reloc) + 1))) {
4348 if (insn_func(dest) && insn_func(insn) &&
4349 insn_func(dest)->pfunc == insn_func(insn)->pfunc) {
4381 WARN_INSN(insn, "relocation to !ENDBR: %s", offstr(dest->sec, dest->offset));
4423 struct instruction *insn;
4426 for_each_insn(file, insn)
4427 warnings += validate_ibt_insn(file, insn);
4471 struct instruction *insn, *next_insn;
4474 for_each_insn(file, insn) {
4475 next_insn = next_insn_same_sec(file, insn);
4477 if (insn->retpoline_safe)
4480 switch (insn->type) {
4483 WARN_INSN(insn, "missing int3 after ret");
4490 WARN_INSN(insn, "missing int3 after indirect jump");
4502 static bool ignore_noreturn_call(struct instruction *insn)
4504 struct symbol *call_dest = insn_call_dest(insn);
4524 insn->sym->warned = 1;
4533 struct instruction *insn, *prev_insn;
4540 for_each_insn(file, insn) {
4541 if (insn->visited || ignore_unreachable_insn(file, insn))
4544 prev_insn = prev_insn_same_sec(file, insn);
4548 WARN_INSN(insn, "%s() is missing a __noreturn annotation",
4555 WARN_INSN(insn, "unreachable instruction");
4649 struct instruction *insn;
4652 for_each_insn(file, insn) {
4653 if (!insn->idx) {
4655 chunk->addr = insn;
4726 * further games with insn->visited.