コード例 #1
0
ファイル: unwind_frame.c プロジェクト: Gentoo-zh/linux-cjktty
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);
}
コード例 #2
0
ファイル: unwind_guess.c プロジェクト: boddob/linux
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;
}
コード例 #3
0
ファイル: unwind_frame.c プロジェクト: AshishNamdev/linux
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);
}
コード例 #4
0
ファイル: unwind_frame.c プロジェクト: xiasenlin/linux
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;
}
コード例 #5
0
ファイル: unwind_guess.c プロジェクト: boddob/linux
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);
}
コード例 #6
0
ファイル: unwind_frame.c プロジェクト: Gentoo-zh/linux-cjktty
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);
		}
	}
}
コード例 #7
0
ファイル: returnVal.cpp プロジェクト: cgclruntime/CSrc2Src
void _fake_processreturnSRet_1(FuncContext *pCtxt)
{
	get_stack_info(pCtxt->m_uiESP1, pCtxt->m_uiEBP1);
	_fake_processreturnSRet_2(pCtxt);
}
コード例 #8
0
ファイル: returnVal.cpp プロジェクト: cgclruntime/CSrc2Src
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);
}
コード例 #9
0
ファイル: dumpstack.c プロジェクト: AshishNamdev/linux
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 == &regs->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);
	}
}
コード例 #10
0
ファイル: unwind_frame.c プロジェクト: Gentoo-zh/linux-cjktty
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;
}