.. code-block:: none
 
    SYM_CODE_START(return_to_handler)
-           UNWIND_HINT_EMPTY
+           UNWIND_HINT_UNDEFINED
            subq  $24, %rsp
 
            /* Save the return values */
 
         */
        movq    %rsp, %rdi
        movq    PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %rsp
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_END_OF_STACK
 
        pushq   RSP-RDI(%rdi)   /* RSP */
        pushq   (%rdi)          /* RDI */
 .pushsection .text, "ax"
        __FUNC_ALIGN
 SYM_CODE_START_NOALIGN(ret_from_fork)
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_END_OF_STACK
        ANNOTATE_NOENDBR // copy_thread
        CALL_DEPTH_ACCOUNT
        movq    %rax, %rdi
 
 1:
        /* kernel thread */
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_END_OF_STACK
        movq    %r12, %rdi
        CALL_NOSPEC rbx
        /*
         */
        movq    %rsp, %rdi
        movq    PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %rsp
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_END_OF_STACK
 
        /* Copy the IRET frame to the trampoline stack. */
        pushq   6*8(%rdi)       /* SS */
  */
        __FUNC_ALIGN
 SYM_CODE_START_NOALIGN(xen_failsafe_callback)
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_UNDEFINED
        ENDBR
        movl    %ds, %ecx
        cmpw    %cx, 0x10(%rsp)
  * MSRs to fully disable 32-bit SYSCALL.
  */
 SYM_CODE_START(ignore_sysret)
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_END_OF_STACK
        ENDBR
        mov     $-ENOSYS, %eax
        sysretl
 
 #define ORC_REG_SP_INDIRECT            9
 #define ORC_REG_MAX                    15
 
-#define ORC_TYPE_CALL                  0
-#define ORC_TYPE_REGS                  1
-#define ORC_TYPE_REGS_PARTIAL          2
+#define ORC_TYPE_UNDEFINED             0
+#define ORC_TYPE_END_OF_STACK          1
+#define ORC_TYPE_CALL                  2
+#define ORC_TYPE_REGS                  3
+#define ORC_TYPE_REGS_PARTIAL          4
 
 #ifndef __ASSEMBLY__
 #include <asm/byteorder.h>
 #if defined(__LITTLE_ENDIAN_BITFIELD)
        unsigned        sp_reg:4;
        unsigned        bp_reg:4;
-       unsigned        type:2;
+       unsigned        type:3;
        unsigned        signal:1;
-       unsigned        end:1;
 #elif defined(__BIG_ENDIAN_BITFIELD)
        unsigned        bp_reg:4;
        unsigned        sp_reg:4;
        unsigned        unused:4;
-       unsigned        end:1;
        unsigned        signal:1;
-       unsigned        type:2;
+       unsigned        type:3;
 #endif
 } __packed;
 
 
 
 #ifdef __ASSEMBLY__
 
-.macro UNWIND_HINT_EMPTY
-       UNWIND_HINT type=UNWIND_HINT_TYPE_CALL end=1
+.macro UNWIND_HINT_END_OF_STACK
+       UNWIND_HINT type=UNWIND_HINT_TYPE_END_OF_STACK
+.endm
+
+.macro UNWIND_HINT_UNDEFINED
+       UNWIND_HINT type=UNWIND_HINT_TYPE_UNDEFINED
 .endm
 
 .macro UNWIND_HINT_ENTRY
        VALIDATE_UNRET_BEGIN
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_END_OF_STACK
 .endm
 
 .macro UNWIND_HINT_REGS base=%rsp offset=0 indirect=0 extra=1 partial=0 signal=1
 #else
 
 #define UNWIND_HINT_FUNC \
