Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * Copyright (C) 2015-2017 Josh Poimboeuf <jpoimboe@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9) #include "builtin.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10) #include "cfi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) #include "arch.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) #include "check.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) #include "special.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #include "warn.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include "arch_elf.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/objtool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/hashtable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <linux/static_call_types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #define FAKE_JUMP_OFFSET -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) struct alternative {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) 	struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) 	bool skip_orig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) struct cfi_init_state initial_func_cfi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) struct instruction *find_insn(struct objtool_file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) 			      struct section *sec, unsigned long offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) 	hash_for_each_possible(file->insn_hash, insn, hash, sec_offset_hash(sec, offset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) 		if (insn->sec == sec && insn->offset == offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) 			return insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) static struct instruction *next_insn_same_sec(struct objtool_file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 					      struct instruction *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) 	struct instruction *next = list_next_entry(insn, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 	if (!next || &next->list == &file->insn_list || next->sec != insn->sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) 	return next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) static struct instruction *next_insn_same_func(struct objtool_file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) 					       struct instruction *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) 	struct instruction *next = list_next_entry(insn, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) 	struct symbol *func = insn->func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) 	if (!func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 	if (&next->list != &file->insn_list && next->func == func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) 		return next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 	/* Check if we're already in the subfunction: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 	if (func == func->cfunc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 	/* Move to the subfunction: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 	return find_insn(file, func->cfunc->sec, func->cfunc->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) static struct instruction *prev_insn_same_sym(struct objtool_file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 					       struct instruction *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 	struct instruction *prev = list_prev_entry(insn, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 	if (&prev->list != &file->insn_list && prev->func == insn->func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) 		return prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) #define func_for_each_insn(file, func, insn)				\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 	for (insn = find_insn(file, func->sec, func->offset);		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) 	     insn;							\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 	     insn = next_insn_same_func(file, insn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) #define sym_for_each_insn(file, sym, insn)				\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 	for (insn = find_insn(file, sym->sec, sym->offset);		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 	     insn && &insn->list != &file->insn_list &&			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 		insn->sec == sym->sec &&				\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) 		insn->offset < sym->offset + sym->len;			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 	     insn = list_next_entry(insn, list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) #define sym_for_each_insn_continue_reverse(file, sym, insn)		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) 	for (insn = list_prev_entry(insn, list);			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) 	     &insn->list != &file->insn_list &&				\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 		insn->sec == sym->sec && insn->offset >= sym->offset;	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 	     insn = list_prev_entry(insn, list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) #define sec_for_each_insn_from(file, insn)				\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 	for (; insn; insn = next_insn_same_sec(file, insn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) #define sec_for_each_insn_continue(file, insn)				\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 	for (insn = next_insn_same_sec(file, insn); insn;		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 	     insn = next_insn_same_sec(file, insn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) static bool is_sibling_call(struct instruction *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 	/* An indirect jump is either a sibling call or a jump to a table. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 	if (insn->type == INSN_JUMP_DYNAMIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 		return list_empty(&insn->alts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 	if (!is_static_jump(insn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 	/* add_jump_destinations() sets insn->call_dest for sibling calls. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 	return !!insn->call_dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126)  * This checks to see if the given function is a "noreturn" function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128)  * For global functions which are outside the scope of this object file, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129)  * have to keep a manual list of them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131)  * For local functions, we have to detect them manually by simply looking for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132)  * the lack of a return instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) static bool __dead_end_function(struct objtool_file *file, struct symbol *func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 				int recursion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	bool empty = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 	 * Unfortunately these have to be hard coded because the noreturn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 	 * attribute isn't provided in ELF data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 	static const char * const global_noreturns[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 		"__stack_chk_fail",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 		"panic",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 		"do_exit",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 		"do_task_dead",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 		"__module_put_and_exit",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 		"complete_and_exit",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 		"__reiserfs_panic",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 		"lbug_with_loc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 		"fortify_panic",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 		"usercopy_abort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 		"machine_real_restart",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 		"rewind_stack_do_exit",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 		"kunit_try_catch_throw",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 		"xen_start_kernel",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 		"cpu_bringup_and_idle",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 	if (!func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 	if (func->bind == STB_WEAK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 	if (func->bind == STB_GLOBAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 		for (i = 0; i < ARRAY_SIZE(global_noreturns); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 			if (!strcmp(func->name, global_noreturns[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 				return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 	if (!func->len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 	insn = find_insn(file, func->sec, func->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 	if (!insn->func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 	func_for_each_insn(file, func, insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 		empty = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 		if (insn->type == INSN_RETURN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 	if (empty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 	 * A function can have a sibling call instead of a return.  In that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 	 * case, the function's dead-end status depends on whether the target
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	 * of the sibling call returns.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 	func_for_each_insn(file, func, insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 		if (is_sibling_call(insn)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 			struct instruction *dest = insn->jump_dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 			if (!dest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 				/* sibling call to another file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 				return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 			/* local sibling call */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 			if (recursion == 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 				 * Infinite recursion: two functions have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 				 * sibling calls to each other.  This is a very
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 				 * rare case.  It means they aren't dead ends.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 				return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 			return __dead_end_function(file, dest->func, recursion+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) static bool dead_end_function(struct objtool_file *file, struct symbol *func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 	return __dead_end_function(file, func, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) static void init_cfi_state(struct cfi_state *cfi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 	for (i = 0; i < CFI_NUM_REGS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 		cfi->regs[i].base = CFI_UNDEFINED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 		cfi->vals[i].base = CFI_UNDEFINED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 	cfi->cfa.base = CFI_UNDEFINED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 	cfi->drap_reg = CFI_UNDEFINED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 	cfi->drap_offset = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) static void init_insn_state(struct insn_state *state, struct section *sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 	memset(state, 0, sizeof(*state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 	init_cfi_state(&state->cfi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	 * We need the full vmlinux for noinstr validation, otherwise we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 	 * not correctly determine insn->call_dest->sec (external symbols do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 	 * not have a section).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 	if (vmlinux && noinstr && sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 		state->noinstr = sec->noinstr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254)  * Call the arch-specific instruction decoder for all the instructions and add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255)  * them to the global instruction list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) static int decode_instructions(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 	struct section *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	struct symbol *func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	unsigned long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	unsigned long nr_insns = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 	for_each_sec(file, sec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 		if (!(sec->sh.sh_flags & SHF_EXECINSTR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 		if (strcmp(sec->name, ".altinstr_replacement") &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 		    strcmp(sec->name, ".altinstr_aux") &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 		    strncmp(sec->name, ".discard.", 9))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 			sec->text = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 		if (!strcmp(sec->name, ".noinstr.text") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 		    !strcmp(sec->name, ".entry.text"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 			sec->noinstr = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 		for (offset = 0; offset < sec->len; offset += insn->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 			insn = malloc(sizeof(*insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 			if (!insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 				WARN("malloc failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 				return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 			memset(insn, 0, sizeof(*insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 			INIT_LIST_HEAD(&insn->alts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 			INIT_LIST_HEAD(&insn->stack_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 			init_cfi_state(&insn->cfi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 			insn->sec = sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 			insn->offset = offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 			ret = arch_decode_instruction(file->elf, sec, offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 						      sec->len - offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 						      &insn->len, &insn->type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 						      &insn->immediate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 						      &insn->stack_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 				goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 			hash_add(file->insn_hash, &insn->hash, sec_offset_hash(sec, insn->offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 			list_add_tail(&insn->list, &file->insn_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 			nr_insns++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 		list_for_each_entry(func, &sec->symbol_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 			if (func->type != STT_FUNC || func->alias != func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 			if (!find_insn(file, sec, func->offset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 				WARN("%s(): can't find starting instruction",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 				     func->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 				return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 			sym_for_each_insn(file, func, insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 				insn->func = func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 	if (stats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 		printf("nr_insns: %lu\n", nr_insns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 	free(insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) static struct instruction *find_last_insn(struct objtool_file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 					  struct section *sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 	struct instruction *insn = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 	unsigned int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 	unsigned int end = (sec->len > 10) ? sec->len - 10 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 	for (offset = sec->len - 1; offset >= end && !insn; offset--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 		insn = find_insn(file, sec, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 	return insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346)  * Mark "ud2" instructions and manually annotated dead ends.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) static int add_dead_ends(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 	struct section *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 	struct reloc *reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 	 * By default, "ud2" is a dead end unless otherwise annotated, because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	 * GCC 7 inserts it for certain divide-by-zero cases.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 	for_each_insn(file, insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 		if (insn->type == INSN_BUG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 			insn->dead_end = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 	 * Check for manually annotated dead ends.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	sec = find_section_by_name(file->elf, ".rela.discard.unreachable");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 	if (!sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 		goto reachable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 	list_for_each_entry(reloc, &sec->reloc_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 		if (reloc->sym->type != STT_SECTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 			WARN("unexpected relocation symbol type in %s", sec->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 		insn = find_insn(file, reloc->sym->sec, reloc->addend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 		if (insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 			insn = list_prev_entry(insn, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 		else if (reloc->addend == reloc->sym->sec->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 			insn = find_last_insn(file, reloc->sym->sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 			if (!insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 				WARN("can't find unreachable insn at %s+0x%x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 				     reloc->sym->sec->name, reloc->addend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 				return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 			WARN("can't find unreachable insn at %s+0x%x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 			     reloc->sym->sec->name, reloc->addend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 		insn->dead_end = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) reachable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 	 * These manually annotated reachable checks are needed for GCC 4.4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 	 * where the Linux unreachable() macro isn't supported.  In that case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 	 * GCC doesn't know the "ud2" is fatal, so it generates code as if it's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 	 * not a dead end.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 	sec = find_section_by_name(file->elf, ".rela.discard.reachable");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 	if (!sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 	list_for_each_entry(reloc, &sec->reloc_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 		if (reloc->sym->type != STT_SECTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 			WARN("unexpected relocation symbol type in %s", sec->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 		insn = find_insn(file, reloc->sym->sec, reloc->addend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 		if (insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 			insn = list_prev_entry(insn, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 		else if (reloc->addend == reloc->sym->sec->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 			insn = find_last_insn(file, reloc->sym->sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 			if (!insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 				WARN("can't find reachable insn at %s+0x%x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 				     reloc->sym->sec->name, reloc->addend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 				return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 			WARN("can't find reachable insn at %s+0x%x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 			     reloc->sym->sec->name, reloc->addend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 		insn->dead_end = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) static int create_static_call_sections(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	struct section *sec, *reloc_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 	struct reloc *reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	struct static_call_site *site;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 	struct symbol *key_sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 	char *key_name, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	sec = find_section_by_name(file->elf, ".static_call_sites");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 	if (sec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 		INIT_LIST_HEAD(&file->static_call_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 		WARN("file already has .static_call_sites section, skipping");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 	if (list_empty(&file->static_call_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 	idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 	list_for_each_entry(insn, &file->static_call_list, static_call_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 		idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 	sec = elf_create_section(file->elf, ".static_call_sites", SHF_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 				 sizeof(struct static_call_site), idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 	if (!sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	reloc_sec = elf_create_reloc_section(file->elf, sec, SHT_RELA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 	if (!reloc_sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 	list_for_each_entry(insn, &file->static_call_list, static_call_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 		site = (struct static_call_site *)sec->data->d_buf + idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 		memset(site, 0, sizeof(struct static_call_site));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 		/* populate reloc for 'addr' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 		reloc = malloc(sizeof(*reloc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 		if (!reloc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 			perror("malloc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 		memset(reloc, 0, sizeof(*reloc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 		insn_to_reloc_sym_addend(insn->sec, insn->offset, reloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 		if (!reloc->sym) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 			WARN_FUNC("static call tramp: missing containing symbol",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 				  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 		reloc->type = R_X86_64_PC32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 		reloc->offset = idx * sizeof(struct static_call_site);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 		reloc->sec = reloc_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 		elf_add_reloc(file->elf, reloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 		/* find key symbol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 		key_name = strdup(insn->call_dest->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 		if (!key_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 			perror("strdup");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 		if (strncmp(key_name, STATIC_CALL_TRAMP_PREFIX_STR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 			    STATIC_CALL_TRAMP_PREFIX_LEN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 			WARN("static_call: trampoline name malformed: %s", key_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 		tmp = key_name + STATIC_CALL_TRAMP_PREFIX_LEN - STATIC_CALL_KEY_PREFIX_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 		memcpy(tmp, STATIC_CALL_KEY_PREFIX_STR, STATIC_CALL_KEY_PREFIX_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 		key_sym = find_symbol_by_name(file->elf, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 		if (!key_sym) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 			if (!module) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 				WARN("static_call: can't find static_call_key symbol: %s", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 				return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 			 * For modules(), the key might not be exported, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 			 * means the module can make static calls but isn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 			 * allowed to change them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 			 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 			 * In that case we temporarily set the key to be the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 			 * trampoline address.  This is fixed up in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 			 * static_call_add_module().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 			key_sym = insn->call_dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 		free(key_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 		/* populate reloc for 'key' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 		reloc = malloc(sizeof(*reloc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 		if (!reloc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 			perror("malloc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 		memset(reloc, 0, sizeof(*reloc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 		reloc->sym = key_sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 		reloc->addend = is_sibling_call(insn) ? STATIC_CALL_SITE_TAIL : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 		reloc->type = R_X86_64_PC32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 		reloc->offset = idx * sizeof(struct static_call_site) + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 		reloc->sec = reloc_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 		elf_add_reloc(file->elf, reloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 		idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 	if (elf_rebuild_reloc_section(file->elf, reloc_sec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) static int create_mcount_loc_sections(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 	struct section *sec, *reloc_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 	struct reloc *reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 	unsigned long *loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 	int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 	sec = find_section_by_name(file->elf, "__mcount_loc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	if (sec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 		INIT_LIST_HEAD(&file->mcount_loc_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 		WARN("file already has __mcount_loc section, skipping");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 	if (list_empty(&file->mcount_loc_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 	idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	list_for_each_entry(insn, &file->mcount_loc_list, mcount_loc_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 		idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 	sec = elf_create_section(file->elf, "__mcount_loc", 0, sizeof(unsigned long), idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 	if (!sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 	reloc_sec = elf_create_reloc_section(file->elf, sec, SHT_RELA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	if (!reloc_sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 	idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 	list_for_each_entry(insn, &file->mcount_loc_list, mcount_loc_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 		loc = (unsigned long *)sec->data->d_buf + idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 		memset(loc, 0, sizeof(unsigned long));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 		reloc = malloc(sizeof(*reloc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 		if (!reloc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 			perror("malloc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 		memset(reloc, 0, sizeof(*reloc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 		if (insn->sec->sym) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 			reloc->sym = insn->sec->sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 			reloc->addend = insn->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 			reloc->sym = find_symbol_containing(insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 			if (!reloc->sym) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 				WARN("missing symbol for insn at offset 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 				     insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 				return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 			reloc->addend = insn->offset - reloc->sym->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 		reloc->type = R_X86_64_64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 		reloc->offset = idx * sizeof(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 		reloc->sec = reloc_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 		elf_add_reloc(file->elf, reloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 		idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 	if (elf_rebuild_reloc_section(file->elf, reloc_sec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621)  * Warnings shouldn't be reported for ignored functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) static void add_ignores(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 	struct section *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 	struct symbol *func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 	struct reloc *reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 	sec = find_section_by_name(file->elf, ".rela.discard.func_stack_frame_non_standard");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 	if (!sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	list_for_each_entry(reloc, &sec->reloc_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 		switch (reloc->sym->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 		case STT_FUNC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 			func = reloc->sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 		case STT_SECTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 			func = find_func_by_offset(reloc->sym->sec, reloc->addend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 			if (!func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 			WARN("unexpected relocation symbol type in %s: %d", sec->name, reloc->sym->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 		func_for_each_insn(file, func, insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 			insn->ignore = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657)  * This is a whitelist of functions that is allowed to be called with AC set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658)  * The list is meant to be minimal and only contains compiler instrumentation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659)  * ABI and a few functions used to implement *_{to,from}_user() functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661)  * These functions must not directly change AC, but may PUSHF/POPF.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) static const char *uaccess_safe_builtin[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 	/* KASAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 	"kasan_report",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	"kasan_check_range",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 	/* KASAN out-of-line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 	"__asan_loadN_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 	"__asan_load1_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 	"__asan_load2_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	"__asan_load4_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 	"__asan_load8_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 	"__asan_load16_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 	"__asan_storeN_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 	"__asan_store1_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 	"__asan_store2_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 	"__asan_store4_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 	"__asan_store8_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 	"__asan_store16_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 	"__kasan_check_read",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 	"__kasan_check_write",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 	/* KASAN in-line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 	"__asan_report_load_n_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 	"__asan_report_load1_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 	"__asan_report_load2_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 	"__asan_report_load4_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 	"__asan_report_load8_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 	"__asan_report_load16_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 	"__asan_report_store_n_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 	"__asan_report_store1_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 	"__asan_report_store2_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 	"__asan_report_store4_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 	"__asan_report_store8_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 	"__asan_report_store16_noabort",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 	/* KCSAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 	"__kcsan_check_access",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 	"kcsan_found_watchpoint",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 	"kcsan_setup_watchpoint",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	"kcsan_check_scoped_accesses",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 	"kcsan_disable_current",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 	"kcsan_enable_current_nowarn",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 	/* KCSAN/TSAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 	"__tsan_func_entry",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 	"__tsan_func_exit",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 	"__tsan_read_range",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	"__tsan_write_range",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 	"__tsan_read1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	"__tsan_read2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 	"__tsan_read4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 	"__tsan_read8",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 	"__tsan_read16",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 	"__tsan_write1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 	"__tsan_write2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 	"__tsan_write4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 	"__tsan_write8",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 	"__tsan_write16",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	"__tsan_read_write1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 	"__tsan_read_write2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 	"__tsan_read_write4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 	"__tsan_read_write8",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	"__tsan_read_write16",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 	"__tsan_atomic8_load",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	"__tsan_atomic16_load",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 	"__tsan_atomic32_load",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 	"__tsan_atomic64_load",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	"__tsan_atomic8_store",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 	"__tsan_atomic16_store",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	"__tsan_atomic32_store",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	"__tsan_atomic64_store",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	"__tsan_atomic8_exchange",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 	"__tsan_atomic16_exchange",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	"__tsan_atomic32_exchange",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 	"__tsan_atomic64_exchange",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 	"__tsan_atomic8_fetch_add",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 	"__tsan_atomic16_fetch_add",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 	"__tsan_atomic32_fetch_add",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 	"__tsan_atomic64_fetch_add",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 	"__tsan_atomic8_fetch_sub",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 	"__tsan_atomic16_fetch_sub",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 	"__tsan_atomic32_fetch_sub",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 	"__tsan_atomic64_fetch_sub",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 	"__tsan_atomic8_fetch_and",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	"__tsan_atomic16_fetch_and",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 	"__tsan_atomic32_fetch_and",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	"__tsan_atomic64_fetch_and",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 	"__tsan_atomic8_fetch_or",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 	"__tsan_atomic16_fetch_or",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 	"__tsan_atomic32_fetch_or",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 	"__tsan_atomic64_fetch_or",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	"__tsan_atomic8_fetch_xor",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 	"__tsan_atomic16_fetch_xor",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 	"__tsan_atomic32_fetch_xor",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	"__tsan_atomic64_fetch_xor",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 	"__tsan_atomic8_fetch_nand",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 	"__tsan_atomic16_fetch_nand",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	"__tsan_atomic32_fetch_nand",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	"__tsan_atomic64_fetch_nand",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	"__tsan_atomic8_compare_exchange_strong",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	"__tsan_atomic16_compare_exchange_strong",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 	"__tsan_atomic32_compare_exchange_strong",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	"__tsan_atomic64_compare_exchange_strong",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	"__tsan_atomic8_compare_exchange_weak",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	"__tsan_atomic16_compare_exchange_weak",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	"__tsan_atomic32_compare_exchange_weak",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	"__tsan_atomic64_compare_exchange_weak",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	"__tsan_atomic8_compare_exchange_val",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	"__tsan_atomic16_compare_exchange_val",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	"__tsan_atomic32_compare_exchange_val",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 	"__tsan_atomic64_compare_exchange_val",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 	"__tsan_atomic_thread_fence",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 	"__tsan_atomic_signal_fence",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 	/* KCOV */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	"write_comp_data",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 	"check_kcov_mode",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 	"__sanitizer_cov_trace_pc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 	"__sanitizer_cov_trace_const_cmp1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 	"__sanitizer_cov_trace_const_cmp2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 	"__sanitizer_cov_trace_const_cmp4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 	"__sanitizer_cov_trace_const_cmp8",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 	"__sanitizer_cov_trace_cmp1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 	"__sanitizer_cov_trace_cmp2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 	"__sanitizer_cov_trace_cmp4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 	"__sanitizer_cov_trace_cmp8",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 	"__sanitizer_cov_trace_switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	/* UBSAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 	"ubsan_type_mismatch_common",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 	"__ubsan_handle_type_mismatch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 	"__ubsan_handle_type_mismatch_v1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 	"__ubsan_handle_shift_out_of_bounds",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 	/* misc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	"csum_partial_copy_generic",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 	"copy_mc_fragile",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	"copy_mc_fragile_handle_tail",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 	"copy_mc_enhanced_fast_string",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 	"ftrace_likely_update", /* CONFIG_TRACE_BRANCH_PROFILING */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) static void add_uaccess_safe(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 	struct symbol *func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 	const char **name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 	if (!uaccess)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 	for (name = uaccess_safe_builtin; *name; name++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 		func = find_symbol_by_name(file->elf, *name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 		if (!func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 		func->uaccess_safe = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817)  * FIXME: For now, just ignore any alternatives which add retpolines.  This is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818)  * a temporary hack, as it doesn't allow ORC to unwind from inside a retpoline.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819)  * But it at least allows objtool to understand the control flow *around* the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820)  * retpoline.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) static int add_ignore_alternatives(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 	struct section *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 	struct reloc *reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 	sec = find_section_by_name(file->elf, ".rela.discard.ignore_alts");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 	if (!sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 	list_for_each_entry(reloc, &sec->reloc_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 		if (reloc->sym->type != STT_SECTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 			WARN("unexpected relocation symbol type in %s", sec->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 		insn = find_insn(file, reloc->sym->sec, reloc->addend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 		if (!insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 			WARN("bad .discard.ignore_alts entry");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 		insn->ignore_alts = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851)  * CONFIG_CFI_CLANG: Check if the section is a CFI jump table or a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852)  * compiler-generated CFI handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) static bool is_cfi_section(struct section *sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 	return (sec->name &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 		(!strncmp(sec->name, ".text..L.cfi.jumptable", 22) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 		 !strcmp(sec->name, ".text.__cfi_check")));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862)  * CONFIG_CFI_CLANG: Ignore CFI jump tables.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) static void add_cfi_jumptables(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	struct section *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 	struct symbol *func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	for_each_sec(file, sec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 		if (!is_cfi_section(sec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 		list_for_each_entry(func, &sec->symbol_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 			sym_for_each_insn(file, func, insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 				insn->ignore = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882)  * Find the destination instructions for all jumps.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) static int add_jump_destinations(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 	struct reloc *reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 	struct section *dest_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 	unsigned long dest_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 	for_each_insn(file, insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 		if (!is_static_jump(insn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 		if (insn->offset == FAKE_JUMP_OFFSET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 		reloc = find_reloc_by_dest_range(file->elf, insn->sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 					       insn->offset, insn->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 		if (!reloc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 			dest_sec = insn->sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 			dest_off = arch_jump_destination(insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 		} else if (reloc->sym->type == STT_SECTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 			dest_sec = reloc->sym->sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 			dest_off = arch_dest_reloc_offset(reloc->addend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 		} else if (reloc->sym->sec->idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 			dest_sec = reloc->sym->sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 			dest_off = reloc->sym->sym.st_value +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 				   arch_dest_reloc_offset(reloc->addend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 		} else if (!strncmp(reloc->sym->name, "__x86_indirect_thunk_", 21) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 			   !strncmp(reloc->sym->name, "__x86_retpoline_", 16)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 			 * Retpoline jumps are really dynamic jumps in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 			 * disguise, so convert them accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 			if (insn->type == INSN_JUMP_UNCONDITIONAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 				insn->type = INSN_JUMP_DYNAMIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 				insn->type = INSN_JUMP_DYNAMIC_CONDITIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 			insn->retpoline_safe = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 			/* external sibling call */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 			insn->call_dest = reloc->sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 			if (insn->call_dest->static_call_tramp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 				list_add_tail(&insn->static_call_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 					      &file->static_call_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 		insn->jump_dest = find_insn(file, dest_sec, dest_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 		if (!insn->jump_dest && dest_sec->len == dest_off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 			insn->jump_dest = find_last_insn(file, dest_sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 		if (!insn->jump_dest) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 			 * This is a special case where an alt instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 			 * jumps past the end of the section.  These are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 			 * handled later in handle_group_alt().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 			if (!strcmp(insn->sec->name, ".altinstr_replacement"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 			if (is_cfi_section(insn->sec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 			WARN_FUNC("can't find jump dest instruction at %s+0x%lx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 				  insn->sec, insn->offset, dest_sec->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 				  dest_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 		 * Cross-function jump.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 		if (insn->func && insn->jump_dest->func &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 		    insn->func != insn->jump_dest->func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 			 * For GCC 8+, create parent/child links for any cold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 			 * subfunctions.  This is _mostly_ redundant with a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 			 * similar initialization in read_symbols().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 			 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 			 * If a function has aliases, we want the *first* such
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 			 * function in the symbol table to be the subfunction's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 			 * parent.  In that case we overwrite the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 			 * initialization done in read_symbols().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 			 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 			 * However this code can't completely replace the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 			 * read_symbols() code because this doesn't detect the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 			 * case where the parent function's only reference to a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 			 * subfunction is through a jump table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 			if (!strstr(insn->func->name, ".cold") &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 			    strstr(insn->jump_dest->func->name, ".cold")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 				insn->func->cfunc = insn->jump_dest->func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 				insn->jump_dest->func->pfunc = insn->func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 			} else if (insn->jump_dest->func->pfunc != insn->func->pfunc &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 				   insn->jump_dest->offset == insn->jump_dest->func->offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 				/* internal sibling call */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 				insn->call_dest = insn->jump_dest->func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 				if (insn->call_dest->static_call_tramp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 					list_add_tail(&insn->static_call_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 						      &file->static_call_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) static void remove_insn_ops(struct instruction *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 	struct stack_op *op, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 	list_for_each_entry_safe(op, tmp, &insn->stack_ops, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 		list_del(&op->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 		free(op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) static struct symbol *find_call_destination(struct section *sec, unsigned long offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 	struct symbol *call_dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 	call_dest = find_func_by_offset(sec, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 	if (!call_dest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 		call_dest = find_symbol_by_offset(sec, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 	return call_dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)  * Find the destination instructions for all calls.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) static int add_call_destinations(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 	unsigned long dest_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 	struct reloc *reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 	for_each_insn(file, insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 		if (insn->type != INSN_CALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 		reloc = find_reloc_by_dest_range(file->elf, insn->sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 					       insn->offset, insn->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 		if (!reloc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 			dest_off = arch_jump_destination(insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 			insn->call_dest = find_call_destination(insn->sec, dest_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 			if (insn->ignore)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 			if (!insn->call_dest) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 				WARN_FUNC("unannotated intra-function call", insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 				return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 			if (insn->func && insn->call_dest->type != STT_FUNC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 				WARN_FUNC("unsupported call to non-function",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 					  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 				return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 		} else if (reloc->sym->type == STT_SECTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 			dest_off = arch_dest_reloc_offset(reloc->addend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 			insn->call_dest = find_call_destination(reloc->sym->sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 								dest_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 			if (!insn->call_dest) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 				if (is_cfi_section(reloc->sym->sec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 				WARN_FUNC("can't find call dest symbol at %s+0x%lx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 					  insn->sec, insn->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 					  reloc->sym->sec->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 					  dest_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 				return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 			insn->call_dest = reloc->sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 		if (insn->call_dest && insn->call_dest->static_call_tramp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 			list_add_tail(&insn->static_call_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 				      &file->static_call_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 		 * Many compilers cannot disable KCOV with a function attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 		 * so they need a little help, NOP out any KCOV calls from noinstr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 		 * text.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 		if (insn->sec->noinstr &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 		    !strncmp(insn->call_dest->name, "__sanitizer_cov_", 16)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 			if (reloc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 				reloc->type = R_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 				elf_write_reloc(file->elf, reloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 			elf_write_insn(file->elf, insn->sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 				       insn->offset, insn->len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 				       arch_nop_insn(insn->len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 			insn->type = INSN_NOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 		if (mcount && !strcmp(insn->call_dest->name, "__fentry__")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 			if (reloc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 				reloc->type = R_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 				elf_write_reloc(file->elf, reloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 			elf_write_insn(file->elf, insn->sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 				       insn->offset, insn->len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 				       arch_nop_insn(insn->len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 			insn->type = INSN_NOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 			list_add_tail(&insn->mcount_loc_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 				      &file->mcount_loc_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 		 * Whatever stack impact regular CALLs have, should be undone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 		 * by the RETURN of the called function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 		 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 		 * Annotated intra-function calls retain the stack_ops but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 		 * are converted to JUMP, see read_intra_function_calls().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 		remove_insn_ops(insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)  * The .alternatives section requires some extra special care, over and above
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)  * what other special sections require:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)  * 1. Because alternatives are patched in-place, we need to insert a fake jump
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)  *    instruction at the end so that validate_branch() skips all the original
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)  *    replaced instructions when validating the new instruction path.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)  * 2. An added wrinkle is that the new instruction length might be zero.  In
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)  *    that case the old instructions are replaced with noops.  We simulate that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)  *    by creating a fake jump as the only new instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)  * 3. In some cases, the alternative section includes an instruction which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)  *    conditionally jumps to the _end_ of the entry.  We have to modify these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)  *    jumps' destinations to point back to .text rather than the end of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)  *    entry in .altinstr_replacement.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) static int handle_group_alt(struct objtool_file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 			    struct special_alt *special_alt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 			    struct instruction *orig_insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 			    struct instruction **new_insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 	static unsigned int alt_group_next_index = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 	struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 	unsigned int alt_group = alt_group_next_index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 	unsigned long dest_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 	last_orig_insn = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 	insn = orig_insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 	sec_for_each_insn_from(file, insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 		if (insn->offset >= special_alt->orig_off + special_alt->orig_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 		insn->alt_group = alt_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 		last_orig_insn = insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 	if (next_insn_same_sec(file, last_orig_insn)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 		fake_jump = malloc(sizeof(*fake_jump));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 		if (!fake_jump) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 			WARN("malloc failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 		memset(fake_jump, 0, sizeof(*fake_jump));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 		INIT_LIST_HEAD(&fake_jump->alts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 		INIT_LIST_HEAD(&fake_jump->stack_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 		init_cfi_state(&fake_jump->cfi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 		fake_jump->sec = special_alt->new_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 		fake_jump->offset = FAKE_JUMP_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 		fake_jump->type = INSN_JUMP_UNCONDITIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 		fake_jump->jump_dest = list_next_entry(last_orig_insn, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 		fake_jump->func = orig_insn->func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 	if (!special_alt->new_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 		if (!fake_jump) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 			WARN("%s: empty alternative at end of section",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 			     special_alt->orig_sec->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 		*new_insn = fake_jump;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 	last_new_insn = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 	alt_group = alt_group_next_index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 	insn = *new_insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 	sec_for_each_insn_from(file, insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 		struct reloc *alt_reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 		if (insn->offset >= special_alt->new_off + special_alt->new_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 		last_new_insn = insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 		insn->ignore = orig_insn->ignore_alts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 		insn->func = orig_insn->func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 		insn->alt_group = alt_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 		 * Since alternative replacement code is copy/pasted by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 		 * kernel after applying relocations, generally such code can't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 		 * have relative-address relocation references to outside the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 		 * .altinstr_replacement section, unless the arch's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 		 * alternatives code can adjust the relative offsets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 		 * accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 		alt_reloc = find_reloc_by_dest_range(file->elf, insn->sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 						   insn->offset, insn->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 		if (alt_reloc &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 		    !arch_support_alt_relocation(special_alt, insn, alt_reloc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 			WARN_FUNC("unsupported relocation in alternatives section",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 				  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 		if (!is_static_jump(insn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 		if (!insn->immediate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 		dest_off = arch_jump_destination(insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 		if (dest_off == special_alt->new_off + special_alt->new_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 			if (!fake_jump) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 				WARN("%s: alternative jump to end of section",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 				     special_alt->orig_sec->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 				return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 			insn->jump_dest = fake_jump;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 		if (!insn->jump_dest) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 			WARN_FUNC("can't find alternative jump destination",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 				  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 	if (!last_new_insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 		WARN_FUNC("can't find last new alternative instruction",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 			  special_alt->new_sec, special_alt->new_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 	if (fake_jump)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 		list_add(&fake_jump->list, &last_new_insn->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)  * A jump table entry can either convert a nop to a jump or a jump to a nop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)  * If the original instruction is a jump, make the alt entry an effective nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)  * by just skipping the original instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) static int handle_jump_alt(struct objtool_file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 			   struct special_alt *special_alt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 			   struct instruction *orig_insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 			   struct instruction **new_insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 	if (orig_insn->type == INSN_NOP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 	if (orig_insn->type != INSN_JUMP_UNCONDITIONAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 		WARN_FUNC("unsupported instruction at jump label",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 			  orig_insn->sec, orig_insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 	*new_insn = list_next_entry(orig_insn, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)  * Read all the special sections which have alternate instructions which can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)  * patched in or redirected to at runtime.  Each instruction having alternate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)  * instruction(s) has them added to its insn->alts list, which will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)  * traversed in validate_branch().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) static int add_special_section_alts(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) 	struct list_head special_alts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 	struct instruction *orig_insn, *new_insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 	struct special_alt *special_alt, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) 	struct alternative *alt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 	ret = special_get_alts(file->elf, &special_alts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) 	list_for_each_entry_safe(special_alt, tmp, &special_alts, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 		orig_insn = find_insn(file, special_alt->orig_sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 				      special_alt->orig_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 		if (!orig_insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 			WARN_FUNC("special: can't find orig instruction",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 				  special_alt->orig_sec, special_alt->orig_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 			ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 		new_insn = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 		if (!special_alt->group || special_alt->new_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 			new_insn = find_insn(file, special_alt->new_sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 					     special_alt->new_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 			if (!new_insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 				WARN_FUNC("special: can't find new instruction",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 					  special_alt->new_sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 					  special_alt->new_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 				ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 		if (special_alt->group) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 			if (!special_alt->orig_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 				WARN_FUNC("empty alternative entry",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 					  orig_insn->sec, orig_insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 			ret = handle_group_alt(file, special_alt, orig_insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 					       &new_insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 		} else if (special_alt->jump_or_nop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 			ret = handle_jump_alt(file, special_alt, orig_insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 					      &new_insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) 		alt = malloc(sizeof(*alt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 		if (!alt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 			WARN("malloc failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 			ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) 		alt->insn = new_insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) 		alt->skip_orig = special_alt->skip_orig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 		orig_insn->ignore_alts |= special_alt->skip_alt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 		list_add_tail(&alt->list, &orig_insn->alts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 		list_del(&special_alt->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) 		free(special_alt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) static int add_jump_table(struct objtool_file *file, struct instruction *insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) 			    struct reloc *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 	struct reloc *reloc = table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 	struct instruction *dest_insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) 	struct alternative *alt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 	struct symbol *pfunc = insn->func->pfunc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 	unsigned int prev_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) 	 * Each @reloc is a switch table relocation which points to the target
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) 	 * instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 	list_for_each_entry_from(reloc, &table->sec->reloc_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 		/* Check for the end of the table: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 		if (reloc != table && reloc->jump_table_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 		/* Make sure the table entries are consecutive: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 		if (prev_offset && reloc->offset != prev_offset + 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) 		/* Detect function pointers from contiguous objects: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) 		if (reloc->sym->sec == pfunc->sec &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) 		    reloc->addend == pfunc->offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 		dest_insn = find_insn(file, reloc->sym->sec, reloc->addend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) 		if (!dest_insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 		/* Make sure the destination is in the same function: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 		if (!dest_insn->func || dest_insn->func->pfunc != pfunc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 		alt = malloc(sizeof(*alt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) 		if (!alt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 			WARN("malloc failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) 		alt->insn = dest_insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) 		list_add_tail(&alt->list, &insn->alts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 		prev_offset = reloc->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 	if (!prev_offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 		WARN_FUNC("can't find switch jump table",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 			  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)  * find_jump_table() - Given a dynamic jump, find the switch jump table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417)  * associated with it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) static struct reloc *find_jump_table(struct objtool_file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) 				      struct symbol *func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) 				      struct instruction *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) 	struct reloc *table_reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) 	struct instruction *dest_insn, *orig_insn = insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) 	 * Backward search using the @first_jump_src links, these help avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 	 * much of the 'in between' code. Which avoids us getting confused by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 	 * it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 	for (;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 	     insn && insn->func && insn->func->pfunc == func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 	     insn = insn->first_jump_src ?: prev_insn_same_sym(file, insn)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 		if (insn != orig_insn && insn->type == INSN_JUMP_DYNAMIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) 		/* allow small jumps within the range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 		if (insn->type == INSN_JUMP_UNCONDITIONAL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) 		    insn->jump_dest &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 		    (insn->jump_dest->offset <= insn->offset ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) 		     insn->jump_dest->offset > orig_insn->offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) 		    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) 		table_reloc = arch_find_switch_table(file, insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 		if (!table_reloc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 		dest_insn = find_insn(file, table_reloc->sym->sec, table_reloc->addend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 		if (!dest_insn || !dest_insn->func || dest_insn->func->pfunc != func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) 		return table_reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)  * First pass: Mark the head of each jump table so that in the next pass,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460)  * we know when a given jump table ends and the next one starts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) static void mark_func_jump_tables(struct objtool_file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) 				    struct symbol *func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) 	struct instruction *insn, *last = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) 	struct reloc *reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) 	func_for_each_insn(file, func, insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) 		if (!last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) 			last = insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) 		 * Store back-pointers for unconditional forward jumps such
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) 		 * that find_jump_table() can back-track using those and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) 		 * avoid some potentially confusing code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) 		if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) 		    insn->offset > last->offset &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) 		    insn->jump_dest->offset > insn->offset &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) 		    !insn->jump_dest->first_jump_src) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) 			insn->jump_dest->first_jump_src = insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) 			last = insn->jump_dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) 		if (insn->type != INSN_JUMP_DYNAMIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) 		reloc = find_jump_table(file, func, insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) 		if (reloc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) 			reloc->jump_table_start = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) 			insn->jump_table = reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) static int add_func_jump_tables(struct objtool_file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) 				  struct symbol *func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) 	func_for_each_insn(file, func, insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) 		if (!insn->jump_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) 		ret = add_jump_table(file, insn, insn->jump_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516)  * For some switch statements, gcc generates a jump table in the .rodata
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)  * section which contains a list of addresses within the function to jump to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518)  * This finds these jump tables and adds them to the insn->alts lists.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) static int add_jump_table_alts(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) 	struct section *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) 	struct symbol *func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) 	if (!file->rodata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) 	for_each_sec(file, sec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) 		list_for_each_entry(func, &sec->symbol_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) 			if (func->type != STT_FUNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) 			mark_func_jump_tables(file, func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) 			ret = add_func_jump_tables(file, func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) 				return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) static int read_unwind_hints(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) 	struct section *sec, *relocsec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) 	struct reloc *reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) 	struct unwind_hint *hint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) 	struct cfi_reg *cfa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) 	sec = find_section_by_name(file->elf, ".discard.unwind_hints");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) 	if (!sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) 	relocsec = sec->reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) 	if (!relocsec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) 		WARN("missing .rela.discard.unwind_hints section");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) 	if (sec->len % sizeof(struct unwind_hint)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) 		WARN("struct unwind_hint size mismatch");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) 	file->hints = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) 	for (i = 0; i < sec->len / sizeof(struct unwind_hint); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) 		hint = (struct unwind_hint *)sec->data->d_buf + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) 		reloc = find_reloc_by_dest(file->elf, sec, i * sizeof(*hint));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) 		if (!reloc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) 			WARN("can't find reloc for unwind_hints[%d]", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) 		insn = find_insn(file, reloc->sym->sec, reloc->addend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) 		if (!insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) 			WARN("can't find insn for unwind_hints[%d]", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) 		cfa = &insn->cfi.cfa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) 		if (hint->type == UNWIND_HINT_TYPE_RET_OFFSET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) 			insn->ret_offset = hint->sp_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) 		insn->hint = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) 		if (arch_decode_hint_reg(insn, hint->sp_reg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) 			WARN_FUNC("unsupported unwind_hint sp base reg %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) 				  insn->sec, insn->offset, hint->sp_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) 		cfa->offset = hint->sp_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) 		insn->cfi.type = hint->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) 		insn->cfi.end = hint->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) static int read_retpoline_hints(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) 	struct section *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) 	struct reloc *reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) 	sec = find_section_by_name(file->elf, ".rela.discard.retpoline_safe");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) 	if (!sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) 	list_for_each_entry(reloc, &sec->reloc_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) 		if (reloc->sym->type != STT_SECTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) 			WARN("unexpected relocation symbol type in %s", sec->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) 		insn = find_insn(file, reloc->sym->sec, reloc->addend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) 		if (!insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) 			WARN("bad .discard.retpoline_safe entry");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) 		if (insn->type != INSN_JUMP_DYNAMIC &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) 		    insn->type != INSN_CALL_DYNAMIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) 			WARN_FUNC("retpoline_safe hint not an indirect jump/call",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) 				  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) 		insn->retpoline_safe = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) static int read_instr_hints(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) 	struct section *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) 	struct reloc *reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) 	sec = find_section_by_name(file->elf, ".rela.discard.instr_end");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) 	if (!sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) 	list_for_each_entry(reloc, &sec->reloc_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) 		if (reloc->sym->type != STT_SECTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) 			WARN("unexpected relocation symbol type in %s", sec->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) 		insn = find_insn(file, reloc->sym->sec, reloc->addend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) 		if (!insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) 			WARN("bad .discard.instr_end entry");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) 		insn->instr--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) 	sec = find_section_by_name(file->elf, ".rela.discard.instr_begin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) 	if (!sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) 	list_for_each_entry(reloc, &sec->reloc_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) 		if (reloc->sym->type != STT_SECTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) 			WARN("unexpected relocation symbol type in %s", sec->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) 		insn = find_insn(file, reloc->sym->sec, reloc->addend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) 		if (!insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) 			WARN("bad .discard.instr_begin entry");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) 		insn->instr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) static int read_intra_function_calls(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) 	struct section *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) 	struct reloc *reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) 	sec = find_section_by_name(file->elf, ".rela.discard.intra_function_calls");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) 	if (!sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) 	list_for_each_entry(reloc, &sec->reloc_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) 		unsigned long dest_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) 		if (reloc->sym->type != STT_SECTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) 			WARN("unexpected relocation symbol type in %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) 			     sec->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) 		insn = find_insn(file, reloc->sym->sec, reloc->addend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) 		if (!insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) 			WARN("bad .discard.intra_function_call entry");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) 		if (insn->type != INSN_CALL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) 			WARN_FUNC("intra_function_call not a direct call",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) 				  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) 		 * Treat intra-function CALLs as JMPs, but with a stack_op.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) 		 * See add_call_destinations(), which strips stack_ops from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) 		 * normal CALLs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) 		insn->type = INSN_JUMP_UNCONDITIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) 		dest_off = insn->offset + insn->len + insn->immediate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) 		insn->jump_dest = find_insn(file, insn->sec, dest_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) 		if (!insn->jump_dest) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) 			WARN_FUNC("can't find call dest at %s+0x%lx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) 				  insn->sec, insn->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) 				  insn->sec->name, dest_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) static int read_static_call_tramps(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) 	struct section *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) 	struct symbol *func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) 	for_each_sec(file, sec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) 		list_for_each_entry(func, &sec->symbol_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) 			if (func->bind == STB_GLOBAL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) 			    !strncmp(func->name, STATIC_CALL_TRAMP_PREFIX_STR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) 				     strlen(STATIC_CALL_TRAMP_PREFIX_STR)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) 				func->static_call_tramp = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) static void mark_rodata(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) 	struct section *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) 	bool found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) 	 * Search for the following rodata sections, each of which can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) 	 * potentially contain jump tables:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) 	 * - .rodata: can contain GCC switch tables
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) 	 * - .rodata.<func>: same, if -fdata-sections is being used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) 	 * - .rodata..c_jump_table: contains C annotated jump tables
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) 	 * .rodata.str1.* sections are ignored; they don't contain jump tables.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) 	for_each_sec(file, sec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) 		if (!strncmp(sec->name, ".rodata", 7) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) 		    !strstr(sec->name, ".str1.")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) 			sec->rodata = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) 			found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) 	file->rodata = found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) static int decode_sections(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) 	mark_rodata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) 	ret = decode_instructions(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) 	ret = add_dead_ends(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) 	add_ignores(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) 	add_uaccess_safe(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) 	add_cfi_jumptables(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) 	ret = add_ignore_alternatives(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) 	 * Must be before add_{jump_call}_destination.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) 	ret = read_static_call_tramps(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) 	ret = add_jump_destinations(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) 	ret = add_special_section_alts(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) 	 * Must be before add_call_destination(); it changes INSN_CALL to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) 	 * INSN_JUMP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) 	ret = read_intra_function_calls(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) 	ret = add_call_destinations(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) 	ret = add_jump_table_alts(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) 	ret = read_unwind_hints(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) 	ret = read_retpoline_hints(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) 	ret = read_instr_hints(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) static bool is_fentry_call(struct instruction *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) 	if (insn->type == INSN_CALL && insn->call_dest &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) 	    insn->call_dest->type == STT_NOTYPE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) 	    !strcmp(insn->call_dest->name, "__fentry__"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) 	return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) static bool has_modified_stack_frame(struct instruction *insn, struct insn_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) 	u8 ret_offset = insn->ret_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) 	struct cfi_state *cfi = &state->cfi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) 	if (cfi->cfa.base != initial_func_cfi.cfa.base || cfi->drap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) 	if (cfi->cfa.offset != initial_func_cfi.cfa.offset + ret_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) 	if (cfi->stack_size != initial_func_cfi.cfa.offset + ret_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) 	 * If there is a ret offset hint then don't check registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) 	 * because a callee-saved register might have been pushed on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) 	 * the stack.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) 	if (ret_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) 	for (i = 0; i < CFI_NUM_REGS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) 		if (cfi->regs[i].base != initial_func_cfi.regs[i].base ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) 		    cfi->regs[i].offset != initial_func_cfi.regs[i].offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) 			return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) 	return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) static bool has_valid_stack_frame(struct insn_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) 	struct cfi_state *cfi = &state->cfi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) 	if (cfi->cfa.base == CFI_BP && cfi->regs[CFI_BP].base == CFI_CFA &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) 	    cfi->regs[CFI_BP].offset == -16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) 	if (cfi->drap && cfi->regs[CFI_BP].base == CFI_BP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) 	return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) static int update_cfi_state_regs(struct instruction *insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) 				  struct cfi_state *cfi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) 				  struct stack_op *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) 	struct cfi_reg *cfa = &cfi->cfa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) 	if (cfa->base != CFI_SP && cfa->base != CFI_SP_INDIRECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) 	/* push */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) 	if (op->dest.type == OP_DEST_PUSH || op->dest.type == OP_DEST_PUSHF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) 		cfa->offset += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) 	/* pop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) 	if (op->src.type == OP_SRC_POP || op->src.type == OP_SRC_POPF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) 		cfa->offset -= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) 	/* add immediate to sp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) 	if (op->dest.type == OP_DEST_REG && op->src.type == OP_SRC_ADD &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) 	    op->dest.reg == CFI_SP && op->src.reg == CFI_SP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) 		cfa->offset -= op->src.offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) static void save_reg(struct cfi_state *cfi, unsigned char reg, int base, int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) 	if (arch_callee_saved_reg(reg) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) 	    cfi->regs[reg].base == CFI_UNDEFINED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) 		cfi->regs[reg].base = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) 		cfi->regs[reg].offset = offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) static void restore_reg(struct cfi_state *cfi, unsigned char reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) 	cfi->regs[reg].base = initial_func_cfi.regs[reg].base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) 	cfi->regs[reg].offset = initial_func_cfi.regs[reg].offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949)  * A note about DRAP stack alignment:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951)  * GCC has the concept of a DRAP register, which is used to help keep track of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952)  * the stack pointer when aligning the stack.  r10 or r13 is used as the DRAP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953)  * register.  The typical DRAP pattern is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955)  *   4c 8d 54 24 08		lea    0x8(%rsp),%r10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956)  *   48 83 e4 c0		and    $0xffffffffffffffc0,%rsp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957)  *   41 ff 72 f8		pushq  -0x8(%r10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958)  *   55				push   %rbp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959)  *   48 89 e5			mov    %rsp,%rbp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960)  *				(more pushes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961)  *   41 52			push   %r10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962)  *				...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963)  *   41 5a			pop    %r10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964)  *				(more pops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965)  *   5d				pop    %rbp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966)  *   49 8d 62 f8		lea    -0x8(%r10),%rsp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967)  *   c3				retq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969)  * There are some variations in the epilogues, like:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971)  *   5b				pop    %rbx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972)  *   41 5a			pop    %r10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973)  *   41 5c			pop    %r12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974)  *   41 5d			pop    %r13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975)  *   41 5e			pop    %r14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976)  *   c9				leaveq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977)  *   49 8d 62 f8		lea    -0x8(%r10),%rsp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978)  *   c3				retq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980)  * and:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982)  *   4c 8b 55 e8		mov    -0x18(%rbp),%r10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983)  *   48 8b 5d e0		mov    -0x20(%rbp),%rbx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984)  *   4c 8b 65 f0		mov    -0x10(%rbp),%r12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985)  *   4c 8b 6d f8		mov    -0x8(%rbp),%r13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986)  *   c9				leaveq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987)  *   49 8d 62 f8		lea    -0x8(%r10),%rsp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988)  *   c3				retq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990)  * Sometimes r13 is used as the DRAP register, in which case it's saved and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991)  * restored beforehand:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993)  *   41 55			push   %r13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994)  *   4c 8d 6c 24 10		lea    0x10(%rsp),%r13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995)  *   48 83 e4 f0		and    $0xfffffffffffffff0,%rsp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996)  *				...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997)  *   49 8d 65 f0		lea    -0x10(%r13),%rsp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998)  *   41 5d			pop    %r13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999)  *   c3				retq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) static int update_cfi_state(struct instruction *insn, struct cfi_state *cfi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) 			     struct stack_op *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) 	struct cfi_reg *cfa = &cfi->cfa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) 	struct cfi_reg *regs = cfi->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) 	/* stack operations don't make sense with an undefined CFA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) 	if (cfa->base == CFI_UNDEFINED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) 		if (insn->func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) 			WARN_FUNC("undefined stack state", insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) 	if (cfi->type == UNWIND_HINT_TYPE_REGS ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) 	    cfi->type == UNWIND_HINT_TYPE_REGS_PARTIAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) 		return update_cfi_state_regs(insn, cfi, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) 	switch (op->dest.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) 	case OP_DEST_REG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) 		switch (op->src.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) 		case OP_SRC_REG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) 			if (op->src.reg == CFI_SP && op->dest.reg == CFI_BP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) 			    cfa->base == CFI_SP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) 			    regs[CFI_BP].base == CFI_CFA &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) 			    regs[CFI_BP].offset == -cfa->offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) 				/* mov %rsp, %rbp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) 				cfa->base = op->dest.reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) 				cfi->bp_scratch = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) 			else if (op->src.reg == CFI_SP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) 				 op->dest.reg == CFI_BP && cfi->drap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) 				/* drap: mov %rsp, %rbp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) 				regs[CFI_BP].base = CFI_BP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) 				regs[CFI_BP].offset = -cfi->stack_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) 				cfi->bp_scratch = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) 			else if (op->src.reg == CFI_SP && cfa->base == CFI_SP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) 				 * mov %rsp, %reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) 				 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) 				 * This is needed for the rare case where GCC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) 				 * does:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) 				 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) 				 *   mov    %rsp, %rax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) 				 *   ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) 				 *   mov    %rax, %rsp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) 				cfi->vals[op->dest.reg].base = CFI_CFA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) 				cfi->vals[op->dest.reg].offset = -cfi->stack_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) 			else if (op->src.reg == CFI_BP && op->dest.reg == CFI_SP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) 				 cfa->base == CFI_BP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) 				 * mov %rbp, %rsp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) 				 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) 				 * Restore the original stack pointer (Clang).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) 				cfi->stack_size = -cfi->regs[CFI_BP].offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) 			else if (op->dest.reg == cfa->base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) 				/* mov %reg, %rsp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) 				if (cfa->base == CFI_SP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) 				    cfi->vals[op->src.reg].base == CFI_CFA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) 					/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) 					 * This is needed for the rare case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) 					 * where GCC does something dumb like:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) 					 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) 					 *   lea    0x8(%rsp), %rcx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) 					 *   ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) 					 *   mov    %rcx, %rsp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) 					 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) 					cfa->offset = -cfi->vals[op->src.reg].offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) 					cfi->stack_size = cfa->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) 				} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) 					cfa->base = CFI_UNDEFINED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) 					cfa->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) 		case OP_SRC_ADD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) 			if (op->dest.reg == CFI_SP && op->src.reg == CFI_SP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) 				/* add imm, %rsp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) 				cfi->stack_size -= op->src.offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) 				if (cfa->base == CFI_SP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) 					cfa->offset -= op->src.offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) 			if (op->dest.reg == CFI_SP && op->src.reg == CFI_BP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) 				/* lea disp(%rbp), %rsp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) 				cfi->stack_size = -(op->src.offset + regs[CFI_BP].offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) 			if (op->src.reg == CFI_SP && cfa->base == CFI_SP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) 				/* drap: lea disp(%rsp), %drap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) 				cfi->drap_reg = op->dest.reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) 				 * lea disp(%rsp), %reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) 				 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) 				 * This is needed for the rare case where GCC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) 				 * does something dumb like:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) 				 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) 				 *   lea    0x8(%rsp), %rcx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) 				 *   ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) 				 *   mov    %rcx, %rsp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) 				cfi->vals[op->dest.reg].base = CFI_CFA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) 				cfi->vals[op->dest.reg].offset = \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) 					-cfi->stack_size + op->src.offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) 			if (cfi->drap && op->dest.reg == CFI_SP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) 			    op->src.reg == cfi->drap_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) 				 /* drap: lea disp(%drap), %rsp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) 				cfa->base = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) 				cfa->offset = cfi->stack_size = -op->src.offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) 				cfi->drap_reg = CFI_UNDEFINED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) 				cfi->drap = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) 			if (op->dest.reg == cfi->cfa.base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) 				WARN_FUNC("unsupported stack register modification",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) 					  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) 				return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) 		case OP_SRC_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) 			if (op->dest.reg != CFI_SP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) 			    (cfi->drap_reg != CFI_UNDEFINED && cfa->base != CFI_SP) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) 			    (cfi->drap_reg == CFI_UNDEFINED && cfa->base != CFI_BP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) 				WARN_FUNC("unsupported stack pointer realignment",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) 					  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) 				return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) 			if (cfi->drap_reg != CFI_UNDEFINED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) 				/* drap: and imm, %rsp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) 				cfa->base = cfi->drap_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) 				cfa->offset = cfi->stack_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) 				cfi->drap = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) 			 * Older versions of GCC (4.8ish) realign the stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) 			 * without DRAP, with a frame pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) 		case OP_SRC_POP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) 		case OP_SRC_POPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) 			if (!cfi->drap && op->dest.reg == cfa->base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) 				/* pop %rbp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) 				cfa->base = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) 			if (cfi->drap && cfa->base == CFI_BP_INDIRECT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) 			    op->dest.reg == cfi->drap_reg &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) 			    cfi->drap_offset == -cfi->stack_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) 				/* drap: pop %drap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) 				cfa->base = cfi->drap_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) 				cfa->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) 				cfi->drap_offset = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) 			} else if (regs[op->dest.reg].offset == -cfi->stack_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) 				/* pop %reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) 				restore_reg(cfi, op->dest.reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) 			cfi->stack_size -= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) 			if (cfa->base == CFI_SP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) 				cfa->offset -= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) 		case OP_SRC_REG_INDIRECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) 			if (cfi->drap && op->src.reg == CFI_BP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) 			    op->src.offset == cfi->drap_offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) 				/* drap: mov disp(%rbp), %drap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) 				cfa->base = cfi->drap_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) 				cfa->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) 				cfi->drap_offset = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) 			if (cfi->drap && op->src.reg == CFI_BP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) 			    op->src.offset == regs[op->dest.reg].offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) 				/* drap: mov disp(%rbp), %reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) 				restore_reg(cfi, op->dest.reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) 			} else if (op->src.reg == cfa->base &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) 			    op->src.offset == regs[op->dest.reg].offset + cfa->offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) 				/* mov disp(%rbp), %reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) 				/* mov disp(%rsp), %reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) 				restore_reg(cfi, op->dest.reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) 			WARN_FUNC("unknown stack-related instruction",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) 				  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) 	case OP_DEST_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) 	case OP_DEST_PUSHF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) 		cfi->stack_size += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) 		if (cfa->base == CFI_SP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) 			cfa->offset += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) 		if (op->src.type != OP_SRC_REG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) 		if (cfi->drap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) 			if (op->src.reg == cfa->base && op->src.reg == cfi->drap_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) 				/* drap: push %drap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) 				cfa->base = CFI_BP_INDIRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) 				cfa->offset = -cfi->stack_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) 				/* save drap so we know when to restore it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) 				cfi->drap_offset = -cfi->stack_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) 			} else if (op->src.reg == CFI_BP && cfa->base == cfi->drap_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) 				/* drap: push %rbp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) 				cfi->stack_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) 				/* drap: push %reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) 				save_reg(cfi, op->src.reg, CFI_BP, -cfi->stack_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) 			/* push %reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) 			save_reg(cfi, op->src.reg, CFI_CFA, -cfi->stack_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) 		/* detect when asm code uses rbp as a scratch register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) 		if (!no_fp && insn->func && op->src.reg == CFI_BP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) 		    cfa->base != CFI_BP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) 			cfi->bp_scratch = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) 	case OP_DEST_REG_INDIRECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) 		if (cfi->drap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) 			if (op->src.reg == cfa->base && op->src.reg == cfi->drap_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) 				/* drap: mov %drap, disp(%rbp) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) 				cfa->base = CFI_BP_INDIRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) 				cfa->offset = op->dest.offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) 				/* save drap offset so we know when to restore it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) 				cfi->drap_offset = op->dest.offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) 				/* drap: mov reg, disp(%rbp) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) 				save_reg(cfi, op->src.reg, CFI_BP, op->dest.offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) 		} else if (op->dest.reg == cfa->base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) 			/* mov reg, disp(%rbp) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) 			/* mov reg, disp(%rsp) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) 			save_reg(cfi, op->src.reg, CFI_CFA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) 				 op->dest.offset - cfi->cfa.offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) 	case OP_DEST_LEAVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) 		if ((!cfi->drap && cfa->base != CFI_BP) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) 		    (cfi->drap && cfa->base != cfi->drap_reg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) 			WARN_FUNC("leave instruction with modified stack frame",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) 				  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) 		/* leave (mov %rbp, %rsp; pop %rbp) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) 		cfi->stack_size = -cfi->regs[CFI_BP].offset - 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) 		restore_reg(cfi, CFI_BP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) 		if (!cfi->drap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) 			cfa->base = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) 			cfa->offset -= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) 	case OP_DEST_MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) 		if (op->src.type != OP_SRC_POP && op->src.type != OP_SRC_POPF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) 			WARN_FUNC("unknown stack-related memory operation",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) 				  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) 		/* pop mem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) 		cfi->stack_size -= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) 		if (cfa->base == CFI_SP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) 			cfa->offset -= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) 		WARN_FUNC("unknown stack-related instruction",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) 			  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) static int handle_insn_ops(struct instruction *insn, struct insn_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) 	struct stack_op *op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) 	list_for_each_entry(op, &insn->stack_ops, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) 		struct cfi_state old_cfi = state->cfi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) 		int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) 		res = update_cfi_state(insn, &state->cfi, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) 		if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) 			return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) 		if (insn->alt_group && memcmp(&state->cfi, &old_cfi, sizeof(struct cfi_state))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) 			WARN_FUNC("alternative modifies stack", insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) 		if (op->dest.type == OP_DEST_PUSHF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) 			if (!state->uaccess_stack) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) 				state->uaccess_stack = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) 			} else if (state->uaccess_stack >> 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) 				WARN_FUNC("PUSHF stack exhausted",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) 					  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) 				return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) 			state->uaccess_stack <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) 			state->uaccess_stack  |= state->uaccess;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) 		if (op->src.type == OP_SRC_POPF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) 			if (state->uaccess_stack) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) 				state->uaccess = state->uaccess_stack & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) 				state->uaccess_stack >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) 				if (state->uaccess_stack == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) 					state->uaccess_stack = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) static bool insn_cfi_match(struct instruction *insn, struct cfi_state *cfi2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) 	struct cfi_state *cfi1 = &insn->cfi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) 	if (memcmp(&cfi1->cfa, &cfi2->cfa, sizeof(cfi1->cfa))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) 		WARN_FUNC("stack state mismatch: cfa1=%d%+d cfa2=%d%+d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) 			  insn->sec, insn->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) 			  cfi1->cfa.base, cfi1->cfa.offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) 			  cfi2->cfa.base, cfi2->cfa.offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) 	} else if (memcmp(&cfi1->regs, &cfi2->regs, sizeof(cfi1->regs))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) 		for (i = 0; i < CFI_NUM_REGS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) 			if (!memcmp(&cfi1->regs[i], &cfi2->regs[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) 				    sizeof(struct cfi_reg)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) 			WARN_FUNC("stack state mismatch: reg1[%d]=%d%+d reg2[%d]=%d%+d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) 				  insn->sec, insn->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) 				  i, cfi1->regs[i].base, cfi1->regs[i].offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) 				  i, cfi2->regs[i].base, cfi2->regs[i].offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) 	} else if (cfi1->type != cfi2->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) 		WARN_FUNC("stack state mismatch: type1=%d type2=%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) 			  insn->sec, insn->offset, cfi1->type, cfi2->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) 	} else if (cfi1->drap != cfi2->drap ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) 		   (cfi1->drap && cfi1->drap_reg != cfi2->drap_reg) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) 		   (cfi1->drap && cfi1->drap_offset != cfi2->drap_offset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) 		WARN_FUNC("stack state mismatch: drap1=%d(%d,%d) drap2=%d(%d,%d)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) 			  insn->sec, insn->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) 			  cfi1->drap, cfi1->drap_reg, cfi1->drap_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) 			  cfi2->drap, cfi2->drap_reg, cfi2->drap_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) 	return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) static inline bool func_uaccess_safe(struct symbol *func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) 	if (func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) 		return func->uaccess_safe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) 	return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) static inline const char *call_dest_name(struct instruction *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) 	if (insn->call_dest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) 		return insn->call_dest->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) 	return "{dynamic}";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) static inline bool noinstr_call_dest(struct symbol *func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) 	 * We can't deal with indirect function calls at present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) 	 * assume they're instrumented.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) 	if (!func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) 	 * If the symbol is from a noinstr section; we good.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) 	if (func->sec->noinstr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) 	 * The __ubsan_handle_*() calls are like WARN(), they only happen when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) 	 * something 'BAD' happened. At the risk of taking the machine down,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) 	 * let them proceed to get the message out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) 	if (!strncmp(func->name, "__ubsan_handle_", 15))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) 	return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) static int validate_call(struct instruction *insn, struct insn_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) 	if (state->noinstr && state->instr <= 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) 	    !noinstr_call_dest(insn->call_dest)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) 		WARN_FUNC("call to %s() leaves .noinstr.text section",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) 				insn->sec, insn->offset, call_dest_name(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) 	if (state->uaccess && !func_uaccess_safe(insn->call_dest)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) 		WARN_FUNC("call to %s() with UACCESS enabled",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) 				insn->sec, insn->offset, call_dest_name(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) 	if (state->df) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) 		WARN_FUNC("call to %s() with DF set",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) 				insn->sec, insn->offset, call_dest_name(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) static int validate_sibling_call(struct instruction *insn, struct insn_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) 	if (has_modified_stack_frame(insn, state)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) 		WARN_FUNC("sibling call from callable instruction with modified stack frame",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) 				insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) 	return validate_call(insn, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) static int validate_return(struct symbol *func, struct instruction *insn, struct insn_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) 	if (state->noinstr && state->instr > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) 		WARN_FUNC("return with instrumentation enabled",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) 			  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) 	if (state->uaccess && !func_uaccess_safe(func)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) 		WARN_FUNC("return with UACCESS enabled",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) 			  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) 	if (!state->uaccess && func_uaccess_safe(func)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) 		WARN_FUNC("return with UACCESS disabled from a UACCESS-safe function",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) 			  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) 	if (state->df) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) 		WARN_FUNC("return with DF set",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) 			  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) 	if (func && has_modified_stack_frame(insn, state)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) 		WARN_FUNC("return with modified stack frame",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) 			  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) 	if (state->cfi.bp_scratch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) 		WARN_FUNC("BP used as a scratch register",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) 			  insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559)  * Alternatives should not contain any ORC entries, this in turn means they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560)  * should not contain any CFI ops, which implies all instructions should have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561)  * the same same CFI state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563)  * It is possible to constuct alternatives that have unreachable holes that go
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564)  * unreported (because they're NOPs), such holes would result in CFI_UNDEFINED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565)  * states which then results in ORC entries, which we just said we didn't want.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567)  * Avoid them by copying the CFI entry of the first instruction into the whole
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568)  * alternative.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) static void fill_alternative_cfi(struct objtool_file *file, struct instruction *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) 	struct instruction *first_insn = insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) 	int alt_group = insn->alt_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) 	sec_for_each_insn_continue(file, insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) 		if (insn->alt_group != alt_group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) 		insn->cfi = first_insn->cfi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583)  * Follow the branch starting at the given instruction, and recursively follow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584)  * any other branches (jumps).  Meanwhile, track the frame pointer state at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585)  * each instruction and validate all the rules described in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586)  * tools/objtool/Documentation/stack-validation.txt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) static int validate_branch(struct objtool_file *file, struct symbol *func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) 			   struct instruction *insn, struct insn_state state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) 	struct alternative *alt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) 	struct instruction *next_insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) 	struct section *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) 	u8 visited;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) 	sec = insn->sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) 	while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) 		next_insn = next_insn_same_sec(file, insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) 		if (file->c_file && func && insn->func && func != insn->func->pfunc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) 			WARN("%s() falls through to next function %s()",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) 			     func->name, insn->func->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) 			return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) 		if (func && insn->ignore) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) 			WARN_FUNC("BUG: why am I validating an ignored function?",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) 				  sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) 			return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) 		visited = 1 << state.uaccess;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) 		if (insn->visited) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) 			if (!insn->hint && !insn_cfi_match(insn, &state.cfi))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) 				return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) 			if (insn->visited & visited)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) 		if (state.noinstr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) 			state.instr += insn->instr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) 		if (insn->hint)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) 			state.cfi = insn->cfi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) 			insn->cfi = state.cfi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) 		insn->visited |= visited;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) 		if (!insn->ignore_alts && !list_empty(&insn->alts)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) 			bool skip_orig = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) 			list_for_each_entry(alt, &insn->alts, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) 				if (alt->skip_orig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) 					skip_orig = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) 				ret = validate_branch(file, func, alt->insn, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) 				if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) 					if (backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) 						BT_FUNC("(alt)", insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) 					return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) 			if (insn->alt_group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) 				fill_alternative_cfi(file, insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) 			if (skip_orig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) 		if (handle_insn_ops(insn, &state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) 			return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) 		switch (insn->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) 		case INSN_RETURN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) 			return validate_return(func, insn, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) 		case INSN_CALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) 		case INSN_CALL_DYNAMIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) 			ret = validate_call(insn, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) 				return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) 			if (!no_fp && func && !is_fentry_call(insn) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) 			    !has_valid_stack_frame(&state)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) 				WARN_FUNC("call without frame pointer save/setup",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) 					  sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) 				return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) 			if (dead_end_function(file, insn->call_dest))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) 		case INSN_JUMP_CONDITIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) 		case INSN_JUMP_UNCONDITIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) 			if (func && is_sibling_call(insn)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) 				ret = validate_sibling_call(insn, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) 				if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) 					return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) 			} else if (insn->jump_dest) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) 				ret = validate_branch(file, func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) 						      insn->jump_dest, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) 				if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) 					if (backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) 						BT_FUNC("(branch)", insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) 					return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) 			if (insn->type == INSN_JUMP_UNCONDITIONAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) 		case INSN_JUMP_DYNAMIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) 		case INSN_JUMP_DYNAMIC_CONDITIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) 			if (func && is_sibling_call(insn)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) 				ret = validate_sibling_call(insn, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) 				if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) 					return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) 			if (insn->type == INSN_JUMP_DYNAMIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) 		case INSN_CONTEXT_SWITCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) 			if (func && (!next_insn || !next_insn->hint)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) 				WARN_FUNC("unsupported instruction in callable function",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) 					  sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) 				return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) 		case INSN_STAC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) 			if (state.uaccess) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) 				WARN_FUNC("recursive UACCESS enable", sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) 				return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) 			state.uaccess = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) 		case INSN_CLAC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) 			if (!state.uaccess && func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) 				WARN_FUNC("redundant UACCESS disable", sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) 				return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) 			if (func_uaccess_safe(func) && !state.uaccess_stack) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) 				WARN_FUNC("UACCESS-safe disables UACCESS", sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) 				return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) 			state.uaccess = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) 		case INSN_STD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) 			if (state.df) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) 				WARN_FUNC("recursive STD", sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) 				return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) 			state.df = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) 		case INSN_CLD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) 			if (!state.df && func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) 				WARN_FUNC("redundant CLD", sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) 				return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) 			state.df = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) 		if (insn->dead_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) 		if (!next_insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) 			if (state.cfi.cfa.base == CFI_UNDEFINED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) 			WARN("%s: unexpected end of section", sec->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) 			return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) 		insn = next_insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) static int validate_unwind_hints(struct objtool_file *file, struct section *sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) 	struct insn_state state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) 	int ret, warnings = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) 	if (!file->hints)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) 	init_insn_state(&state, sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) 	if (sec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) 		insn = find_insn(file, sec, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) 		if (!insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) 		insn = list_first_entry(&file->insn_list, typeof(*insn), list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) 	while (&insn->list != &file->insn_list && (!sec || insn->sec == sec)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) 		if (insn->hint && !insn->visited) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) 			ret = validate_branch(file, insn->func, insn, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) 			if (ret && backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) 				BT_FUNC("<=== (hint)", insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) 			warnings += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) 		insn = list_next_entry(insn, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) 	return warnings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) static int validate_retpoline(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) 	int warnings = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) 	for_each_insn(file, insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) 		if (insn->type != INSN_JUMP_DYNAMIC &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) 		    insn->type != INSN_CALL_DYNAMIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) 		if (insn->retpoline_safe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) 		 * .init.text code is ran before userspace and thus doesn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) 		 * strictly need retpolines, except for modules which are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) 		 * loaded late, they very much do need retpoline in their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) 		 * .init.text
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) 		if (!strcmp(insn->sec->name, ".init.text") && !module)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) 		WARN_FUNC("indirect %s found in RETPOLINE build",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) 			  insn->sec, insn->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) 			  insn->type == INSN_JUMP_DYNAMIC ? "jump" : "call");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) 		warnings++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) 	return warnings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) static bool is_kasan_insn(struct instruction *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) 	return (insn->type == INSN_CALL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) 		!strcmp(insn->call_dest->name, "__asan_handle_no_return"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) static bool is_ubsan_insn(struct instruction *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) 	return (insn->type == INSN_CALL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) 		!strcmp(insn->call_dest->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) 			"__ubsan_handle_builtin_unreachable"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) static bool ignore_unreachable_insn(struct objtool_file *file, struct instruction *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) 	struct instruction *prev_insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) 	if (insn->ignore || insn->type == INSN_NOP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) 	 * Ignore any unused exceptions.  This can happen when a whitelisted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) 	 * function has an exception table entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) 	 * Also ignore alternative replacement instructions.  This can happen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) 	 * when a whitelisted function uses one of the ALTERNATIVE macros.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) 	if (!strcmp(insn->sec->name, ".fixup") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) 	    !strcmp(insn->sec->name, ".altinstr_replacement") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) 	    !strcmp(insn->sec->name, ".altinstr_aux"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) 	if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->offset == FAKE_JUMP_OFFSET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) 	if (!insn->func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) 	 * CONFIG_UBSAN_TRAP inserts a UD2 when it sees
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) 	 * __builtin_unreachable().  The BUG() macro has an unreachable() after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) 	 * the UD2, which causes GCC's undefined trap logic to emit another UD2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) 	 * (or occasionally a JMP to UD2).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) 	 * It may also insert a UD2 after calling a __noreturn function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) 	prev_insn = list_prev_entry(insn, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) 	if ((prev_insn->dead_end || dead_end_function(file, prev_insn->call_dest)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) 	    (insn->type == INSN_BUG ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) 	     (insn->type == INSN_JUMP_UNCONDITIONAL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) 	      insn->jump_dest && insn->jump_dest->type == INSN_BUG)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) 	 * Check if this (or a subsequent) instruction is related to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) 	 * CONFIG_UBSAN or CONFIG_KASAN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) 	 * End the search at 5 instructions to avoid going into the weeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) 	for (i = 0; i < 5; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) 		if (is_kasan_insn(insn) || is_ubsan_insn(insn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) 			return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) 		if (insn->type == INSN_JUMP_UNCONDITIONAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) 			if (insn->jump_dest &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) 			    insn->jump_dest->func == insn->func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) 				insn = insn->jump_dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) 		if (insn->offset + insn->len >= insn->func->offset + insn->func->len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) 		insn = list_next_entry(insn, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) 	return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) static int validate_symbol(struct objtool_file *file, struct section *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) 			   struct symbol *sym, struct insn_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) 	if (!sym->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) 		WARN("%s() is missing an ELF size annotation", sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) 	if (sym->pfunc != sym || sym->alias != sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) 	insn = find_insn(file, sec, sym->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) 	if (!insn || insn->ignore || insn->visited)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) 	state->uaccess = sym->uaccess_safe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) 	ret = validate_branch(file, insn->func, insn, *state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) 	if (ret && backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) 		BT_FUNC("<=== (sym)", insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) static int validate_section(struct objtool_file *file, struct section *sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) 	struct insn_state state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) 	struct symbol *func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) 	int warnings = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) 	list_for_each_entry(func, &sec->symbol_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) 		if (func->type != STT_FUNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) 		init_insn_state(&state, sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) 		state.cfi.cfa = initial_func_cfi.cfa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) 		memcpy(&state.cfi.regs, &initial_func_cfi.regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) 		       CFI_NUM_REGS * sizeof(struct cfi_reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) 		state.cfi.stack_size = initial_func_cfi.cfa.offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) 		warnings += validate_symbol(file, sec, func, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) 	return warnings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) static int validate_vmlinux_functions(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) 	struct section *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) 	int warnings = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) 	sec = find_section_by_name(file->elf, ".noinstr.text");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) 	if (sec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) 		warnings += validate_section(file, sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) 		warnings += validate_unwind_hints(file, sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) 	sec = find_section_by_name(file->elf, ".entry.text");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) 	if (sec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) 		warnings += validate_section(file, sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) 		warnings += validate_unwind_hints(file, sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) 	return warnings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) static int validate_functions(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) 	struct section *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) 	int warnings = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) 	for_each_sec(file, sec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) 		if (!(sec->sh.sh_flags & SHF_EXECINSTR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) 		warnings += validate_section(file, sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) 	return warnings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) static int validate_reachable_instructions(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) 	struct instruction *insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) 	if (file->ignore_unreachables)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) 	for_each_insn(file, insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) 		if (insn->visited || ignore_unreachable_insn(file, insn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) 		WARN_FUNC("unreachable instruction", insn->sec, insn->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) int check(struct objtool_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) 	int ret, warnings = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) 	arch_initial_func_cfi_state(&initial_func_cfi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) 	ret = decode_sections(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) 	warnings += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) 	if (list_empty(&file->insn_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) 	if (vmlinux && !validate_dup) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) 		ret = validate_vmlinux_functions(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) 		warnings += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) 	if (retpoline) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) 		ret = validate_retpoline(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) 		warnings += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) 	ret = validate_functions(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) 	warnings += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) 	ret = validate_unwind_hints(file, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073) 	warnings += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) 	if (!warnings) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076) 		ret = validate_reachable_instructions(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) 		warnings += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) 	ret = create_static_call_sections(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) 	warnings += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) 	if (mcount) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) 		ret = create_mcount_loc_sections(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) 		warnings += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) 	 *  For now, don't fail the kernel build on fatal warnings.  These
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) 	 *  errors are still fairly common due to the growing matrix of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) 	 *  supported toolchains and their recent pace of change.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) }