xref: /openbmc/linux/arch/x86/include/asm/unwind_hints.h (revision 39358a033b2e4432052265c1fa0f36f572d8cfb5)
1*39358a03SJosh Poimboeuf #ifndef _ASM_X86_UNWIND_HINTS_H
2*39358a03SJosh Poimboeuf #define _ASM_X86_UNWIND_HINTS_H
3*39358a03SJosh Poimboeuf 
4*39358a03SJosh Poimboeuf #include "orc_types.h"
5*39358a03SJosh Poimboeuf 
6*39358a03SJosh Poimboeuf #ifdef __ASSEMBLY__
7*39358a03SJosh Poimboeuf 
8*39358a03SJosh Poimboeuf /*
9*39358a03SJosh Poimboeuf  * In asm, there are two kinds of code: normal C-type callable functions and
10*39358a03SJosh Poimboeuf  * the rest.  The normal callable functions can be called by other code, and
11*39358a03SJosh Poimboeuf  * don't do anything unusual with the stack.  Such normal callable functions
12*39358a03SJosh Poimboeuf  * are annotated with the ENTRY/ENDPROC macros.  Most asm code falls in this
13*39358a03SJosh Poimboeuf  * category.  In this case, no special debugging annotations are needed because
14*39358a03SJosh Poimboeuf  * objtool can automatically generate the ORC data for the ORC unwinder to read
15*39358a03SJosh Poimboeuf  * at runtime.
16*39358a03SJosh Poimboeuf  *
17*39358a03SJosh Poimboeuf  * Anything which doesn't fall into the above category, such as syscall and
18*39358a03SJosh Poimboeuf  * interrupt handlers, tends to not be called directly by other functions, and
19*39358a03SJosh Poimboeuf  * often does unusual non-C-function-type things with the stack pointer.  Such
20*39358a03SJosh Poimboeuf  * code needs to be annotated such that objtool can understand it.  The
21*39358a03SJosh Poimboeuf  * following CFI hint macros are for this type of code.
22*39358a03SJosh Poimboeuf  *
23*39358a03SJosh Poimboeuf  * These macros provide hints to objtool about the state of the stack at each
24*39358a03SJosh Poimboeuf  * instruction.  Objtool starts from the hints and follows the code flow,
25*39358a03SJosh Poimboeuf  * making automatic CFI adjustments when it sees pushes and pops, filling out
26*39358a03SJosh Poimboeuf  * the debuginfo as necessary.  It will also warn if it sees any
27*39358a03SJosh Poimboeuf  * inconsistencies.
28*39358a03SJosh Poimboeuf  */
29*39358a03SJosh Poimboeuf .macro UNWIND_HINT sp_reg=ORC_REG_SP sp_offset=0 type=ORC_TYPE_CALL
30*39358a03SJosh Poimboeuf #ifdef CONFIG_STACK_VALIDATION
31*39358a03SJosh Poimboeuf .Lunwind_hint_ip_\@:
32*39358a03SJosh Poimboeuf 	.pushsection .discard.unwind_hints
33*39358a03SJosh Poimboeuf 		/* struct unwind_hint */
34*39358a03SJosh Poimboeuf 		.long .Lunwind_hint_ip_\@ - .
35*39358a03SJosh Poimboeuf 		.short \sp_offset
36*39358a03SJosh Poimboeuf 		.byte \sp_reg
37*39358a03SJosh Poimboeuf 		.byte \type
38*39358a03SJosh Poimboeuf 	.popsection
39*39358a03SJosh Poimboeuf #endif
40*39358a03SJosh Poimboeuf .endm
41*39358a03SJosh Poimboeuf 
42*39358a03SJosh Poimboeuf .macro UNWIND_HINT_EMPTY
43*39358a03SJosh Poimboeuf 	UNWIND_HINT sp_reg=ORC_REG_UNDEFINED
44*39358a03SJosh Poimboeuf .endm
45*39358a03SJosh Poimboeuf 
46*39358a03SJosh Poimboeuf .macro UNWIND_HINT_REGS base=%rsp offset=0 indirect=0 extra=1 iret=0
47*39358a03SJosh Poimboeuf 	.if \base == %rsp && \indirect
48*39358a03SJosh Poimboeuf 		.set sp_reg, ORC_REG_SP_INDIRECT
49*39358a03SJosh Poimboeuf 	.elseif \base == %rsp
50*39358a03SJosh Poimboeuf 		.set sp_reg, ORC_REG_SP
51*39358a03SJosh Poimboeuf 	.elseif \base == %rbp
52*39358a03SJosh Poimboeuf 		.set sp_reg, ORC_REG_BP
53*39358a03SJosh Poimboeuf 	.elseif \base == %rdi
54*39358a03SJosh Poimboeuf 		.set sp_reg, ORC_REG_DI
55*39358a03SJosh Poimboeuf 	.elseif \base == %rdx
56*39358a03SJosh Poimboeuf 		.set sp_reg, ORC_REG_DX
57*39358a03SJosh Poimboeuf 	.elseif \base == %r10
58*39358a03SJosh Poimboeuf 		.set sp_reg, ORC_REG_R10
59*39358a03SJosh Poimboeuf 	.else
60*39358a03SJosh Poimboeuf 		.error "UNWIND_HINT_REGS: bad base register"
61*39358a03SJosh Poimboeuf 	.endif
62*39358a03SJosh Poimboeuf 
63*39358a03SJosh Poimboeuf 	.set sp_offset, \offset
64*39358a03SJosh Poimboeuf 
65*39358a03SJosh Poimboeuf 	.if \iret
66*39358a03SJosh Poimboeuf 		.set type, ORC_TYPE_REGS_IRET
67*39358a03SJosh Poimboeuf 	.elseif \extra == 0
68*39358a03SJosh Poimboeuf 		.set type, ORC_TYPE_REGS_IRET
69*39358a03SJosh Poimboeuf 		.set sp_offset, \offset + (16*8)
70*39358a03SJosh Poimboeuf 	.else
71*39358a03SJosh Poimboeuf 		.set type, ORC_TYPE_REGS
72*39358a03SJosh Poimboeuf 	.endif
73*39358a03SJosh Poimboeuf 
74*39358a03SJosh Poimboeuf 	UNWIND_HINT sp_reg=sp_reg sp_offset=sp_offset type=type
75*39358a03SJosh Poimboeuf .endm
76*39358a03SJosh Poimboeuf 
77*39358a03SJosh Poimboeuf .macro UNWIND_HINT_IRET_REGS base=%rsp offset=0
78*39358a03SJosh Poimboeuf 	UNWIND_HINT_REGS base=\base offset=\offset iret=1
79*39358a03SJosh Poimboeuf .endm
80*39358a03SJosh Poimboeuf 
81*39358a03SJosh Poimboeuf .macro UNWIND_HINT_FUNC sp_offset=8
82*39358a03SJosh Poimboeuf 	UNWIND_HINT sp_offset=\sp_offset
83*39358a03SJosh Poimboeuf .endm
84*39358a03SJosh Poimboeuf 
85*39358a03SJosh Poimboeuf #else /* !__ASSEMBLY__ */
86*39358a03SJosh Poimboeuf 
87*39358a03SJosh Poimboeuf #define UNWIND_HINT(sp_reg, sp_offset, type)			\
88*39358a03SJosh Poimboeuf 	"987: \n\t"						\
89*39358a03SJosh Poimboeuf 	".pushsection .discard.unwind_hints\n\t"		\
90*39358a03SJosh Poimboeuf 	/* struct unwind_hint */				\
91*39358a03SJosh Poimboeuf 	".long 987b - .\n\t"					\
92*39358a03SJosh Poimboeuf 	".short " __stringify(sp_offset) "\n\t"		\
93*39358a03SJosh Poimboeuf 	".byte " __stringify(sp_reg) "\n\t"			\
94*39358a03SJosh Poimboeuf 	".byte " __stringify(type) "\n\t"			\
95*39358a03SJosh Poimboeuf 	".popsection\n\t"
96*39358a03SJosh Poimboeuf 
97*39358a03SJosh Poimboeuf #define UNWIND_HINT_SAVE UNWIND_HINT(0, 0, UNWIND_HINT_TYPE_SAVE)
98*39358a03SJosh Poimboeuf 
99*39358a03SJosh Poimboeuf #define UNWIND_HINT_RESTORE UNWIND_HINT(0, 0, UNWIND_HINT_TYPE_RESTORE)
100*39358a03SJosh Poimboeuf 
101*39358a03SJosh Poimboeuf #endif /* __ASSEMBLY__ */
102*39358a03SJosh Poimboeuf 
103*39358a03SJosh Poimboeuf #endif /* _ASM_X86_UNWIND_HINTS_H */
104