-       UNWIND_HINT(UNWIND_HINT_TYPE_FUNC, ORC_REG_SP, 8, 0, 0)
+       UNWIND_HINT(UNWIND_HINT_TYPE_FUNC, ORC_REG_SP, 8, 0)
 
 #endif /* __ASSEMBLY__ */
 
 
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 SYM_CODE_START(return_to_handler)
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_UNDEFINED
        ANNOTATE_NOENDBR
        subq  $16, %rsp
 
 
        __HEAD
        .code64
 SYM_CODE_START_NOALIGN(startup_64)
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_END_OF_STACK
        /*
         * At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 0,
         * and someone has loaded an identity mapped page table
        lretq
 
 .Lon_kernel_cs:
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_END_OF_STACK
 
        /* Sanitize CPU configuration */
        call verify_cpu
 SYM_CODE_END(startup_64)
 
 SYM_CODE_START(secondary_startup_64)
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_END_OF_STACK
        ANNOTATE_NOENDBR
        /*
         * At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 0,
         * verify_cpu() above to make sure NX is enabled.
         */
 SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL)
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_END_OF_STACK
        ANNOTATE_NOENDBR
 
        /*
        ANNOTATE_RETPOLINE_SAFE
        jmp     *%rax
 1:
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_END_OF_STACK
        ANNOTATE_NOENDBR // above
 
        /*
  */
 SYM_CODE_START(start_cpu0)
        ANNOTATE_NOENDBR
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_END_OF_STACK
        movq    initial_stack(%rip), %rsp
        jmp     .Ljump_to_C_code
 SYM_CODE_END(start_cpu0)
 
        .code64
 SYM_CODE_START_NOALIGN(relocate_range)
 SYM_CODE_START_NOALIGN(relocate_kernel)
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_END_OF_STACK
        ANNOTATE_NOENDBR
        /*
         * %rdi indirection_page
 SYM_CODE_END(relocate_kernel)
 
 SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_END_OF_STACK
        /* set return address to 0 if not preserving context */
        pushq   $0
        /* store the start address on the stack */
 SYM_CODE_END(identity_mapped)
 
 SYM_CODE_START_LOCAL_NOALIGN(virtual_mapped)
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_END_OF_STACK
        ANNOTATE_NOENDBR // RET target, above
        movq    RSP(%r8), %rsp
        movq    CR4(%r8), %rax
 
        /* Do the copies */
 SYM_CODE_START_LOCAL_NOALIGN(swap_pages)
-       UNWIND_HINT_EMPTY
-       movq    %rdi, %rcx      /* Put the page_list in %rcx */
+       UNWIND_HINT_END_OF_STACK
+       movq    %rdi, %rcx      /* Put the page_list in %rcx */
        xorl    %edi, %edi
        xorl    %esi, %esi
        jmp     1f
 
        .sp_offset      = 16,
        .bp_reg         = ORC_REG_PREV_SP,
        .bp_offset      = -16,
-       .end            = 0,
 };
 
 static struct orc_entry *orc_find(unsigned long ip)
                return -1;
 
        /*
-        * The "weak" section terminator entries need to always be on the left
+        * The "weak" section terminator entries need to always be first
         * to ensure the lookup code skips them in favor of real entries.
         * These terminator entries exist to handle any gaps created by
         * whitelisted .o files which didn't get objtool generation.
         */
        orc_a = cur_orc_table + (a - cur_orc_ip_table);
-       return orc_a->sp_reg == ORC_REG_UNDEFINED && !orc_a->end ? -1 : 1;
+       return orc_a->type == ORC_TYPE_UNDEFINED ? -1 : 1;
 }
 
 void unwind_module_init(struct module *mod, void *_orc_ip, size_t orc_ip_size,
                 */
                orc = &orc_fp_entry;
                state->error = true;
-       }
-
-       /* End-of-stack check for kernel threads: */
-       if (orc->sp_reg == ORC_REG_UNDEFINED) {
-               if (!orc->end)
+       } else {
+               if (orc->type == ORC_TYPE_UNDEFINED)
                        goto err;
 
-               goto the_end;
+               if (orc->type == ORC_TYPE_END_OF_STACK)
+                       goto the_end;
        }
 
        state->signal = orc->signal;
 
 
        .align RETPOLINE_THUNK_SIZE
 SYM_INNER_LABEL(__x86_indirect_thunk_\reg, SYM_L_GLOBAL)
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_UNDEFINED
        ANNOTATE_NOENDBR
 
        ALTERNATIVE_2 __stringify(RETPOLINE \reg), \
        .align RETPOLINE_THUNK_SIZE
 
 SYM_INNER_LABEL(__x86_indirect_call_thunk_\reg, SYM_L_GLOBAL)
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_UNDEFINED
        ANNOTATE_NOENDBR
 
        CALL_DEPTH_ACCOUNT
        .align RETPOLINE_THUNK_SIZE
 
 SYM_INNER_LABEL(__x86_indirect_jump_thunk_\reg, SYM_L_GLOBAL)
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_UNDEFINED
        ANNOTATE_NOENDBR
        POLINE \reg
        ANNOTATE_UNRET_SAFE
 
 #define PVH_DS_SEL             (PVH_GDT_ENTRY_DS * 8)
 
 SYM_CODE_START_LOCAL(pvh_start_xen)
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_END_OF_STACK
        cld
 
        lgdt (_pa(gdt))
 
 SYM_CODE_START(xen_early_idt_handler_array)
        i = 0
        .rept NUM_EXCEPTION_VECTORS
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_UNDEFINED
        ENDBR
        pop %rcx
        pop %r11
  * rsp->rax            }
  */
 SYM_CODE_START(xen_iret)
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_UNDEFINED
        ANNOTATE_NOENDBR
        pushq $0
        jmp hypercall_iret
 
 #ifdef CONFIG_XEN_PV
        __INIT
 SYM_CODE_START(startup_xen)
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_END_OF_STACK
        ANNOTATE_NOENDBR
        cld
 
 #ifdef CONFIG_XEN_PV_SMP
 .pushsection .text
 SYM_CODE_START(asm_cpu_bringup_and_idle)
