Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #include <linux/sched.h>
0003 #include <linux/sched/task.h>
0004 #include <linux/sched/task_stack.h>
0005 #include <linux/interrupt.h>
0006 #include <asm/sections.h>
0007 #include <asm/ptrace.h>
0008 #include <asm/bitops.h>
0009 #include <asm/stacktrace.h>
0010 #include <asm/unwind.h>
0011 
0012 unsigned long unwind_get_return_address(struct unwind_state *state)
0013 {
0014     if (unwind_done(state))
0015         return 0;
0016     return __kernel_text_address(state->ip) ? state->ip : 0;
0017 }
0018 EXPORT_SYMBOL_GPL(unwind_get_return_address);
0019 
0020 static bool outside_of_stack(struct unwind_state *state, unsigned long sp)
0021 {
0022     return (sp <= state->sp) ||
0023         (sp > state->stack_info.end - sizeof(struct stack_frame));
0024 }
0025 
0026 static bool update_stack_info(struct unwind_state *state, unsigned long sp)
0027 {
0028     struct stack_info *info = &state->stack_info;
0029     unsigned long *mask = &state->stack_mask;
0030 
0031     /* New stack pointer leaves the current stack */
0032     if (get_stack_info(sp, state->task, info, mask) != 0 ||
0033         !on_stack(info, sp, sizeof(struct stack_frame)))
0034         /* 'sp' does not point to a valid stack */
0035         return false;
0036     return true;
0037 }
0038 
0039 static inline bool is_final_pt_regs(struct unwind_state *state,
0040                     struct pt_regs *regs)
0041 {
0042     /* user mode or kernel thread pt_regs at the bottom of task stack */
0043     if (task_pt_regs(state->task) == regs)
0044         return true;
0045 
0046     /* user mode pt_regs at the bottom of irq stack */
0047     return state->stack_info.type == STACK_TYPE_IRQ &&
0048            state->stack_info.end - sizeof(struct pt_regs) == (unsigned long)regs &&
0049            READ_ONCE_NOCHECK(regs->psw.mask) & PSW_MASK_PSTATE;
0050 }
0051 
0052 bool unwind_next_frame(struct unwind_state *state)
0053 {
0054     struct stack_info *info = &state->stack_info;
0055     struct stack_frame *sf;
0056     struct pt_regs *regs;
0057     unsigned long sp, ip;
0058     bool reliable;
0059 
0060     regs = state->regs;
0061     if (unlikely(regs)) {
0062         sp = state->sp;
0063         sf = (struct stack_frame *) sp;
0064         ip = READ_ONCE_NOCHECK(sf->gprs[8]);
0065         reliable = false;
0066         regs = NULL;
0067         /* skip bogus %r14 or if is the same as regs->psw.addr */
0068         if (!__kernel_text_address(ip) || state->ip == unwind_recover_ret_addr(state, ip)) {
0069             state->regs = NULL;
0070             return unwind_next_frame(state);
0071         }
0072     } else {
0073         sf = (struct stack_frame *) state->sp;
0074         sp = READ_ONCE_NOCHECK(sf->back_chain);
0075         if (likely(sp)) {
0076             /* Non-zero back-chain points to the previous frame */
0077             if (unlikely(outside_of_stack(state, sp))) {
0078                 if (!update_stack_info(state, sp))
0079                     goto out_err;
0080             }
0081             sf = (struct stack_frame *) sp;
0082             ip = READ_ONCE_NOCHECK(sf->gprs[8]);
0083             reliable = true;
0084         } else {
0085             /* No back-chain, look for a pt_regs structure */
0086             sp = state->sp + STACK_FRAME_OVERHEAD;
0087             if (!on_stack(info, sp, sizeof(struct pt_regs)))
0088                 goto out_err;
0089             regs = (struct pt_regs *) sp;
0090             if (is_final_pt_regs(state, regs))
0091                 goto out_stop;
0092             ip = READ_ONCE_NOCHECK(regs->psw.addr);
0093             sp = READ_ONCE_NOCHECK(regs->gprs[15]);
0094             if (unlikely(outside_of_stack(state, sp))) {
0095                 if (!update_stack_info(state, sp))
0096                     goto out_err;
0097             }
0098             reliable = true;
0099         }
0100     }
0101 
0102     /* Sanity check: ABI requires SP to be aligned 8 bytes. */
0103     if (sp & 0x7)
0104         goto out_err;
0105 
0106     /* Update unwind state */
0107     state->sp = sp;
0108     state->regs = regs;
0109     state->reliable = reliable;
0110     state->ip = unwind_recover_ret_addr(state, ip);
0111     return true;
0112 
0113 out_err:
0114     state->error = true;
0115 out_stop:
0116     state->stack_info.type = STACK_TYPE_UNKNOWN;
0117     return false;
0118 }
0119 EXPORT_SYMBOL_GPL(unwind_next_frame);
0120 
0121 void __unwind_start(struct unwind_state *state, struct task_struct *task,
0122             struct pt_regs *regs, unsigned long first_frame)
0123 {
0124     struct stack_info *info = &state->stack_info;
0125     struct stack_frame *sf;
0126     unsigned long ip, sp;
0127 
0128     memset(state, 0, sizeof(*state));
0129     state->task = task;
0130     state->regs = regs;
0131 
0132     /* Don't even attempt to start from user mode regs: */
0133     if (regs && user_mode(regs)) {
0134         info->type = STACK_TYPE_UNKNOWN;
0135         return;
0136     }
0137 
0138     /* Get the instruction pointer from pt_regs or the stack frame */
0139     if (regs) {
0140         ip = regs->psw.addr;
0141         sp = regs->gprs[15];
0142     } else if (task == current) {
0143         sp = current_frame_address();
0144     } else {
0145         sp = task->thread.ksp;
0146     }
0147 
0148     /* Get current stack pointer and initialize stack info */
0149     if (!update_stack_info(state, sp)) {
0150         /* Something is wrong with the stack pointer */
0151         info->type = STACK_TYPE_UNKNOWN;
0152         state->error = true;
0153         return;
0154     }
0155 
0156     if (!regs) {
0157         /* Stack frame is within valid stack */
0158         sf = (struct stack_frame *)sp;
0159         ip = READ_ONCE_NOCHECK(sf->gprs[8]);
0160     }
0161 
0162     /* Update unwind state */
0163     state->sp = sp;
0164     state->reliable = true;
0165     state->ip = unwind_recover_ret_addr(state, ip);
0166 
0167     if (!first_frame)
0168         return;
0169     /* Skip through the call chain to the specified starting frame */
0170     while (!unwind_done(state)) {
0171         if (on_stack(&state->stack_info, first_frame, sizeof(struct stack_frame))) {
0172             if (state->sp >= first_frame)
0173                 break;
0174         }
0175         unwind_next_frame(state);
0176     }
0177 }
0178 EXPORT_SYMBOL_GPL(__unwind_start);