xref: /openbmc/linux/arch/x86/include/asm/unwind_hints.h (revision e25eea89bb8853763a22fa2547199cf96b571ba1)
139358a03SJosh Poimboeuf #ifndef _ASM_X86_UNWIND_HINTS_H
239358a03SJosh Poimboeuf #define _ASM_X86_UNWIND_HINTS_H
339358a03SJosh Poimboeuf 
439358a03SJosh Poimboeuf #include "orc_types.h"
539358a03SJosh Poimboeuf 
639358a03SJosh Poimboeuf #ifdef __ASSEMBLY__
739358a03SJosh Poimboeuf 
839358a03SJosh Poimboeuf /*
939358a03SJosh Poimboeuf  * In asm, there are two kinds of code: normal C-type callable functions and
1039358a03SJosh Poimboeuf  * the rest.  The normal callable functions can be called by other code, and
1139358a03SJosh Poimboeuf  * don't do anything unusual with the stack.  Such normal callable functions
1239358a03SJosh Poimboeuf  * are annotated with the ENTRY/ENDPROC macros.  Most asm code falls in this
1339358a03SJosh Poimboeuf  * category.  In this case, no special debugging annotations are needed because
1439358a03SJosh Poimboeuf  * objtool can automatically generate the ORC data for the ORC unwinder to read
1539358a03SJosh Poimboeuf  * at runtime.
1639358a03SJosh Poimboeuf  *
1739358a03SJosh Poimboeuf  * Anything which doesn't fall into the above category, such as syscall and
1839358a03SJosh Poimboeuf  * interrupt handlers, tends to not be called directly by other functions, and
1939358a03SJosh Poimboeuf  * often does unusual non-C-function-type things with the stack pointer.  Such
2039358a03SJosh Poimboeuf  * code needs to be annotated such that objtool can understand it.  The
2139358a03SJosh Poimboeuf  * following CFI hint macros are for this type of code.
2239358a03SJosh Poimboeuf  *
2339358a03SJosh Poimboeuf  * These macros provide hints to objtool about the state of the stack at each
2439358a03SJosh Poimboeuf  * instruction.  Objtool starts from the hints and follows the code flow,
2539358a03SJosh Poimboeuf  * making automatic CFI adjustments when it sees pushes and pops, filling out
2639358a03SJosh Poimboeuf  * the debuginfo as necessary.  It will also warn if it sees any
2739358a03SJosh Poimboeuf  * inconsistencies.
2839358a03SJosh Poimboeuf  */
29d31a5802SJosh Poimboeuf .macro UNWIND_HINT sp_reg=ORC_REG_SP sp_offset=0 type=ORC_TYPE_CALL end=0
3039358a03SJosh Poimboeuf #ifdef CONFIG_STACK_VALIDATION
3139358a03SJosh Poimboeuf .Lunwind_hint_ip_\@:
3239358a03SJosh Poimboeuf 	.pushsection .discard.unwind_hints
3339358a03SJosh Poimboeuf 		/* struct unwind_hint */
3439358a03SJosh Poimboeuf 		.long .Lunwind_hint_ip_\@ - .
3539358a03SJosh Poimboeuf 		.short \sp_offset
3639358a03SJosh Poimboeuf 		.byte \sp_reg
3739358a03SJosh Poimboeuf 		.byte \type
38d31a5802SJosh Poimboeuf 		.byte \end
39d31a5802SJosh Poimboeuf 		.balign 4
4039358a03SJosh Poimboeuf 	.popsection
4139358a03SJosh Poimboeuf #endif
4239358a03SJosh Poimboeuf .endm
4339358a03SJosh Poimboeuf 
4439358a03SJosh Poimboeuf .macro UNWIND_HINT_EMPTY
45d31a5802SJosh Poimboeuf 	UNWIND_HINT sp_reg=ORC_REG_UNDEFINED end=1
4639358a03SJosh Poimboeuf .endm
4739358a03SJosh Poimboeuf 
4839358a03SJosh Poimboeuf .macro UNWIND_HINT_REGS base=%rsp offset=0 indirect=0 extra=1 iret=0
49af79ded4SJosh Poimboeuf 	.if \base == %rsp
50af79ded4SJosh Poimboeuf 		.if \indirect
5139358a03SJosh Poimboeuf 			.set sp_reg, ORC_REG_SP_INDIRECT
52af79ded4SJosh Poimboeuf 		.else
5339358a03SJosh Poimboeuf 			.set sp_reg, ORC_REG_SP
54af79ded4SJosh Poimboeuf 		.endif
5539358a03SJosh Poimboeuf 	.elseif \base == %rbp
5639358a03SJosh Poimboeuf 		.set sp_reg, ORC_REG_BP
5739358a03SJosh Poimboeuf 	.elseif \base == %rdi
5839358a03SJosh Poimboeuf 		.set sp_reg, ORC_REG_DI
5939358a03SJosh Poimboeuf 	.elseif \base == %rdx
6039358a03SJosh Poimboeuf 		.set sp_reg, ORC_REG_DX
6139358a03SJosh Poimboeuf 	.elseif \base == %r10
6239358a03SJosh Poimboeuf 		.set sp_reg, ORC_REG_R10
6339358a03SJosh Poimboeuf 	.else
6439358a03SJosh Poimboeuf 		.error "UNWIND_HINT_REGS: bad base register"
6539358a03SJosh Poimboeuf 	.endif
6639358a03SJosh Poimboeuf 
6739358a03SJosh Poimboeuf 	.set sp_offset, \offset
6839358a03SJosh Poimboeuf 
6939358a03SJosh Poimboeuf 	.if \iret
7039358a03SJosh Poimboeuf 		.set type, ORC_TYPE_REGS_IRET
7139358a03SJosh Poimboeuf 	.elseif \extra == 0
7239358a03SJosh Poimboeuf 		.set type, ORC_TYPE_REGS_IRET
7339358a03SJosh Poimboeuf 		.set sp_offset, \offset + (16*8)
7439358a03SJosh Poimboeuf 	.else
7539358a03SJosh Poimboeuf 		.set type, ORC_TYPE_REGS
7639358a03SJosh Poimboeuf 	.endif
7739358a03SJosh Poimboeuf 
7839358a03SJosh Poimboeuf 	UNWIND_HINT sp_reg=sp_reg sp_offset=sp_offset type=type
7939358a03SJosh Poimboeuf .endm
8039358a03SJosh Poimboeuf 
8139358a03SJosh Poimboeuf .macro UNWIND_HINT_IRET_REGS base=%rsp offset=0
8239358a03SJosh Poimboeuf 	UNWIND_HINT_REGS base=\base offset=\offset iret=1
8339358a03SJosh Poimboeuf .endm
8439358a03SJosh Poimboeuf 
8539358a03SJosh Poimboeuf .macro UNWIND_HINT_FUNC sp_offset=8
8639358a03SJosh Poimboeuf 	UNWIND_HINT sp_offset=\sp_offset
8739358a03SJosh Poimboeuf .endm
8839358a03SJosh Poimboeuf 
8977ac117bSJosh Poimboeuf .macro UNWIND_HINT_SAVE
9077ac117bSJosh Poimboeuf 	UNWIND_HINT type=UNWIND_HINT_TYPE_SAVE
9177ac117bSJosh Poimboeuf .endm
9277ac117bSJosh Poimboeuf 
9377ac117bSJosh Poimboeuf .macro UNWIND_HINT_RESTORE
9477ac117bSJosh Poimboeuf 	UNWIND_HINT type=UNWIND_HINT_TYPE_RESTORE
9577ac117bSJosh Poimboeuf .endm
9677ac117bSJosh Poimboeuf 
97*e25eea89SPeter Zijlstra 
98*e25eea89SPeter Zijlstra /*
99*e25eea89SPeter Zijlstra  * RET_OFFSET: Used on instructions that terminate a function; mostly RETURN
100*e25eea89SPeter Zijlstra  * and sibling calls. On these, sp_offset denotes the expected offset from
101*e25eea89SPeter Zijlstra  * initial_func_cfi.
102*e25eea89SPeter Zijlstra  */
103*e25eea89SPeter Zijlstra .macro UNWIND_HINT_RET_OFFSET sp_offset=8
104*e25eea89SPeter Zijlstra 	UNWIND_HINT type=UNWIND_HINT_TYPE_RET_OFFSET sp_offset=\sp_offset
105*e25eea89SPeter Zijlstra .endm
106*e25eea89SPeter Zijlstra 
10739358a03SJosh Poimboeuf #else /* !__ASSEMBLY__ */
10839358a03SJosh Poimboeuf 
109d31a5802SJosh Poimboeuf #define UNWIND_HINT(sp_reg, sp_offset, type, end)		\
11039358a03SJosh Poimboeuf 	"987: \n\t"						\
11139358a03SJosh Poimboeuf 	".pushsection .discard.unwind_hints\n\t"		\
11239358a03SJosh Poimboeuf 	/* struct unwind_hint */				\
11339358a03SJosh Poimboeuf 	".long 987b - .\n\t"					\
11439358a03SJosh Poimboeuf 	".short " __stringify(sp_offset) "\n\t"			\
11539358a03SJosh Poimboeuf 	".byte " __stringify(sp_reg) "\n\t"			\
11639358a03SJosh Poimboeuf 	".byte " __stringify(type) "\n\t"			\
117d31a5802SJosh Poimboeuf 	".byte " __stringify(end) "\n\t"			\
118d31a5802SJosh Poimboeuf 	".balign 4 \n\t"					\
11939358a03SJosh Poimboeuf 	".popsection\n\t"
12039358a03SJosh Poimboeuf 
121d31a5802SJosh Poimboeuf #define UNWIND_HINT_SAVE UNWIND_HINT(0, 0, UNWIND_HINT_TYPE_SAVE, 0)
12239358a03SJosh Poimboeuf 
123d31a5802SJosh Poimboeuf #define UNWIND_HINT_RESTORE UNWIND_HINT(0, 0, UNWIND_HINT_TYPE_RESTORE, 0)
12439358a03SJosh Poimboeuf 
12539358a03SJosh Poimboeuf #endif /* __ASSEMBLY__ */
12639358a03SJosh Poimboeuf 
12739358a03SJosh Poimboeuf #endif /* _ASM_X86_UNWIND_HINTS_H */
128