-       UNWIND_HINT_EMPTY
+       UNWIND_HINT_END_OF_STACK
        ENDBR
 
        call cpu_bringup_and_idle
 
 
 #ifndef __ASSEMBLY__
 
-#define UNWIND_HINT(type, sp_reg, sp_offset, signal, end)      \
+#define UNWIND_HINT(type, sp_reg, sp_offset, signal)   \
        "987: \n\t"                                             \
        ".pushsection .discard.unwind_hints\n\t"                \
        /* struct unwind_hint */                                \
        ".byte " __stringify(sp_reg) "\n\t"                     \
        ".byte " __stringify(type) "\n\t"                       \
        ".byte " __stringify(signal) "\n\t"                     \
-       ".byte " __stringify(end) "\n\t"                        \
        ".balign 4 \n\t"                                        \
        ".popsection\n\t"
 
  * the debuginfo as necessary.  It will also warn if it sees any
  * inconsistencies.
  */
-.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0 end=0
+.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0
 .Lhere_\@:
        .pushsection .discard.unwind_hints
                /* struct unwind_hint */
                .byte \sp_reg
                .byte \type
                .byte \signal
-               .byte \end
                .balign 4
        .popsection
 .endm
 
 #ifndef __ASSEMBLY__
 
-#define UNWIND_HINT(type, sp_reg, sp_offset, signal, end) "\n\t"
+#define UNWIND_HINT(type, sp_reg, sp_offset, signal) "\n\t"
 #define STACK_FRAME_NON_STANDARD(func)
 #define STACK_FRAME_NON_STANDARD_FP(func)
 #define ANNOTATE_NOENDBR
 #define ASM_REACHABLE
 #else
 #define ANNOTATE_INTRA_FUNCTION_CALL
-.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0 end=0
+.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0
 .endm
 .macro STACK_FRAME_NON_STANDARD func:req
 .endm
 
        u8              sp_reg;
        u8              type;
        u8              signal;
-       u8              end;
 };
 
 #endif /* __ASSEMBLY__ */
 
 /*
+ * UNWIND_HINT_TYPE_UNDEFINED: A blind spot in ORC coverage which can result in
+ * a truncated and unreliable stack unwind.
+ *
+ * UNWIND_HINT_TYPE_END_OF_STACK: The end of the kernel stack unwind before
+ * hitting user entry, boot code, or fork entry (when there are no pt_regs
+ * available).
+ *
  * UNWIND_HINT_TYPE_CALL: Indicates that sp_reg+sp_offset resolves to PREV_SP
  * (the caller's SP right before it made the call).  Used for all callable
  * functions, i.e. all C code and all callable asm functions.
  * UNWIND_HINT_TYPE_REGS_PARTIAL: Used in entry code to indicate that
  * sp_reg+sp_offset points to the iret return frame.
  *
- * UNWIND_HINT_FUNC: Generate the unwind metadata of a callable function.
+ * UNWIND_HINT_TYPE_FUNC: Generate the unwind metadata of a callable function.
  * Useful for code which doesn't have an ELF function annotation.
  *
- * UNWIND_HINT_ENTRY: machine entry without stack, SYSCALL/SYSENTER etc.
+ * UNWIND_HINT_TYPE_{SAVE,RESTORE}: Save the unwind metadata at a certain
+ * location so that it can be restored later.
  */
