Beispiel #1
0
// XXX: very experimental
R_API int r_debug_step_soft(RDebug *dbg) {
	int ret;
	ut8 buf[32];
	RAnalOp op;
	ut64 pc0, pc1, pc2;
	if (r_debug_is_dead (dbg))
		return R_FALSE;
	pc0 = r_debug_reg_get (dbg, dbg->reg->name[R_REG_NAME_PC]);
	dbg->iob.read_at (dbg->iob.io, pc0, buf, sizeof (buf));
	ret = r_anal_op (dbg->anal, &op, pc0, buf, sizeof (buf));
//eprintf ("read from pc0 = 0x%llx\n", pc0);
	pc1 = pc0 + op.length;
//eprintf ("oplen = %d\n", op.length);
//eprintf ("breakpoint at pc1 = 0x%llx\n", pc1);
	// XXX: Does not works for 'ret'
	pc2 = op.jump? op.jump: 0;
//eprintf ("ADD SECOND BREAKPOINT FRO CALLS %llx\n", op.jump);
//eprintf ("breakpoint 2 at pc2 = 0x%llx\n", pc2);

	r_bp_add_sw (dbg->bp, pc1, 4, R_BP_PROT_EXEC);
	if (pc2) r_bp_add_sw (dbg->bp, pc2, 4, R_BP_PROT_EXEC);
	r_debug_continue (dbg);
//eprintf ("wait\n");
	//r_debug_wait (dbg);
//eprintf ("del\n");
	r_bp_del (dbg->bp, pc1);
	if (pc2) r_bp_del (dbg->bp, pc2);

	return ret;
}
Beispiel #2
0
R_API int r_debug_continue_until(RDebug *dbg, ut64 addr) {
	int has_bp;
	ut64 pc;

	if (r_debug_is_dead (dbg))
		return R_FALSE;

	// Check if there was another breakpoint set at addr
	has_bp = r_bp_get_in (dbg->bp, addr, R_BP_PROT_EXEC) != NULL;
	if (!has_bp)
		r_bp_add_sw (dbg->bp, addr, dbg->bpsize, R_BP_PROT_EXEC);

	// Continue until the bp is reached
	for (;;) {
		if (r_debug_is_dead (dbg))
			break;

		pc = r_debug_reg_get (dbg, dbg->reg->name[R_REG_NAME_PC]);
		if (pc == addr)
			break;
		if (r_bp_get_at (dbg->bp, pc))
                        break;
		r_debug_continue (dbg);
	}

	// Clean up if needed
	if (!has_bp)
		r_bp_del (dbg->bp, addr);

	return R_TRUE;
}
Beispiel #3
0
R_API int r_debug_step_over(RDebug *dbg, int steps) {
	RAnalOp op;
	ut8 buf[64];
	int ret = -1;
	if (r_debug_is_dead (dbg))
		return R_FALSE;
	if (dbg->h && dbg->h->step_over) {
		if (steps<1) steps = 1;
		while (steps--)
			if (!dbg->h->step_over (dbg))
				return R_FALSE;
		return R_TRUE;
	}
	if (dbg->anal && dbg->reg) {
		ut64 pc = r_debug_reg_get (dbg, dbg->reg->name[R_REG_NAME_PC]);
		dbg->iob.read_at (dbg->iob.io, pc, buf, sizeof (buf));
		r_anal_op (dbg->anal, &op, pc, buf, sizeof (buf));
		if (op.type & R_ANAL_OP_TYPE_CALL
		   || op.type & R_ANAL_OP_TYPE_UCALL) {
			ut64 bpaddr = pc + op.length;
			r_bp_add_sw (dbg->bp, bpaddr, 1, R_BP_PROT_EXEC);
			ret = r_debug_continue (dbg);
			r_bp_del (dbg->bp, bpaddr);
		} else {
			ret = r_debug_step (dbg, 1);
		}
	} else eprintf ("Undefined debugger backend\n");
	return ret;
}
Beispiel #4
0
/* 
 * Save 4096 bytes from %esp
 * TODO: Add support for reverse stack architectures
 * Also known as r_debug_inject()
 */
