Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86,objtool: Split UNWIND_HINT_EMPTY in two

Mark reported that the ORC unwinder incorrectly marks an unwind as
reliable when the unwind terminates prematurely in the dark corners of
return_to_handler() due to lack of information about the next frame.

The problem is UNWIND_HINT_EMPTY is used in two different situations:

1) The end of the kernel stack unwind before hitting user entry, boot
code, or fork entry

2) A blind spot in ORC coverage where the unwinder has to bail due to
lack of information about the next frame

The ORC unwinder has no way to tell the difference between the two.
When it encounters an undefined stack state with 'end=1', it blindly
marks the stack reliable, which can break the livepatch consistency
model.

Fix it by splitting UNWIND_HINT_EMPTY into UNWIND_HINT_UNDEFINED and
UNWIND_HINT_END_OF_STACK.

Reported-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/fd6212c8b450d3564b855e1cb48404d6277b4d9f.1677683419.git.jpoimboe@kernel.org

authored by

Josh Poimboeuf and committed by
Peter Zijlstra
fb799447 4708ea14

+116 -95
+1 -1
Documentation/livepatch/reliable-stacktrace.rst
··· 183 183 .. code-block:: none 184 184 185 185 SYM_CODE_START(return_to_handler) 186 - UNWIND_HINT_EMPTY 186 + UNWIND_HINT_UNDEFINED 187 187 subq $24, %rsp 188 188 189 189 /* Save the return values */
+6 -6
arch/x86/entry/entry_64.S
··· 205 205 */ 206 206 movq %rsp, %rdi 207 207 movq PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %rsp 208 - UNWIND_HINT_EMPTY 208 + UNWIND_HINT_END_OF_STACK 209 209 210 210 pushq RSP-RDI(%rdi) /* RSP */ 211 211 pushq (%rdi) /* RDI */ ··· 286 286 .pushsection .text, "ax" 287 287 __FUNC_ALIGN 288 288 SYM_CODE_START_NOALIGN(ret_from_fork) 289 - UNWIND_HINT_EMPTY 289 + UNWIND_HINT_END_OF_STACK 290 290 ANNOTATE_NOENDBR // copy_thread 291 291 CALL_DEPTH_ACCOUNT 292 292 movq %rax, %rdi ··· 303 303 304 304 1: 305 305 /* kernel thread */ 306 - UNWIND_HINT_EMPTY 306 + UNWIND_HINT_END_OF_STACK 307 307 movq %r12, %rdi 308 308 CALL_NOSPEC rbx 309 309 /* ··· 643 643 */ 644 644 movq %rsp, %rdi 645 645 movq PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %rsp 646 - UNWIND_HINT_EMPTY 646 + UNWIND_HINT_END_OF_STACK 647 647 648 648 /* Copy the IRET frame to the trampoline stack. */ 649 649 pushq 6*8(%rdi) /* SS */ ··· 869 869 */ 870 870 __FUNC_ALIGN 871 871 SYM_CODE_START_NOALIGN(xen_failsafe_callback) 872 - UNWIND_HINT_EMPTY 872 + UNWIND_HINT_UNDEFINED 873 873 ENDBR 874 874 movl %ds, %ecx 875 875 cmpw %cx, 0x10(%rsp) ··· 1520 1520 * MSRs to fully disable 32-bit SYSCALL. 1521 1521 */ 1522 1522 SYM_CODE_START(ignore_sysret) 1523 - UNWIND_HINT_EMPTY 1523 + UNWIND_HINT_END_OF_STACK 1524 1524 ENDBR 1525 1525 mov $-ENOSYS, %eax 1526 1526 sysretl
+7 -7
arch/x86/include/asm/orc_types.h
··· 39 39 #define ORC_REG_SP_INDIRECT 9 40 40 #define ORC_REG_MAX 15 41 41 42 - #define ORC_TYPE_CALL 0 43 - #define ORC_TYPE_REGS 1 44 - #define ORC_TYPE_REGS_PARTIAL 2 42 + #define ORC_TYPE_UNDEFINED 0 43 + #define ORC_TYPE_END_OF_STACK 1 44 + #define ORC_TYPE_CALL 2 45 + #define ORC_TYPE_REGS 3 46 + #define ORC_TYPE_REGS_PARTIAL 4 45 47 46 48 #ifndef __ASSEMBLY__ 47 49 #include <asm/byteorder.h> ··· 62 60 #if defined(__LITTLE_ENDIAN_BITFIELD) 63 61 unsigned sp_reg:4; 64 62 unsigned bp_reg:4; 65 - unsigned type:2; 63 + unsigned type:3; 66 64 unsigned signal:1; 67 - unsigned end:1; 68 65 #elif defined(__BIG_ENDIAN_BITFIELD) 69 66 unsigned bp_reg:4; 70 67 unsigned sp_reg:4; 71 68 unsigned unused:4; 72 - unsigned end:1; 73 69 unsigned signal:1; 74 - unsigned type:2; 70 + unsigned type:3; 75 71 #endif 76 72 } __packed; 77 73
+8 -4
arch/x86/include/asm/unwind_hints.h
··· 7 7 8 8 #ifdef __ASSEMBLY__ 9 9 10 - .macro UNWIND_HINT_EMPTY 11 - UNWIND_HINT type=UNWIND_HINT_TYPE_CALL end=1 10 + .macro UNWIND_HINT_END_OF_STACK 11 + UNWIND_HINT type=UNWIND_HINT_TYPE_END_OF_STACK 12 + .endm 13 + 14 + .macro UNWIND_HINT_UNDEFINED 15 + UNWIND_HINT type=UNWIND_HINT_TYPE_UNDEFINED 12 16 .endm 13 17 14 18 .macro UNWIND_HINT_ENTRY 15 19 VALIDATE_UNRET_BEGIN 16 - UNWIND_HINT_EMPTY 20 + UNWIND_HINT_END_OF_STACK 17 21 .endm 18 22 19 23 .macro UNWIND_HINT_REGS base=%rsp offset=0 indirect=0 extra=1 partial=0 signal=1 ··· 77 73 #else 78 74 79 75 #define UNWIND_HINT_FUNC \ 80 - UNWIND_HINT(UNWIND_HINT_TYPE_FUNC, ORC_REG_SP, 8, 0, 0) 76 + UNWIND_HINT(UNWIND_HINT_TYPE_FUNC, ORC_REG_SP, 8, 0) 81 77 82 78 #endif /* __ASSEMBLY__ */ 83 79
+1 -1
arch/x86/kernel/ftrace_64.S
··· 340 340 341 341 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 342 342 SYM_CODE_START(return_to_handler) 343 - UNWIND_HINT_EMPTY 343 + UNWIND_HINT_UNDEFINED 344 344 ANNOTATE_NOENDBR 345 345 subq $16, %rsp 346 346
+6 -6
arch/x86/kernel/head_64.S
··· 42 42 __HEAD 43 43 .code64 44 44 SYM_CODE_START_NOALIGN(startup_64) 45 - UNWIND_HINT_EMPTY 45 + UNWIND_HINT_END_OF_STACK 46 46 /* 47 47 * At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 0, 48 48 * and someone has loaded an identity mapped page table ··· 105 105 lretq 106 106 107 107 .Lon_kernel_cs: 108 - UNWIND_HINT_EMPTY 108 + UNWIND_HINT_END_OF_STACK 109 109 110 110 /* Sanitize CPU configuration */ 111 111 call verify_cpu ··· 127 127 SYM_CODE_END(startup_64) 128 128 129 129 SYM_CODE_START(secondary_startup_64) 130 - UNWIND_HINT_EMPTY 130 + UNWIND_HINT_END_OF_STACK 131 131 ANNOTATE_NOENDBR 132 132 /* 133 133 * At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 0, ··· 156 156 * verify_cpu() above to make sure NX is enabled. 157 157 */ 158 158 SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL) 159 - UNWIND_HINT_EMPTY 159 + UNWIND_HINT_END_OF_STACK 160 160 ANNOTATE_NOENDBR 161 161 162 162 /* ··· 238 238 ANNOTATE_RETPOLINE_SAFE 239 239 jmp *%rax 240 240 1: 241 - UNWIND_HINT_EMPTY 241 + UNWIND_HINT_END_OF_STACK 242 242 ANNOTATE_NOENDBR // above 243 243 244 244 /* ··· 371 371 */ 372 372 SYM_CODE_START(start_cpu0) 373 373 ANNOTATE_NOENDBR 374 - UNWIND_HINT_EMPTY 374 + UNWIND_HINT_END_OF_STACK 375 375 movq initial_stack(%rip), %rsp 376 376 jmp .Ljump_to_C_code 377 377 SYM_CODE_END(start_cpu0)
+5 -5
arch/x86/kernel/relocate_kernel_64.S
··· 43 43 .code64 44 44 SYM_CODE_START_NOALIGN(relocate_range) 45 45 SYM_CODE_START_NOALIGN(relocate_kernel) 46 - UNWIND_HINT_EMPTY 46 + UNWIND_HINT_END_OF_STACK 47 47 ANNOTATE_NOENDBR 48 48 /* 49 49 * %rdi indirection_page ··· 113 113 SYM_CODE_END(relocate_kernel) 114 114 115 115 SYM_CODE_START_LOCAL_NOALIGN(identity_mapped) 116 - UNWIND_HINT_EMPTY 116 + UNWIND_HINT_END_OF_STACK 117 117 /* set return address to 0 if not preserving context */ 118 118 pushq $0 119 119 /* store the start address on the stack */ ··· 231 231 SYM_CODE_END(identity_mapped) 232 232 233 233 SYM_CODE_START_LOCAL_NOALIGN(virtual_mapped) 234 - UNWIND_HINT_EMPTY 234 + UNWIND_HINT_END_OF_STACK 235 235 ANNOTATE_NOENDBR // RET target, above 236 236 movq RSP(%r8), %rsp 237 237 movq CR4(%r8), %rax ··· 256 256 257 257 /* Do the copies */ 258 258 SYM_CODE_START_LOCAL_NOALIGN(swap_pages) 259 - UNWIND_HINT_EMPTY 260 - movq %rdi, %rcx /* Put the page_list in %rcx */ 259 + UNWIND_HINT_END_OF_STACK 260 + movq %rdi, %rcx /* Put the page_list in %rcx */ 261 261 xorl %edi, %edi 262 262 xorl %esi, %esi 263 263 jmp 1f
+6 -9
arch/x86/kernel/unwind_orc.c
··· 158 158 .sp_offset = 16, 159 159 .bp_reg = ORC_REG_PREV_SP, 160 160 .bp_offset = -16, 161 - .end = 0, 162 161 }; 163 162 164 163 static struct orc_entry *orc_find(unsigned long ip) ··· 249 250 return -1; 250 251 251 252 /* 252 - * The "weak" section terminator entries need to always be on the left 253 + * The "weak" section terminator entries need to always be first 253 254 * to ensure the lookup code skips them in favor of real entries. 254 255 * These terminator entries exist to handle any gaps created by 255 256 * whitelisted .o files which didn't get objtool generation. 256 257 */ 257 258 orc_a = cur_orc_table + (a - cur_orc_ip_table); 258 - return orc_a->sp_reg == ORC_REG_UNDEFINED && !orc_a->end ? -1 : 1; 259 + return orc_a->type == ORC_TYPE_UNDEFINED ? -1 : 1; 259 260 } 260 261 261 262 void unwind_module_init(struct module *mod, void *_orc_ip, size_t orc_ip_size, ··· 473 474 */ 474 475 orc = &orc_fp_entry; 475 476 state->error = true; 476 - } 477 - 478 - /* End-of-stack check for kernel threads: */ 479 - if (orc->sp_reg == ORC_REG_UNDEFINED) { 480 - if (!orc->end) 477 + } else { 478 + if (orc->type == ORC_TYPE_UNDEFINED) 481 479 goto err; 482 480 483 - goto the_end; 481 + if (orc->type == ORC_TYPE_END_OF_STACK) 482 + goto the_end; 484 483 } 485 484 486 485 state->signal = orc->signal;
+3 -3
arch/x86/lib/retpoline.S
··· 33 33 34 34 .align RETPOLINE_THUNK_SIZE 35 35 SYM_INNER_LABEL(__x86_indirect_thunk_\reg, SYM_L_GLOBAL) 36 - UNWIND_HINT_EMPTY 36 + UNWIND_HINT_UNDEFINED 37 37 ANNOTATE_NOENDBR 38 38 39 39 ALTERNATIVE_2 __stringify(RETPOLINE \reg), \ ··· 75 75 .align RETPOLINE_THUNK_SIZE 76 76 77 77 SYM_INNER_LABEL(__x86_indirect_call_thunk_\reg, SYM_L_GLOBAL) 78 - UNWIND_HINT_EMPTY 78 + UNWIND_HINT_UNDEFINED 79 79 ANNOTATE_NOENDBR 80 80 81 81 CALL_DEPTH_ACCOUNT ··· 103 103 .align RETPOLINE_THUNK_SIZE 104 104 105 105 SYM_INNER_LABEL(__x86_indirect_jump_thunk_\reg, SYM_L_GLOBAL) 106 - UNWIND_HINT_EMPTY 106 + UNWIND_HINT_UNDEFINED 107 107 ANNOTATE_NOENDBR 108 108 POLINE \reg 109 109 ANNOTATE_UNRET_SAFE
+1 -1
arch/x86/platform/pvh/head.S
··· 50 50 #define PVH_DS_SEL (PVH_GDT_ENTRY_DS * 8) 51 51 52 52 SYM_CODE_START_LOCAL(pvh_start_xen) 53 - UNWIND_HINT_EMPTY 53 + UNWIND_HINT_END_OF_STACK 54 54 cld 55 55 56 56 lgdt (_pa(gdt))
+2 -2
arch/x86/xen/xen-asm.S
··· 165 165 SYM_CODE_START(xen_early_idt_handler_array) 166 166 i = 0 167 167 .rept NUM_EXCEPTION_VECTORS 168 - UNWIND_HINT_EMPTY 168 + UNWIND_HINT_UNDEFINED 169 169 ENDBR 170 170 pop %rcx 171 171 pop %r11 ··· 193 193 * rsp->rax } 194 194 */ 195 195 SYM_CODE_START(xen_iret) 196 - UNWIND_HINT_EMPTY 196 + UNWIND_HINT_UNDEFINED 197 197 ANNOTATE_NOENDBR 198 198 pushq $0 199 199 jmp hypercall_iret
+2 -2
arch/x86/xen/xen-head.S
··· 45 45 #ifdef CONFIG_XEN_PV 46 46 __INIT 47 47 SYM_CODE_START(startup_xen) 48 - UNWIND_HINT_EMPTY 48 + UNWIND_HINT_END_OF_STACK 49 49 ANNOTATE_NOENDBR 50 50 cld 51 51 ··· 71 71 #ifdef CONFIG_XEN_PV_SMP 72 72 .pushsection .text 73 73 SYM_CODE_START(asm_cpu_bringup_and_idle) 74 - UNWIND_HINT_EMPTY 74 + UNWIND_HINT_END_OF_STACK 75 75 ENDBR 76 76 77 77 call cpu_bringup_and_idle
+4 -6
include/linux/objtool.h
··· 10 10 11 11 #ifndef __ASSEMBLY__ 12 12 13 - #define UNWIND_HINT(type, sp_reg, sp_offset, signal, end) \ 13 + #define UNWIND_HINT(type, sp_reg, sp_offset, signal) \ 14 14 "987: \n\t" \ 15 15 ".pushsection .discard.unwind_hints\n\t" \ 16 16 /* struct unwind_hint */ \ ··· 19 19 ".byte " __stringify(sp_reg) "\n\t" \ 20 20 ".byte " __stringify(type) "\n\t" \ 21 21 ".byte " __stringify(signal) "\n\t" \ 22 - ".byte " __stringify(end) "\n\t" \ 23 22 ".balign 4 \n\t" \ 24 23 ".popsection\n\t" 25 24 ··· 90 91 * the debuginfo as necessary. It will also warn if it sees any 91 92 * inconsistencies. 92 93 */ 93 - .macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0 end=0 94 + .macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0 94 95 .Lhere_\@: 95 96 .pushsection .discard.unwind_hints 96 97 /* struct unwind_hint */ ··· 99 100 .byte \sp_reg 100 101 .byte \type 101 102 .byte \signal 102 - .byte \end 103 103 .balign 4 104 104 .popsection 105 105 .endm ··· 151 153 152 154 #ifndef __ASSEMBLY__ 153 155 154 - #define UNWIND_HINT(type, sp_reg, sp_offset, signal, end) "\n\t" 156 + #define UNWIND_HINT(type, sp_reg, sp_offset, signal) "\n\t" 155 157 #define STACK_FRAME_NON_STANDARD(func) 156 158 #define STACK_FRAME_NON_STANDARD_FP(func) 157 159 #define ANNOTATE_NOENDBR 158 160 #define ASM_REACHABLE 159 161 #else 160 162 #define ANNOTATE_INTRA_FUNCTION_CALL 161 - .macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0 end=0 163 + .macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0 162 164 .endm 163 165 .macro STACK_FRAME_NON_STANDARD func:req 164 166 .endm
+18 -9
include/linux/objtool_types.h
··· 16 16 u8 sp_reg; 17 17 u8 type; 18 18 u8 signal; 19 - u8 end; 20 19 }; 21 20 22 21 #endif /* __ASSEMBLY__ */ 23 22 24 23 /* 24 + * UNWIND_HINT_TYPE_UNDEFINED: A blind spot in ORC coverage which can result in 25 + * a truncated and unreliable stack unwind. 26 + * 27 + * UNWIND_HINT_TYPE_END_OF_STACK: The end of the kernel stack unwind before 28 + * hitting user entry, boot code, or fork entry (when there are no pt_regs 29 + * available). 30 + * 25 31 * UNWIND_HINT_TYPE_CALL: Indicates that sp_reg+sp_offset resolves to PREV_SP 26 32 * (the caller's SP right before it made the call). Used for all callable 27 33 * functions, i.e. all C code and all callable asm functions. ··· 38 32 * UNWIND_HINT_TYPE_REGS_PARTIAL: Used in entry code to indicate that 39 33 * sp_reg+sp_offset points to the iret return frame. 40 34 * 41 - * UNWIND_HINT_FUNC: Generate the unwind metadata of a callable function. 35 + * UNWIND_HINT_TYPE_FUNC: Generate the unwind metadata of a callable function. 42 36 * Useful for code which doesn't have an ELF function annotation. 43 37 * 44 - * UNWIND_HINT_ENTRY: machine entry without stack, SYSCALL/SYSENTER etc. 38 + * UNWIND_HINT_TYPE_{SAVE,RESTORE}: Save the unwind metadata at a certain 39 + * location so that it can be restored later. 45 40 */ 46 - #define UNWIND_HINT_TYPE_CALL 0 47 - #define UNWIND_HINT_TYPE_REGS 1 48 - #define UNWIND_HINT_TYPE_REGS_PARTIAL 2 41 + #define UNWIND_HINT_TYPE_UNDEFINED 0 42 + #define UNWIND_HINT_TYPE_END_OF_STACK 1 43 + #define UNWIND_HINT_TYPE_CALL 2 44 + #define UNWIND_HINT_TYPE_REGS 3 45 + #define UNWIND_HINT_TYPE_REGS_PARTIAL 4 49 46 /* The below hint types don't have corresponding ORC types */ 50 - #define UNWIND_HINT_TYPE_FUNC 3 51 - #define UNWIND_HINT_TYPE_SAVE 4 52 - #define UNWIND_HINT_TYPE_RESTORE 5 47 + #define UNWIND_HINT_TYPE_FUNC 5 48 + #define UNWIND_HINT_TYPE_SAVE 6 49 + #define UNWIND_HINT_TYPE_RESTORE 7 53 50 54 51 #endif /* _LINUX_OBJTOOL_TYPES_H */
+1 -1
scripts/sorttable.h
··· 128 128 * whitelisted .o files which didn't get objtool generation. 129 129 */ 130 130 orc_a = g_orc_table + (a - g_orc_ip_table); 131 - return orc_a->sp_reg == ORC_REG_UNDEFINED && !orc_a->end ? -1 : 1; 131 + return orc_a->type == ORC_TYPE_UNDEFINED ? -1 : 1; 132 132 } 133 133 134 134 static void *sort_orctable(void *arg)
+7 -7
tools/arch/x86/include/asm/orc_types.h
··· 39 39 #define ORC_REG_SP_INDIRECT 9 40 40 #define ORC_REG_MAX 15 41 41 42 - #define ORC_TYPE_CALL 0 43 - #define ORC_TYPE_REGS 1 44 - #define ORC_TYPE_REGS_PARTIAL 2 42 + #define ORC_TYPE_UNDEFINED 0 43 + #define ORC_TYPE_END_OF_STACK 1 44 + #define ORC_TYPE_CALL 2 45 + #define ORC_TYPE_REGS 3 46 + #define ORC_TYPE_REGS_PARTIAL 4 45 47 46 48 #ifndef __ASSEMBLY__ 47 49 #include <asm/byteorder.h> ··· 62 60 #if defined(__LITTLE_ENDIAN_BITFIELD) 63 61 unsigned sp_reg:4; 64 62 unsigned bp_reg:4; 65 - unsigned type:2; 63 + unsigned type:3; 66 64 unsigned signal:1; 67 - unsigned end:1; 68 65 #elif defined(__BIG_ENDIAN_BITFIELD) 69 66 unsigned bp_reg:4; 70 67 unsigned sp_reg:4; 71 68 unsigned unused:4; 72 - unsigned end:1; 73 69 unsigned signal:1; 74 - unsigned type:2; 70 + unsigned type:3; 75 71 #endif 76 72 } __packed; 77 73
+18 -9
tools/include/linux/objtool_types.h
··· 16 16 u8 sp_reg; 17 17 u8 type; 18 18 u8 signal; 19 - u8 end; 20 19 }; 21 20 22 21 #endif /* __ASSEMBLY__ */ 23 22 24 23 /* 24 + * UNWIND_HINT_TYPE_UNDEFINED: A blind spot in ORC coverage which can result in 25 + * a truncated and unreliable stack unwind. 26 + * 27 + * UNWIND_HINT_TYPE_END_OF_STACK: The end of the kernel stack unwind before 28 + * hitting user entry, boot code, or fork entry (when there are no pt_regs 29 + * available). 30 + * 25 31 * UNWIND_HINT_TYPE_CALL: Indicates that sp_reg+sp_offset resolves to PREV_SP 26 32 * (the caller's SP right before it made the call). Used for all callable 27 33 * functions, i.e. all C code and all callable asm functions. ··· 38 32 * UNWIND_HINT_TYPE_REGS_PARTIAL: Used in entry code to indicate that 39 33 * sp_reg+sp_offset points to the iret return frame. 40 34 * 41 - * UNWIND_HINT_FUNC: Generate the unwind metadata of a callable function. 35 + * UNWIND_HINT_TYPE_FUNC: Generate the unwind metadata of a callable function. 42 36 * Useful for code which doesn't have an ELF function annotation. 43 37 * 44 - * UNWIND_HINT_ENTRY: machine entry without stack, SYSCALL/SYSENTER etc. 38 + * UNWIND_HINT_TYPE_{SAVE,RESTORE}: Save the unwind metadata at a certain 39 + * location so that it can be restored later. 45 40 */ 46 - #define UNWIND_HINT_TYPE_CALL 0 47 - #define UNWIND_HINT_TYPE_REGS 1 48 - #define UNWIND_HINT_TYPE_REGS_PARTIAL 2 41 + #define UNWIND_HINT_TYPE_UNDEFINED 0 42 + #define UNWIND_HINT_TYPE_END_OF_STACK 1 43 + #define UNWIND_HINT_TYPE_CALL 2 44 + #define UNWIND_HINT_TYPE_REGS 3 45 + #define UNWIND_HINT_TYPE_REGS_PARTIAL 4 49 46 /* The below hint types don't have corresponding ORC types */ 50 - #define UNWIND_HINT_TYPE_FUNC 3 51 - #define UNWIND_HINT_TYPE_SAVE 4 52 - #define UNWIND_HINT_TYPE_RESTORE 5 47 + #define UNWIND_HINT_TYPE_FUNC 5 48 + #define UNWIND_HINT_TYPE_SAVE 6 49 + #define UNWIND_HINT_TYPE_RESTORE 7 53 50 54 51 #endif /* _LINUX_OBJTOOL_TYPES_H */
+1 -1
tools/objtool/check.c
··· 2243 2243 memcpy(&state->regs, &initial_func_cfi.regs, 2244 2244 CFI_NUM_REGS * sizeof(struct cfi_reg)); 2245 2245 state->stack_size = initial_func_cfi.cfa.offset; 2246 + state->type = UNWIND_HINT_TYPE_CALL; 2246 2247 } 2247 2248 2248 2249 static int read_unwind_hints(struct objtool_file *file) ··· 2328 2327 cfi.cfa.offset = bswap_if_needed(file->elf, hint->sp_offset); 2329 2328 cfi.type = hint->type; 2330 2329 cfi.signal = hint->signal; 2331 - cfi.end = hint->end; 2332 2330 2333 2331 insn->cfi = cfi_hash_find_or_add(&cfi); 2334 2332 }
+6 -2
tools/objtool/orc_dump.c
··· 38 38 static const char *orc_type_name(unsigned int type) 39 39 { 40 40 switch (type) { 41 + case ORC_TYPE_UNDEFINED: 42 + return "(und)"; 43 + case ORC_TYPE_END_OF_STACK: 44 + return "end"; 41 45 case ORC_TYPE_CALL: 42 46 return "call"; 43 47 case ORC_TYPE_REGS: ··· 205 201 printf("%llx:", (unsigned long long)(orc_ip_addr + (i * sizeof(int)) + orc_ip[i])); 206 202 } 207 203 204 + printf("type:%s", orc_type_name(orc[i].type)); 208 205 209 206 printf(" sp:"); 210 207 ··· 215 210 216 211 print_reg(orc[i].bp_reg, bswap_if_needed(&dummy_elf, orc[i].bp_offset)); 217 212 218 - printf(" type:%s signal:%d end:%d\n", 219 - orc_type_name(orc[i].type), orc[i].signal, orc[i].end); 213 + printf(" signal:%d\n", orc[i].signal); 220 214 } 221 215 222 216 elf_end(elf);
+13 -13
tools/objtool/orc_gen.c
··· 21 21 memset(orc, 0, sizeof(*orc)); 22 22 23 23 if (!cfi) { 24 - orc->end = 0; 25 - orc->sp_reg = ORC_REG_UNDEFINED; 24 + /* 25 + * This is usually either unreachable nops/traps (which don't 26 + * trigger unreachable instruction warnings), or 27 + * STACK_FRAME_NON_STANDARD functions. 28 + */ 29 + orc->type = ORC_TYPE_UNDEFINED; 26 30 return 0; 27 31 } 28 32 29 33 switch (cfi->type) { 34 + case UNWIND_HINT_TYPE_UNDEFINED: 35 + orc->type = ORC_TYPE_UNDEFINED; 36 + return 0; 37 + case UNWIND_HINT_TYPE_END_OF_STACK: 38 + orc->type = ORC_TYPE_END_OF_STACK; 39 + return 0; 30 40 case UNWIND_HINT_TYPE_CALL: 31 41 orc->type = ORC_TYPE_CALL; 32 42 break; ··· 52 42 return -1; 53 43 } 54 44 55 - orc->end = cfi->end; 56 45 orc->signal = cfi->signal; 57 - 58 - if (cfi->cfa.base == CFI_UNDEFINED) { 59 - orc->sp_reg = ORC_REG_UNDEFINED; 60 - return 0; 61 - } 62 46 63 47 switch (cfi->cfa.base) { 64 48 case CFI_SP: ··· 167 163 struct orc_list_entry *entry; 168 164 struct list_head orc_list; 169 165 170 - struct orc_entry null = { 171 - .sp_reg = ORC_REG_UNDEFINED, 172 - .bp_reg = ORC_REG_UNDEFINED, 173 - .type = ORC_TYPE_CALL, 174 - }; 166 + struct orc_entry null = { .type = ORC_TYPE_UNDEFINED }; 175 167 176 168 /* Build a deduplicated list of ORC entries: */ 177 169 INIT_LIST_HEAD(&orc_list);