예제 #1
0
/* routine to determine if a word value represents a return address
 * This routine checks to see if the word value points to an address that
 * immediately follows a branch instruction.
 */
int is_ARM_return_address(int pid, mapinfo *milist, unsigned int value)
{
	unsigned int addr;
	unsigned int data;
	unsigned int rel_addr;
	const mapinfo *mi;

	/* check 4 bytes before the address */
	addr = value-4;

	/* FIXTHIS - check map to see if this is in text segment */
	rel_addr = addr;
	mi = pc_to_mapinfo(milist, addr, &rel_addr);
	if (mi == NULL) {
		/* address is not in the executable memory map */
		/* note that the [stack] map is not executable,
 		 * and has already been filtered from the map list
 		*/
		return 0;
	}

	DLOG("checking addr=0x%08lx for instruction\n", addr);

	data = ptrace(PTRACE_PEEKTEXT, pid, (void*)addr, NULL);

	/* detect failure to read data from process memory */
	if (data==0xffffffff) {
		return 0;
	}

	DLOG("instruction at %08lx is %08lx\n", addr, data);

	if (is_ARM_bl(data)) {	
		DLOG("this instruction is a branch and link, with offset %d and target 0x%08x\n",
			branch_offset(data), branch_target(addr, data));
		return 1;
	} else {
		return 0;
	}
}
static int patch_alt_instruction(unsigned int *src, unsigned int *dest,
				 unsigned int *alt_start, unsigned int *alt_end)
{
	unsigned int instr;

	instr = *src;

	if (instr_is_relative_branch(*src)) {
		unsigned int *target = (unsigned int *)branch_target(src);

		/* Branch within the section doesn't need translating */
		if (target < alt_start || target > alt_end) {
			instr = translate_branch(dest, src);
			if (!instr)
				return 1;
		}
	}

	patch_instruction(dest, instr);

	return 0;
}
예제 #3
0
int guess_unwind_backtrace_with_ptrace(int pid, mapinfo *milist,
	unsigned int sp_list[], int *frame0_pc_sane)
{
	struct pt_regs r;

	unsigned int sp, pc, lr, fp, p, addr, data;
	unsigned int func_addr, exec_addr;
	unsigned int stack_size;
	int frame_no;
	int i;

	/* move up stack looking at addresses */

	/* set up regs for backtrace */
	if (ptrace(PTRACE_GETREGS, pid, 0, &r)) return;
	sp = r.ARM_sp;
	pc = r.ARM_pc;
	lr = r.ARM_lr;
	fp = r.ARM_fp;

	/* find out if LR points to an instruction after a BL */
	DLOG("lr=0x%08x\n", lr);

	/* check 4 bytes before the address */
	if (is_ARM_return_address(pid, milist, lr)) {
		DLOG("lr points to a branch and link instruction\n");
	} else {
		DLOG("lr doesn't point to a branch link instruction\n");
		return 0;
	}

	addr = lr-4;
	data = ptrace(PTRACE_PEEKTEXT, pid, (void*)addr, NULL);

	DLOG("addr+offset = 0x%08x\n", (int)(addr) + branch_offset(data));

	/* determine function called by branch */
	func_addr = branch_target(addr, data);
	DLOG("called function is: 0x%08lx\n", func_addr);
	exec_addr = pc;
	DLOG("execution offset in function is: %08lx + 0x%x\n", func_addr,
		exec_addr-func_addr);

	LOG("Crash occured at PC: 0x%08x\n", pc);
	exec_addr = pc;
	frame_no = 0;

	LOG("#%d:0x%08lx in function 0x%08lx at offset 0x%lx\n",
		frame_no, exec_addr, func_addr, exec_addr-func_addr);

	/* start of loop */
	/* desired output format(final):
	 * <frame number>:<execution addr> in function <function_name> at <line_no>
	 * desired output format(unprocessed):
	 * <frame number>:<execution addr> in function <function_addr> at offset 
	 */

	/* scan stack looking for return addresses */
	stack_size = stack_map.end - sp;
	for ( i=0; i<(stack_size/4); i++ ) {
		data = ptrace(PTRACE_PEEKTEXT, pid, (void*)sp, NULL);
		DLOG("checking value 0x%08lx at stack position 0x%08lx\n", data, sp);
		if (is_ARM_return_address(pid, milist, data)) {
			DLOG("at sp=%08lx: possible return address 0x%08lx on stack\n",
				sp, data);

			addr = data-4;
			data = ptrace(PTRACE_PEEKTEXT, pid, (void*)addr, NULL);

			/* determine function called by branch */
			func_addr = branch_target(addr, data);
			DLOG("called function is: 0x%08lx\n", func_addr);
			exec_addr = addr;
			DLOG("execution offset in function is: %08lx + 0x%x\n", func_addr,
				exec_addr-func_addr);

			frame_no++;

			/* FIXTHIS - use pc_to_mapinfo() to find the section name */

			LOG("#%d:0x%08lx in function 0x%08lx at offset 0x%lx\n",
				frame_no, exec_addr, func_addr, exec_addr-func_addr);
		}
		sp += 4;
	}

	return frame_no;
}