100089c04SJulien Thierry /* SPDX-License-Identifier: GPL-2.0 */ 200089c04SJulien Thierry #ifndef _LINUX_OBJTOOL_H 300089c04SJulien Thierry #define _LINUX_OBJTOOL_H 400089c04SJulien Thierry 5*ee819aedSJulien Thierry #ifndef __ASSEMBLY__ 6*ee819aedSJulien Thierry 7*ee819aedSJulien Thierry #include <linux/types.h> 8*ee819aedSJulien Thierry 9*ee819aedSJulien Thierry /* 10*ee819aedSJulien Thierry * This struct is used by asm and inline asm code to manually annotate the 11*ee819aedSJulien Thierry * location of registers on the stack. 12*ee819aedSJulien Thierry */ 13*ee819aedSJulien Thierry struct unwind_hint { 14*ee819aedSJulien Thierry u32 ip; 15*ee819aedSJulien Thierry s16 sp_offset; 16*ee819aedSJulien Thierry u8 sp_reg; 17*ee819aedSJulien Thierry u8 type; 18*ee819aedSJulien Thierry u8 end; 19*ee819aedSJulien Thierry }; 20*ee819aedSJulien Thierry #endif 21*ee819aedSJulien Thierry 22*ee819aedSJulien Thierry /* 23*ee819aedSJulien Thierry * UNWIND_HINT_TYPE_CALL: Indicates that sp_reg+sp_offset resolves to PREV_SP 24*ee819aedSJulien Thierry * (the caller's SP right before it made the call). Used for all callable 25*ee819aedSJulien Thierry * functions, i.e. all C code and all callable asm functions. 26*ee819aedSJulien Thierry * 27*ee819aedSJulien Thierry * UNWIND_HINT_TYPE_REGS: Used in entry code to indicate that sp_reg+sp_offset 28*ee819aedSJulien Thierry * points to a fully populated pt_regs from a syscall, interrupt, or exception. 29*ee819aedSJulien Thierry * 30*ee819aedSJulien Thierry * UNWIND_HINT_TYPE_REGS_PARTIAL: Used in entry code to indicate that 31*ee819aedSJulien Thierry * sp_reg+sp_offset points to the iret return frame. 32*ee819aedSJulien Thierry */ 33*ee819aedSJulien Thierry #define UNWIND_HINT_TYPE_CALL 0 34*ee819aedSJulien Thierry #define UNWIND_HINT_TYPE_REGS 1 35*ee819aedSJulien Thierry #define UNWIND_HINT_TYPE_REGS_PARTIAL 2 36*ee819aedSJulien Thierry #define UNWIND_HINT_TYPE_RET_OFFSET 3 37*ee819aedSJulien Thierry 3800089c04SJulien Thierry #ifdef CONFIG_STACK_VALIDATION 395567c6c3SJulien Thierry 405567c6c3SJulien Thierry #ifndef __ASSEMBLY__ 41*ee819aedSJulien Thierry 42*ee819aedSJulien Thierry #define UNWIND_HINT(sp_reg, sp_offset, type, end) \ 43*ee819aedSJulien Thierry "987: \n\t" \ 44*ee819aedSJulien Thierry ".pushsection .discard.unwind_hints\n\t" \ 45*ee819aedSJulien Thierry /* struct unwind_hint */ \ 46*ee819aedSJulien Thierry ".long 987b - .\n\t" \ 47*ee819aedSJulien Thierry ".short " __stringify(sp_offset) "\n\t" \ 48*ee819aedSJulien Thierry ".byte " __stringify(sp_reg) "\n\t" \ 49*ee819aedSJulien Thierry ".byte " __stringify(type) "\n\t" \ 50*ee819aedSJulien Thierry ".byte " __stringify(end) "\n\t" \ 51*ee819aedSJulien Thierry ".balign 4 \n\t" \ 52*ee819aedSJulien Thierry ".popsection\n\t" 53*ee819aedSJulien Thierry 5400089c04SJulien Thierry /* 5500089c04SJulien Thierry * This macro marks the given function's stack frame as "non-standard", which 5600089c04SJulien Thierry * tells objtool to ignore the function when doing stack metadata validation. 5700089c04SJulien Thierry * It should only be used in special cases where you're 100% sure it won't 5800089c04SJulien Thierry * affect the reliability of frame pointers and kernel stack traces. 5900089c04SJulien Thierry * 6000089c04SJulien Thierry * For more information, see tools/objtool/Documentation/stack-validation.txt. 6100089c04SJulien Thierry */ 6200089c04SJulien Thierry #define STACK_FRAME_NON_STANDARD(func) \ 6300089c04SJulien Thierry static void __used __section(.discard.func_stack_frame_non_standard) \ 6400089c04SJulien Thierry *__func_stack_frame_non_standard_##func = func 6500089c04SJulien Thierry 665567c6c3SJulien Thierry #else /* __ASSEMBLY__ */ 675567c6c3SJulien Thierry 6800089c04SJulien Thierry /* 6900089c04SJulien Thierry * This macro indicates that the following intra-function call is valid. 7000089c04SJulien Thierry * Any non-annotated intra-function call will cause objtool to issue a warning. 7100089c04SJulien Thierry */ 7200089c04SJulien Thierry #define ANNOTATE_INTRA_FUNCTION_CALL \ 7300089c04SJulien Thierry 999: \ 7400089c04SJulien Thierry .pushsection .discard.intra_function_calls; \ 7500089c04SJulien Thierry .long 999b; \ 7600089c04SJulien Thierry .popsection; 7700089c04SJulien Thierry 78*ee819aedSJulien Thierry /* 79*ee819aedSJulien Thierry * In asm, there are two kinds of code: normal C-type callable functions and 80*ee819aedSJulien Thierry * the rest. The normal callable functions can be called by other code, and 81*ee819aedSJulien Thierry * don't do anything unusual with the stack. Such normal callable functions 82*ee819aedSJulien Thierry * are annotated with the ENTRY/ENDPROC macros. Most asm code falls in this 83*ee819aedSJulien Thierry * category. In this case, no special debugging annotations are needed because 84*ee819aedSJulien Thierry * objtool can automatically generate the ORC data for the ORC unwinder to read 85*ee819aedSJulien Thierry * at runtime. 86*ee819aedSJulien Thierry * 87*ee819aedSJulien Thierry * Anything which doesn't fall into the above category, such as syscall and 88*ee819aedSJulien Thierry * interrupt handlers, tends to not be called directly by other functions, and 89*ee819aedSJulien Thierry * often does unusual non-C-function-type things with the stack pointer. Such 90*ee819aedSJulien Thierry * code needs to be annotated such that objtool can understand it. The 91*ee819aedSJulien Thierry * following CFI hint macros are for this type of code. 92*ee819aedSJulien Thierry * 93*ee819aedSJulien Thierry * These macros provide hints to objtool about the state of the stack at each 94*ee819aedSJulien Thierry * instruction. Objtool starts from the hints and follows the code flow, 95*ee819aedSJulien Thierry * making automatic CFI adjustments when it sees pushes and pops, filling out 96*ee819aedSJulien Thierry * the debuginfo as necessary. It will also warn if it sees any 97*ee819aedSJulien Thierry * inconsistencies. 98*ee819aedSJulien Thierry */ 99*ee819aedSJulien Thierry .macro UNWIND_HINT sp_reg:req sp_offset=0 type:req end=0 100*ee819aedSJulien Thierry .Lunwind_hint_ip_\@: 101*ee819aedSJulien Thierry .pushsection .discard.unwind_hints 102*ee819aedSJulien Thierry /* struct unwind_hint */ 103*ee819aedSJulien Thierry .long .Lunwind_hint_ip_\@ - . 104*ee819aedSJulien Thierry .short \sp_offset 105*ee819aedSJulien Thierry .byte \sp_reg 106*ee819aedSJulien Thierry .byte \type 107*ee819aedSJulien Thierry .byte \end 108*ee819aedSJulien Thierry .balign 4 109*ee819aedSJulien Thierry .popsection 110*ee819aedSJulien Thierry .endm 111*ee819aedSJulien Thierry 1125567c6c3SJulien Thierry #endif /* __ASSEMBLY__ */ 1135567c6c3SJulien Thierry 11400089c04SJulien Thierry #else /* !CONFIG_STACK_VALIDATION */ 11500089c04SJulien Thierry 116*ee819aedSJulien Thierry #ifndef __ASSEMBLY__ 117*ee819aedSJulien Thierry 118*ee819aedSJulien Thierry #define UNWIND_HINT(sp_reg, sp_offset, type, end) \ 119*ee819aedSJulien Thierry "\n\t" 12000089c04SJulien Thierry #define STACK_FRAME_NON_STANDARD(func) 121*ee819aedSJulien Thierry #else 12200089c04SJulien Thierry #define ANNOTATE_INTRA_FUNCTION_CALL 123*ee819aedSJulien Thierry .macro UNWIND_HINT sp_reg:req sp_offset=0 type:req end=0 124*ee819aedSJulien Thierry .endm 125*ee819aedSJulien Thierry #endif 12600089c04SJulien Thierry 12700089c04SJulien Thierry #endif /* CONFIG_STACK_VALIDATION */ 12800089c04SJulien Thierry 12900089c04SJulien Thierry #endif /* _LINUX_OBJTOOL_H */ 130