R_API ut64 r_debug_execute(RDebug *dbg, const ut8 *buf, int len, int restore) {
	int orig_sz;
	ut8 stackbackup[4096];
	ut8 *backup, *orig = NULL;
	RRegItem *ri, *risp, *ripc;
	ut64 rsp, rpc, ra0 = 0LL;
	if (r_debug_is_dead (dbg))
		return R_FALSE;
	ripc = r_reg_get (dbg->reg, dbg->reg->name[R_REG_NAME_PC], R_REG_TYPE_GPR);
	risp = r_reg_get (dbg->reg, dbg->reg->name[R_REG_NAME_SP], R_REG_TYPE_GPR);
	if (ripc) {
		r_debug_reg_sync (dbg, R_REG_TYPE_GPR, R_FALSE);
		orig = r_reg_get_bytes (dbg->reg, -1, &orig_sz);
		if (orig == NULL) {
			eprintf ("Cannot get register arena bytes\n");
			return 0LL;
		}
		rpc = r_reg_get_value (dbg->reg, ripc);
		rsp = r_reg_get_value (dbg->reg, risp);

		backup = malloc (len);
		if (backup == NULL) {
			free (orig);
			return 0LL;
		}
		dbg->iob.read_at (dbg->iob.io, rpc, backup, len);
		dbg->iob.read_at (dbg->iob.io, rsp, stackbackup, len);

		r_bp_add_sw (dbg->bp, rpc+len, dbg->bpsize, R_BP_PROT_EXEC);

		/* execute code here */
		dbg->iob.write_at (dbg->iob.io, rpc, buf, len);
	//r_bp_add_sw (dbg->bp, rpc+len, 4, R_BP_PROT_EXEC);
		r_debug_continue (dbg);
	//r_bp_del (dbg->bp, rpc+len);
		/* TODO: check if stopped in breakpoint or not */

		r_bp_del (dbg->bp, rpc+len);
		dbg->iob.write_at (dbg->iob.io, rpc, backup, len);
		if (restore) {
			dbg->iob.write_at (dbg->iob.io, rsp, stackbackup, len);
		}

		r_debug_reg_sync (dbg, R_REG_TYPE_GPR, R_FALSE);
		ri = r_reg_get (dbg->reg, dbg->reg->name[R_REG_NAME_A0], R_REG_TYPE_GPR);
		ra0 = r_reg_get_value (dbg->reg, ri);
		if (restore) {
			r_reg_set_bytes (dbg->reg, -1, orig, orig_sz);
		} else {
			r_reg_set_value (dbg->reg, ripc, rpc);
		}
		r_debug_reg_sync (dbg, R_REG_TYPE_GPR, R_TRUE);
		free (backup);
		free (orig);
		eprintf ("ra0=0x%08"PFMT64x"\n", ra0);
	} else eprintf ("r_debug_execute: Cannot get program counter\n");
	return (ra0);
}
Beispiel #5
0
R_API int r_debug_step_soft(RDebug *dbg) {
	ut8 buf[32];
	ut64 pc, sp;
	ut64 next[2];
	RAnalOp op;
	int br, i, ret;
	union {
		ut64 r64;
		ut32 r32[2];
	} sp_top;

	if (r_debug_is_dead (dbg))
		return R_FALSE;

	pc = r_debug_reg_get (dbg, dbg->reg->name[R_REG_NAME_PC]);
	sp = r_debug_reg_get (dbg, dbg->reg->name[R_REG_NAME_SP]);

	if (dbg->iob.read_at) {
		if (dbg->iob.read_at (dbg->iob.io, pc, buf, sizeof (buf)) < 0)
			return R_FALSE;
	} else return R_FALSE;

	if (!r_anal_op (dbg->anal, &op, pc, buf, sizeof (buf)))
		return R_FALSE;

	if (op.type == R_ANAL_OP_TYPE_ILL)
		return R_FALSE;

	switch (op.type) {
	case R_ANAL_OP_TYPE_RET:
		dbg->iob.read_at (dbg->iob.io, sp, (ut8 *)&sp_top, 8);
		next[0] = (dbg->bits == R_SYS_BITS_32) ? sp_top.r32[0] : sp_top.r64;
		br = 1;
		break;

	case R_ANAL_OP_TYPE_CJMP:
	case R_ANAL_OP_TYPE_CCALL:
		next[0] = op.jump;
		next[1] = op.fail;
		br = 2;
		break;

	case R_ANAL_OP_TYPE_CALL:
	case R_ANAL_OP_TYPE_JMP:
		next[0] = op.jump;
		br = 1;
		break;

	default:
		next[0] = op.addr + op.size;
		br = 1;
		break;
	}

	for (i = 0; i < br; i++)
		r_bp_add_sw (dbg->bp, next[i], dbg->bpsize, R_BP_PROT_EXEC);

	ret = r_debug_continue (dbg);

	for (i = 0; i < br; i++)
		r_bp_del (dbg->bp, next[i]);

	return ret;
}