1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _LINUX_OBJTOOL_H
3#define _LINUX_OBJTOOL_H
4
5#include <linux/objtool_types.h>
6
7#ifdef CONFIG_OBJTOOL
8
9#include <asm/asm.h>
10
11#ifndef __ASSEMBLY__
12
13#define UNWIND_HINT(type, sp_reg, sp_offset, signal)	\
14	"987: \n\t"						\
15	".pushsection .discard.unwind_hints\n\t"		\
16	/* struct unwind_hint */				\
17	".long 987b - .\n\t"					\
18	".short " __stringify(sp_offset) "\n\t"			\
19	".byte " __stringify(sp_reg) "\n\t"			\
20	".byte " __stringify(type) "\n\t"			\
21	".byte " __stringify(signal) "\n\t"			\
22	".balign 4 \n\t"					\
23	".popsection\n\t"
24
25/*
26 * This macro marks the given function's stack frame as "non-standard", which
27 * tells objtool to ignore the function when doing stack metadata validation.
28 * It should only be used in special cases where you're 100% sure it won't
29 * affect the reliability of frame pointers and kernel stack traces.
30 *
31 * For more information, see tools/objtool/Documentation/objtool.txt.
32 */
33#define STACK_FRAME_NON_STANDARD(func) \
34	static void __used __section(".discard.func_stack_frame_non_standard") \
35		*__func_stack_frame_non_standard_##func = func
36
37/*
38 * STACK_FRAME_NON_STANDARD_FP() is a frame-pointer-specific function ignore
39 * for the case where a function is intentionally missing frame pointer setup,
40 * but otherwise needs objtool/ORC coverage when frame pointers are disabled.
41 */
42#ifdef CONFIG_FRAME_POINTER
43#define STACK_FRAME_NON_STANDARD_FP(func) STACK_FRAME_NON_STANDARD(func)
44#else
45#define STACK_FRAME_NON_STANDARD_FP(func)
46#endif
47
48#define ANNOTATE_NOENDBR					\
49	"986: \n\t"						\
50	".pushsection .discard.noendbr\n\t"			\
51	".long 986b\n\t"					\
52	".popsection\n\t"
53
54#define ASM_REACHABLE							\
55	"998:\n\t"							\
56	".pushsection .discard.reachable\n\t"				\
57	".long 998b\n\t"						\
58	".popsection\n\t"
59
60#else /* __ASSEMBLY__ */
61
62/*
63 * This macro indicates that the following intra-function call is valid.
64 * Any non-annotated intra-function call will cause objtool to issue a warning.
65 */
66#define ANNOTATE_INTRA_FUNCTION_CALL				\
67	999:							\
68	.pushsection .discard.intra_function_calls;		\
69	.long 999b;						\
70	.popsection;
71
72/*
73 * In asm, there are two kinds of code: normal C-type callable functions and
74 * the rest.  The normal callable functions can be called by other code, and
75 * don't do anything unusual with the stack.  Such normal callable functions
76 * are annotated with the ENTRY/ENDPROC macros.  Most asm code falls in this
77 * category.  In this case, no special debugging annotations are needed because
78 * objtool can automatically generate the ORC data for the ORC unwinder to read
79 * at runtime.
80 *
81 * Anything which doesn't fall into the above category, such as syscall and
82 * interrupt handlers, tends to not be called directly by other functions, and
83 * often does unusual non-C-function-type things with the stack pointer.  Such
84 * code needs to be annotated such that objtool can understand it.  The
85 * following CFI hint macros are for this type of code.
86 *
87 * These macros provide hints to objtool about the state of the stack at each
88 * instruction.  Objtool starts from the hints and follows the code flow,
89 * making automatic CFI adjustments when it sees pushes and pops, filling out
90 * the debuginfo as necessary.  It will also warn if it sees any
91 * inconsistencies.
92 */
93.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0
94.Lhere_\@:
95	.pushsection .discard.unwind_hints
96		/* struct unwind_hint */
97		.long .Lhere_\@ - .
98		.short \sp_offset
99		.byte \sp_reg
100		.byte \type
101		.byte \signal
102		.balign 4
103	.popsection
104.endm
105
106.macro STACK_FRAME_NON_STANDARD func:req
107	.pushsection .discard.func_stack_frame_non_standard, "aw"
108	.long \func - .
109	.popsection
110.endm
111
112.macro STACK_FRAME_NON_STANDARD_FP func:req
113#ifdef CONFIG_FRAME_POINTER
114	STACK_FRAME_NON_STANDARD \func
115#endif
116.endm
117
118.macro ANNOTATE_NOENDBR
119.Lhere_\@:
120	.pushsection .discard.noendbr
121	.long	.Lhere_\@
122	.popsection
123.endm
124
125/*
126 * Use objtool to validate the entry requirement that all code paths do
127 * VALIDATE_UNRET_END before RET.
128 *
129 * NOTE: The macro must be used at the beginning of a global symbol, otherwise
130 * it will be ignored.
131 */
132.macro VALIDATE_UNRET_BEGIN
133#if defined(CONFIG_NOINSTR_VALIDATION) && \
134	(defined(CONFIG_MITIGATION_UNRET_ENTRY) || defined(CONFIG_MITIGATION_SRSO))
135.Lhere_\@:
136	.pushsection .discard.validate_unret
137	.long	.Lhere_\@ - .
138	.popsection
139#endif
140.endm
141
142.macro REACHABLE
143.Lhere_\@:
144	.pushsection .discard.reachable
145	.long	.Lhere_\@
146	.popsection
147.endm
148
149#endif /* __ASSEMBLY__ */
150
151#else /* !CONFIG_OBJTOOL */
152
153#ifndef __ASSEMBLY__
154
155#define UNWIND_HINT(type, sp_reg, sp_offset, signal) "\n\t"
156#define STACK_FRAME_NON_STANDARD(func)
157#define STACK_FRAME_NON_STANDARD_FP(func)
158#define ANNOTATE_NOENDBR
159#define ASM_REACHABLE
160#else
161#define ANNOTATE_INTRA_FUNCTION_CALL
162.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0
163.endm
164.macro STACK_FRAME_NON_STANDARD func:req
165.endm
166.macro ANNOTATE_NOENDBR
167.endm
168.macro REACHABLE
169.endm
170#endif
171
172#endif /* CONFIG_OBJTOOL */
173
174#endif /* _LINUX_OBJTOOL_H */
175