-#define UNWIND_HINT_TYPE_CALL          0
-#define UNWIND_HINT_TYPE_REGS          1
-#define UNWIND_HINT_TYPE_REGS_PARTIAL  2
+#define UNWIND_HINT_TYPE_UNDEFINED     0
+#define UNWIND_HINT_TYPE_END_OF_STACK  1
+#define UNWIND_HINT_TYPE_CALL          2
+#define UNWIND_HINT_TYPE_REGS          3
+#define UNWIND_HINT_TYPE_REGS_PARTIAL  4
 /* The below hint types don't have corresponding ORC types */
-#define UNWIND_HINT_TYPE_FUNC          3
-#define UNWIND_HINT_TYPE_SAVE          4
-#define UNWIND_HINT_TYPE_RESTORE       5
+#define UNWIND_HINT_TYPE_FUNC          5
+#define UNWIND_HINT_TYPE_SAVE          6
+#define UNWIND_HINT_TYPE_RESTORE       7
 
 #endif /* _LINUX_OBJTOOL_TYPES_H */
 
         * whitelisted .o files which didn't get objtool generation.
         */
        orc_a = g_orc_table + (a - g_orc_ip_table);
-       return orc_a->sp_reg == ORC_REG_UNDEFINED && !orc_a->end ? -1 : 1;
+       return orc_a->type == ORC_TYPE_UNDEFINED ? -1 : 1;
 }
 
 static void *sort_orctable(void *arg)
 
 #define ORC_REG_SP_INDIRECT            9
 #define ORC_REG_MAX                    15
 
-#define ORC_TYPE_CALL                  0
-#define ORC_TYPE_REGS                  1
-#define ORC_TYPE_REGS_PARTIAL          2
+#define ORC_TYPE_UNDEFINED             0
+#define ORC_TYPE_END_OF_STACK          1
+#define ORC_TYPE_CALL                  2
+#define ORC_TYPE_REGS                  3
+#define ORC_TYPE_REGS_PARTIAL          4
 
 #ifndef __ASSEMBLY__
 #include <asm/byteorder.h>
 #if defined(__LITTLE_ENDIAN_BITFIELD)
        unsigned        sp_reg:4;
        unsigned        bp_reg:4;
-       unsigned        type:2;
+       unsigned        type:3;
        unsigned        signal:1;
-       unsigned        end:1;
 #elif defined(__BIG_ENDIAN_BITFIELD)
        unsigned        bp_reg:4;
        unsigned        sp_reg:4;
        unsigned        unused:4;
-       unsigned        end:1;
        unsigned        signal:1;
-       unsigned        type:2;
+       unsigned        type:3;
 #endif
 } __packed;
 
 
        u8              sp_reg;
        u8              type;
        u8              signal;
-       u8              end;
 };
 
 #endif /* __ASSEMBLY__ */
 
 /*
+ * UNWIND_HINT_TYPE_UNDEFINED: A blind spot in ORC coverage which can result in
+ * a truncated and unreliable stack unwind.
+ *
+ * UNWIND_HINT_TYPE_END_OF_STACK: The end of the kernel stack unwind before
+ * hitting user entry, boot code, or fork entry (when there are no pt_regs
+ * available).
+ *
  * UNWIND_HINT_TYPE_CALL: Indicates that sp_reg+sp_offset resolves to PREV_SP
  * (the caller's SP right before it made the call).  Used for all callable
  * functions, i.e. all C code and all callable asm functions.
  * UNWIND_HINT_TYPE_REGS_PARTIAL: Used in entry code to indicate that
  * sp_reg+sp_offset points to the iret return frame.
  *
- * UNWIND_HINT_FUNC: Generate the unwind metadata of a callable function.
+ * UNWIND_HINT_TYPE_FUNC: Generate the unwind metadata of a callable function.
  * Useful for code which doesn't have an ELF function annotation.
  *
- * UNWIND_HINT_ENTRY: machine entry without stack, SYSCALL/SYSENTER etc.
+ * UNWIND_HINT_TYPE_{SAVE,RESTORE}: Save the unwind metadata at a certain
+ * location so that it can be restored later.
  */
