18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _LINUX_OBJTOOL_H
38c2ecf20Sopenharmony_ci#define _LINUX_OBJTOOL_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <linux/types.h>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci/*
108c2ecf20Sopenharmony_ci * This struct is used by asm and inline asm code to manually annotate the
118c2ecf20Sopenharmony_ci * location of registers on the stack.
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_cistruct unwind_hint {
148c2ecf20Sopenharmony_ci	u32		ip;
158c2ecf20Sopenharmony_ci	s16		sp_offset;
168c2ecf20Sopenharmony_ci	u8		sp_reg;
178c2ecf20Sopenharmony_ci	u8		type;
188c2ecf20Sopenharmony_ci	u8		end;
198c2ecf20Sopenharmony_ci};
208c2ecf20Sopenharmony_ci#endif
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/*
238c2ecf20Sopenharmony_ci * UNWIND_HINT_TYPE_CALL: Indicates that sp_reg+sp_offset resolves to PREV_SP
248c2ecf20Sopenharmony_ci * (the caller's SP right before it made the call).  Used for all callable
258c2ecf20Sopenharmony_ci * functions, i.e. all C code and all callable asm functions.
268c2ecf20Sopenharmony_ci *
278c2ecf20Sopenharmony_ci * UNWIND_HINT_TYPE_REGS: Used in entry code to indicate that sp_reg+sp_offset
288c2ecf20Sopenharmony_ci * points to a fully populated pt_regs from a syscall, interrupt, or exception.
298c2ecf20Sopenharmony_ci *
308c2ecf20Sopenharmony_ci * UNWIND_HINT_TYPE_REGS_PARTIAL: Used in entry code to indicate that
318c2ecf20Sopenharmony_ci * sp_reg+sp_offset points to the iret return frame.
328c2ecf20Sopenharmony_ci *
338c2ecf20Sopenharmony_ci * UNWIND_HINT_FUNC: Generate the unwind metadata of a callable function.
348c2ecf20Sopenharmony_ci * Useful for code which doesn't have an ELF function annotation.
358c2ecf20Sopenharmony_ci *
368c2ecf20Sopenharmony_ci * UNWIND_HINT_ENTRY: machine entry without stack, SYSCALL/SYSENTER etc.
378c2ecf20Sopenharmony_ci */
388c2ecf20Sopenharmony_ci#define UNWIND_HINT_TYPE_CALL		0
398c2ecf20Sopenharmony_ci#define UNWIND_HINT_TYPE_REGS		1
408c2ecf20Sopenharmony_ci#define UNWIND_HINT_TYPE_REGS_PARTIAL	2
418c2ecf20Sopenharmony_ci#define UNWIND_HINT_TYPE_FUNC		3
428c2ecf20Sopenharmony_ci#define UNWIND_HINT_TYPE_ENTRY		4
438c2ecf20Sopenharmony_ci#define UNWIND_HINT_TYPE_SAVE		5
448c2ecf20Sopenharmony_ci#define UNWIND_HINT_TYPE_RESTORE	6
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci#ifdef CONFIG_STACK_VALIDATION
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#define UNWIND_HINT(sp_reg, sp_offset, type, end)		\
518c2ecf20Sopenharmony_ci	"987: \n\t"						\
528c2ecf20Sopenharmony_ci	".pushsection .discard.unwind_hints\n\t"		\
538c2ecf20Sopenharmony_ci	/* struct unwind_hint */				\
548c2ecf20Sopenharmony_ci	".long 987b - .\n\t"					\
558c2ecf20Sopenharmony_ci	".short " __stringify(sp_offset) "\n\t"			\
568c2ecf20Sopenharmony_ci	".byte " __stringify(sp_reg) "\n\t"			\
578c2ecf20Sopenharmony_ci	".byte " __stringify(type) "\n\t"			\
588c2ecf20Sopenharmony_ci	".byte " __stringify(end) "\n\t"			\
598c2ecf20Sopenharmony_ci	".balign 4 \n\t"					\
608c2ecf20Sopenharmony_ci	".popsection\n\t"
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci/*
638c2ecf20Sopenharmony_ci * This macro marks the given function's stack frame as "non-standard", which
648c2ecf20Sopenharmony_ci * tells objtool to ignore the function when doing stack metadata validation.
658c2ecf20Sopenharmony_ci * It should only be used in special cases where you're 100% sure it won't
668c2ecf20Sopenharmony_ci * affect the reliability of frame pointers and kernel stack traces.
678c2ecf20Sopenharmony_ci *
688c2ecf20Sopenharmony_ci * For more information, see tools/objtool/Documentation/stack-validation.txt.
698c2ecf20Sopenharmony_ci */
708c2ecf20Sopenharmony_ci#define STACK_FRAME_NON_STANDARD(func) \
718c2ecf20Sopenharmony_ci	static void __used __section(".discard.func_stack_frame_non_standard") \
728c2ecf20Sopenharmony_ci		*__func_stack_frame_non_standard_##func = func
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci/*
758c2ecf20Sopenharmony_ci * STACK_FRAME_NON_STANDARD_FP() is a frame-pointer-specific function ignore
768c2ecf20Sopenharmony_ci * for the case where a function is intentionally missing frame pointer setup,
778c2ecf20Sopenharmony_ci * but otherwise needs objtool/ORC coverage when frame pointers are disabled.
788c2ecf20Sopenharmony_ci */
798c2ecf20Sopenharmony_ci#ifdef CONFIG_FRAME_POINTER
808c2ecf20Sopenharmony_ci#define STACK_FRAME_NON_STANDARD_FP(func) STACK_FRAME_NON_STANDARD(func)
818c2ecf20Sopenharmony_ci#else
828c2ecf20Sopenharmony_ci#define STACK_FRAME_NON_STANDARD_FP(func)
838c2ecf20Sopenharmony_ci#endif
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci#define ANNOTATE_NOENDBR					\
868c2ecf20Sopenharmony_ci	"986: \n\t"						\
878c2ecf20Sopenharmony_ci	".pushsection .discard.noendbr\n\t"			\
888c2ecf20Sopenharmony_ci	_ASM_PTR " 986b\n\t"					\
898c2ecf20Sopenharmony_ci	".popsection\n\t"
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci#else /* __ASSEMBLY__ */
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci/*
948c2ecf20Sopenharmony_ci * This macro indicates that the following intra-function call is valid.
958c2ecf20Sopenharmony_ci * Any non-annotated intra-function call will cause objtool to issue a warning.
968c2ecf20Sopenharmony_ci */
978c2ecf20Sopenharmony_ci#define ANNOTATE_INTRA_FUNCTION_CALL				\
988c2ecf20Sopenharmony_ci	999:							\
998c2ecf20Sopenharmony_ci	.pushsection .discard.intra_function_calls;		\
1008c2ecf20Sopenharmony_ci	.long 999b;						\
1018c2ecf20Sopenharmony_ci	.popsection;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci/*
1048c2ecf20Sopenharmony_ci * In asm, there are two kinds of code: normal C-type callable functions and
1058c2ecf20Sopenharmony_ci * the rest.  The normal callable functions can be called by other code, and
1068c2ecf20Sopenharmony_ci * don't do anything unusual with the stack.  Such normal callable functions
1078c2ecf20Sopenharmony_ci * are annotated with the ENTRY/ENDPROC macros.  Most asm code falls in this
1088c2ecf20Sopenharmony_ci * category.  In this case, no special debugging annotations are needed because
1098c2ecf20Sopenharmony_ci * objtool can automatically generate the ORC data for the ORC unwinder to read
1108c2ecf20Sopenharmony_ci * at runtime.
1118c2ecf20Sopenharmony_ci *
1128c2ecf20Sopenharmony_ci * Anything which doesn't fall into the above category, such as syscall and
1138c2ecf20Sopenharmony_ci * interrupt handlers, tends to not be called directly by other functions, and
1148c2ecf20Sopenharmony_ci * often does unusual non-C-function-type things with the stack pointer.  Such
1158c2ecf20Sopenharmony_ci * code needs to be annotated such that objtool can understand it.  The
1168c2ecf20Sopenharmony_ci * following CFI hint macros are for this type of code.
1178c2ecf20Sopenharmony_ci *
1188c2ecf20Sopenharmony_ci * These macros provide hints to objtool about the state of the stack at each
1198c2ecf20Sopenharmony_ci * instruction.  Objtool starts from the hints and follows the code flow,
1208c2ecf20Sopenharmony_ci * making automatic CFI adjustments when it sees pushes and pops, filling out
1218c2ecf20Sopenharmony_ci * the debuginfo as necessary.  It will also warn if it sees any
1228c2ecf20Sopenharmony_ci * inconsistencies.
1238c2ecf20Sopenharmony_ci */
1248c2ecf20Sopenharmony_ci.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
1258c2ecf20Sopenharmony_ci.Lunwind_hint_ip_\@:
1268c2ecf20Sopenharmony_ci	.pushsection .discard.unwind_hints
1278c2ecf20Sopenharmony_ci		/* struct unwind_hint */
1288c2ecf20Sopenharmony_ci		.long .Lunwind_hint_ip_\@ - .
1298c2ecf20Sopenharmony_ci		.short \sp_offset
1308c2ecf20Sopenharmony_ci		.byte \sp_reg
1318c2ecf20Sopenharmony_ci		.byte \type
1328c2ecf20Sopenharmony_ci		.byte \end
1338c2ecf20Sopenharmony_ci		.balign 4
1348c2ecf20Sopenharmony_ci	.popsection
1358c2ecf20Sopenharmony_ci.endm
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci.macro ANNOTATE_NOENDBR
1388c2ecf20Sopenharmony_ci.Lhere_\@:
1398c2ecf20Sopenharmony_ci	.pushsection .discard.noendbr
1408c2ecf20Sopenharmony_ci	.quad	.Lhere_\@
1418c2ecf20Sopenharmony_ci	.popsection
1428c2ecf20Sopenharmony_ci.endm
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci#else /* !CONFIG_STACK_VALIDATION */
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci#define UNWIND_HINT(sp_reg, sp_offset, type, end)	\
1518c2ecf20Sopenharmony_ci	"\n\t"
1528c2ecf20Sopenharmony_ci#define STACK_FRAME_NON_STANDARD(func)
1538c2ecf20Sopenharmony_ci#define STACK_FRAME_NON_STANDARD_FP(func)
1548c2ecf20Sopenharmony_ci#define ANNOTATE_NOENDBR
1558c2ecf20Sopenharmony_ci#else
1568c2ecf20Sopenharmony_ci#define ANNOTATE_INTRA_FUNCTION_CALL
1578c2ecf20Sopenharmony_ci.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
1588c2ecf20Sopenharmony_ci.endm
1598c2ecf20Sopenharmony_ci.macro ANNOTATE_NOENDBR
1608c2ecf20Sopenharmony_ci.endm
1618c2ecf20Sopenharmony_ci#endif
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci#endif /* CONFIG_STACK_VALIDATION */
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci#endif /* _LINUX_OBJTOOL_H */
166