void __unwind_start(struct unwind_state *state, struct task_struct *task, struct pt_regs *regs, unsigned long *first_frame) { unsigned long *bp; memset(state, 0, sizeof(*state)); state->task = task; state->got_irq = (regs); /* Don't even attempt to start from user mode regs: */ if (regs && user_mode(regs)) { state->stack_info.type = STACK_TYPE_UNKNOWN; return; } bp = get_frame_pointer(task, regs); /* Initialize stack info and make sure the frame data is accessible: */ get_stack_info(bp, state->task, &state->stack_info, &state->stack_mask); update_stack_state(state, bp); /* * The caller can provide the address of the first frame directly * (first_frame) or indirectly (regs->sp) to indicate which stack frame * to start unwinding at. Skip ahead until we reach it. */ while (!unwind_done(state) && (!on_stack(&state->stack_info, first_frame, sizeof(long)) || state->bp < first_frame)) unwind_next_frame(state); }
bool unwind_next_frame(struct unwind_state *state) { struct stack_info *info = &state->stack_info; if (unwind_done(state)) return false; do { for (state->sp++; state->sp < info->end; state->sp++) if (__kernel_text_address(*state->sp)) return true; state->sp = info->next_sp; } while (!get_stack_info(state->sp, state->task, info, &state->stack_mask)); return false; }
void __unwind_start(struct unwind_state *state, struct task_struct *task, struct pt_regs *regs, unsigned long *first_frame) { unsigned long *bp, *frame; size_t len; memset(state, 0, sizeof(*state)); state->task = task; /* don't even attempt to start from user mode regs */ if (regs && user_mode(regs)) { state->stack_info.type = STACK_TYPE_UNKNOWN; return; } /* set up the starting stack frame */ bp = get_frame_pointer(task, regs); regs = decode_frame_pointer(bp); if (regs) { state->regs = regs; frame = (unsigned long *)regs; len = sizeof(*regs); } else { state->bp = bp; frame = bp; len = FRAME_HEADER_SIZE; } /* initialize stack info and make sure the frame data is accessible */ get_stack_info(frame, state->task, &state->stack_info, &state->stack_mask); update_stack_state(state, frame, len); /* * The caller can provide the address of the first frame directly * (first_frame) or indirectly (regs->sp) to indicate which stack frame * to start unwinding at. Skip ahead until we reach it. */ while (!unwind_done(state) && (!on_stack(&state->stack_info, first_frame, sizeof(long)) || state->bp < first_frame)) unwind_next_frame(state); }
static bool update_stack_state(struct unwind_state *state, void *addr, size_t len) { struct stack_info *info = &state->stack_info; /* * If addr isn't on the current stack, switch to the next one. * * We may have to traverse multiple stacks to deal with the possibility * that 'info->next_sp' could point to an empty stack and 'addr' could * be on a subsequent stack. */ while (!on_stack(info, addr, len)) if (get_stack_info(info->next_sp, state->task, info, &state->stack_mask)) return false; return true; }
void __unwind_start(struct unwind_state *state, struct task_struct *task, struct pt_regs *regs, unsigned long *first_frame) { memset(state, 0, sizeof(*state)); state->task = task; state->sp = first_frame; get_stack_info(first_frame, state->task, &state->stack_info, &state->stack_mask); /* * The caller can provide the address of the first frame directly * (first_frame) or indirectly (regs->sp) to indicate which stack frame * to start unwinding at. Skip ahead until we reach it. */ if (!unwind_done(state) && (!on_stack(&state->stack_info, first_frame, sizeof(long)) || !__kernel_text_address(*first_frame))) unwind_next_frame(state); }
static void unwind_dump(struct unwind_state *state) { static bool dumped_before = false; bool prev_zero, zero = false; unsigned long word, *sp; struct stack_info stack_info = {0}; unsigned long visit_mask = 0; if (dumped_before) return; dumped_before = true; printk_deferred("unwind stack type:%d next_sp:%p mask:0x%lx graph_idx:%d\n", state->stack_info.type, state->stack_info.next_sp, state->stack_mask, state->graph_idx); for (sp = state->orig_sp; sp; sp = PTR_ALIGN(stack_info.next_sp, sizeof(long))) { if (get_stack_info(sp, state->task, &stack_info, &visit_mask)) break; for (; sp < stack_info.end; sp++) { word = READ_ONCE_NOCHECK(*sp); prev_zero = zero; zero = word == 0; if (zero) { if (!prev_zero) printk_deferred("%p: %0*x ...\n", sp, BITS_PER_LONG/4, 0); continue; } printk_deferred("%p: %0*lx (%pB)\n", sp, BITS_PER_LONG/4, word, (void *)word); } } }
void _fake_processreturnSRet_1(FuncContext *pCtxt) { get_stack_info(pCtxt->m_uiESP1, pCtxt->m_uiEBP1); _fake_processreturnSRet_2(pCtxt); }
void _fake_processreturnSRet_2(FuncContext *pCtxt) { get_stack_info(pCtxt->m_uiESP2, pCtxt->m_uiEBP2); pCtxt->m_iArgsLen = pCtxt->m_uiEBP1->pCtxt->m_uiEBP2-8; memcpy(pCtxt->m_acArgs, (void *)(pCtxt->m_uiEBP2+8), pCtxt->m_iArgsLen); }
void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, unsigned long *stack, char *log_lvl) { struct unwind_state state; struct stack_info stack_info = {0}; unsigned long visit_mask = 0; int graph_idx = 0; printk("%sCall Trace:\n", log_lvl); unwind_start(&state, task, regs, stack); stack = stack ? : get_stack_pointer(task, regs); /* * Iterate through the stacks, starting with the current stack pointer. * Each stack has a pointer to the next one. * * x86-64 can have several stacks: * - task stack * - interrupt stack * - HW exception stacks (double fault, nmi, debug, mce) * * x86-32 can have up to three stacks: * - task stack * - softirq stack * - hardirq stack */ for (regs = NULL; stack; stack = stack_info.next_sp) { const char *stack_name; /* * If we overflowed the task stack into a guard page, jump back * to the bottom of the usable stack. */ if (task_stack_page(task) - (void *)stack < PAGE_SIZE) stack = task_stack_page(task); if (get_stack_info(stack, task, &stack_info, &visit_mask)) break; stack_name = stack_type_name(stack_info.type); if (stack_name) printk("%s <%s>\n", log_lvl, stack_name); /* * Scan the stack, printing any text addresses we find. At the * same time, follow proper stack frames with the unwinder. * * Addresses found during the scan which are not reported by * the unwinder are considered to be additional clues which are * sometimes useful for debugging and are prefixed with '?'. * This also serves as a failsafe option in case the unwinder * goes off in the weeds. */ for (; stack < stack_info.end; stack++) { unsigned long real_addr; int reliable = 0; unsigned long addr = READ_ONCE_NOCHECK(*stack); unsigned long *ret_addr_p = unwind_get_return_address_ptr(&state); if (!__kernel_text_address(addr)) continue; /* * Don't print regs->ip again if it was already printed * by __show_regs() below. */ if (regs && stack == ®s->ip) { unwind_next_frame(&state); continue; } if (stack == ret_addr_p) reliable = 1; /* * When function graph tracing is enabled for a * function, its return address on the stack is * replaced with the address of an ftrace handler * (return_to_handler). In that case, before printing * the "real" address, we want to print the handler * address as an "unreliable" hint that function graph * tracing was involved. */ real_addr = ftrace_graph_ret_addr(task, &graph_idx, addr, stack); if (real_addr != addr) printk_stack_address(addr, 0, log_lvl); printk_stack_address(real_addr, reliable, log_lvl); if (!reliable) continue; /* * Get the next frame from the unwinder. No need to * check for an error: if anything goes wrong, the rest * of the addresses will just be printed as unreliable. */ unwind_next_frame(&state); /* if the frame has entry regs, print them */ regs = unwind_get_entry_regs(&state); if (regs) __show_regs(regs, 0); } if (stack_name) printk("%s </%s>\n", log_lvl, stack_name); } }
static bool update_stack_state(struct unwind_state *state, unsigned long *next_bp) { struct stack_info *info = &state->stack_info; enum stack_type prev_type = info->type; struct pt_regs *regs; unsigned long *frame, *prev_frame_end, *addr_p, addr; size_t len; if (state->regs) prev_frame_end = (void *)state->regs + regs_size(state->regs); else prev_frame_end = (void *)state->bp + FRAME_HEADER_SIZE; /* Is the next frame pointer an encoded pointer to pt_regs? */ regs = decode_frame_pointer(next_bp); if (regs) { frame = (unsigned long *)regs; len = regs_size(regs); state->got_irq = true; } else { frame = next_bp; len = FRAME_HEADER_SIZE; } /* * If the next bp isn't on the current stack, switch to the next one. * * We may have to traverse multiple stacks to deal with the possibility * that info->next_sp could point to an empty stack and the next bp * could be on a subsequent stack. */ while (!on_stack(info, frame, len)) if (get_stack_info(info->next_sp, state->task, info, &state->stack_mask)) return false; /* Make sure it only unwinds up and doesn't overlap the prev frame: */ if (state->orig_sp && state->stack_info.type == prev_type && frame < prev_frame_end) return false; /* Move state to the next frame: */ if (regs) { state->regs = regs; state->bp = NULL; } else { state->bp = next_bp; state->regs = NULL; } /* Save the return address: */ if (state->regs && user_mode(state->regs)) state->ip = 0; else { addr_p = unwind_get_return_address_ptr(state); addr = READ_ONCE_TASK_STACK(state->task, *addr_p); state->ip = ftrace_graph_ret_addr(state->task, &state->graph_idx, addr, addr_p); } /* Save the original stack pointer for unwind_dump(): */ if (!state->orig_sp) state->orig_sp = frame; return true; }