-#define UNWIND_HINT_TYPE_CALL          0
-#define UNWIND_HINT_TYPE_REGS          1
-#define UNWIND_HINT_TYPE_REGS_PARTIAL  2
+#define UNWIND_HINT_TYPE_UNDEFINED     0
+#define UNWIND_HINT_TYPE_END_OF_STACK  1
+#define UNWIND_HINT_TYPE_CALL          2
+#define UNWIND_HINT_TYPE_REGS          3
+#define UNWIND_HINT_TYPE_REGS_PARTIAL  4
 /* The below hint types don't have corresponding ORC types */
-#define UNWIND_HINT_TYPE_FUNC          3
-#define UNWIND_HINT_TYPE_SAVE          4
-#define UNWIND_HINT_TYPE_RESTORE       5
+#define UNWIND_HINT_TYPE_FUNC          5
+#define UNWIND_HINT_TYPE_SAVE          6
+#define UNWIND_HINT_TYPE_RESTORE       7
 
 #endif /* _LINUX_OBJTOOL_TYPES_H */
 
        memcpy(&state->regs, &initial_func_cfi.regs,
               CFI_NUM_REGS * sizeof(struct cfi_reg));
        state->stack_size = initial_func_cfi.cfa.offset;
+       state->type = UNWIND_HINT_TYPE_CALL;
 }
 
 static int read_unwind_hints(struct objtool_file *file)
                cfi.cfa.offset = bswap_if_needed(file->elf, hint->sp_offset);
                cfi.type = hint->type;
                cfi.signal = hint->signal;
-               cfi.end = hint->end;
 
                insn->cfi = cfi_hash_find_or_add(&cfi);
        }
 
 static const char *orc_type_name(unsigned int type)
 {
        switch (type) {
+       case ORC_TYPE_UNDEFINED:
+               return "(und)";
+       case ORC_TYPE_END_OF_STACK:
+               return "end";
        case ORC_TYPE_CALL:
                return "call";
        case ORC_TYPE_REGS:
                        printf("%llx:", (unsigned long long)(orc_ip_addr + (i * sizeof(int)) + orc_ip[i]));
                }
 
+               printf("type:%s", orc_type_name(orc[i].type));
 
                printf(" sp:");
 
 
                print_reg(orc[i].bp_reg, bswap_if_needed(&dummy_elf, orc[i].bp_offset));
 
-               printf(" type:%s signal:%d end:%d\n",
-                      orc_type_name(orc[i].type), orc[i].signal, orc[i].end);
+               printf(" signal:%d\n", orc[i].signal);
        }
 
        elf_end(elf);
 
        memset(orc, 0, sizeof(*orc));
 
        if (!cfi) {
-               orc->end = 0;
-               orc->sp_reg = ORC_REG_UNDEFINED;
+               /*
+                * This is usually either unreachable nops/traps (which don't
+                * trigger unreachable instruction warnings), or
+                * STACK_FRAME_NON_STANDARD functions.
+                */
+               orc->type = ORC_TYPE_UNDEFINED;
                return 0;
        }
 
        switch (cfi->type) {
+       case UNWIND_HINT_TYPE_UNDEFINED:
+               orc->type = ORC_TYPE_UNDEFINED;
+               return 0;
+       case UNWIND_HINT_TYPE_END_OF_STACK:
+               orc->type = ORC_TYPE_END_OF_STACK;
+               return 0;
        case UNWIND_HINT_TYPE_CALL:
                orc->type = ORC_TYPE_CALL;
                break;
                return -1;
        }
 
-       orc->end = cfi->end;
        orc->signal = cfi->signal;
 
-       if (cfi->cfa.base == CFI_UNDEFINED) {
-               orc->sp_reg = ORC_REG_UNDEFINED;
-               return 0;
-       }
-
        switch (cfi->cfa.base) {
        case CFI_SP:
                orc->sp_reg = ORC_REG_SP;
        struct orc_list_entry *entry;
        struct list_head orc_list;
 
-       struct orc_entry null = {
-               .sp_reg  = ORC_REG_UNDEFINED,
-               .bp_reg  = ORC_REG_UNDEFINED,
-               .type    = ORC_TYPE_CALL,
-       };
+       struct orc_entry null = { .type = ORC_TYPE_UNDEFINED };
 
        /* Build a deduplicated list of ORC entries: */
        INIT_LIST_HEAD(&orc_list);