Example #1
0
static int get_frame_info(struct mips_frame_info *info)
{
	union mips_instruction *ip = info->func;
	int i, max_insns =
		min(128UL, info->func_size / sizeof(union mips_instruction));

	info->pc_offset = -1;
	info->frame_size = 0;

	for (i = 0; i < max_insns; i++, ip++) {

		if (is_jal_jalr_jr_ins(ip))
			break;
		if (!info->frame_size) {
			if (is_sp_move_ins(ip))
				info->frame_size = - ip->i_format.simmediate;
			continue;
		}
		if (info->pc_offset == -1 && is_ra_save_ins(ip)) {
			info->pc_offset =
				ip->i_format.simmediate / sizeof(long);
			break;
		}
	}
	if (info->frame_size && info->pc_offset >= 0) /* nested */
		return 0;
	if (info->pc_offset < 0) /* leaf */
		return 1;
	/* prologue seems boggus... */
	return -1;
}
static inline int unwind_user_frame(struct stackframe *old_frame,
				    const unsigned int max_instr_check)
{
	struct stackframe new_frame = *old_frame;
	off_t ra_offset = 0;
	size_t stack_size = 0;
	unsigned long addr;

	if (old_frame->pc == 0 || old_frame->sp == 0 || old_frame->ra == 0)
		return -9;

	for (addr = new_frame.pc; (addr + max_instr_check > new_frame.pc)
		&& (!ra_offset || !stack_size); --addr) {
		union mips_instruction ip;

		if (get_mem(addr, (unsigned long *) &ip))
			return -11;

		if (is_sp_move_ins(&ip)) {
			int stack_adjustment = ip.i_format.simmediate;
			if (stack_adjustment > 0)
				/* This marks the end of the previous function,
				   which means we overran. */
				break;
			stack_size = (unsigned long) stack_adjustment;
		} else if (is_ra_save_ins(&ip)) {
			int ra_slot = ip.i_format.simmediate;
			if (ra_slot < 0)
				/* This shouldn't happen. */
				break;
			ra_offset = ra_slot;
		} else if (is_end_of_function_marker(&ip))
			break;
	}

	if (!ra_offset || !stack_size)
		goto done;

	if (ra_offset) {
		new_frame.ra = old_frame->sp + ra_offset;
		if (get_mem(new_frame.ra, &(new_frame.ra)))
			return -13;
	}

	if (stack_size) {
		new_frame.sp = old_frame->sp + stack_size;
		if (get_mem(new_frame.sp, &(new_frame.sp)))
			return -14;
	}

	if (new_frame.sp > old_frame->sp)
		return -2;

done:
	new_frame.pc = old_frame->ra;
	*old_frame = new_frame;

	return 0;
}
static int get_frame_info(struct mips_frame_info *info)
{
	union mips_instruction *ip = info->func;
	unsigned max_insns = info->func_size / sizeof(union mips_instruction);
	unsigned i;

	info->pc_offset = -1;
	info->frame_size = 0;

	if (!ip)
		goto err;

	if (max_insns == 0)
		max_insns = 128U;	/*                       */
	max_insns = min(128U, max_insns);

	for (i = 0; i < max_insns; i++, ip++) {

		if (is_jal_jalr_jr_ins(ip))
			break;
		if (!info->frame_size) {
			if (is_sp_move_ins(ip))
				info->frame_size = - ip->i_format.simmediate;
			continue;
		}
		if (info->pc_offset == -1 && is_ra_save_ins(ip)) {
			info->pc_offset =
				ip->i_format.simmediate / sizeof(long);
			break;
		}
	}
	if (info->frame_size && info->pc_offset >= 0) /*        */
		return 0;
	if (info->pc_offset < 0) /*      */
		return 1;
	/*                          */
err:
	return -1;
}