Esempio n. 1
0
// XXX: Do this work correctly?
static RList *backtrace_x86_64_anal(RDebug *dbg, ut64 at) {
	int i;
	ut8 buf[8];
	RDebugFrame *frame;
	ut64 ptr, ebp2 = UT64_MAX;
	ut64 _rip, _rbp;
	RList *list;
	RReg *reg = dbg->reg;
	RIOBind *bio = &dbg->iob;
	RAnalFunction *fcn;

	_rip = r_reg_get_value (reg, r_reg_get (reg, "rip", R_REG_TYPE_GPR));
	if (at == UT64_MAX) {
		//_rsp = r_reg_get_value (reg, r_reg_get (reg, "rsp", R_REG_TYPE_GPR));
		_rbp = r_reg_get_value (reg, r_reg_get (reg, "rbp", R_REG_TYPE_GPR));
	} else {
		_rbp = at;
	}

	list = r_list_new ();
	list->free = free;
	bio->read_at (bio->io, _rip, (ut8*)&buf, 8);

	// TODO : frame->size by using esil to emulate first instructions
	fcn = r_anal_get_fcn_in (dbg->anal, _rip, R_ANAL_FCN_TYPE_NULL);
	if (fcn) {
		frame = R_NEW0 (RDebugFrame);
		frame->addr = _rip;
		frame->size = 0;
		frame->sp = _rbp;
		frame->bp = _rbp + 8; // XXX
		r_list_append (list, frame);
	}

	for (i=1; i<dbg->btdepth; i++) {
		// TODO: make those two reads in a shot
		bio->read_at (bio->io, _rbp, (ut8*)&ebp2, 8);
		if (ebp2 == UT64_MAX)
			break;
		bio->read_at (bio->io, _rbp+8, (ut8*)&ptr, 8);
		if (!ptr || !_rbp)
			break;
		//fcn = r_anal_get_fcn_in (dbg->anal, ptr, R_ANAL_FCN_TYPE_NULL);
		frame = R_NEW0 (RDebugFrame);
		frame->addr = ptr;
		frame->size = 0;
		frame->sp = _rbp;
		frame->bp = _rbp + 8;
		//frame->name = (fcn && fcn->name) ? strdup (fcn->name) : NULL;
		r_list_append (list, frame);
		_rbp = ebp2;
	}

	return list;
}
Esempio n. 2
0
static RList *backtrace_x86_64(RDebug *dbg, ut64 at) {
	int i;
	ut8 buf[8];
	RDebugFrame *frame;
	ut64 ptr, ebp2;
	ut64 _rip, _rsp, _rbp = 0;
	RList *list;
	RReg *reg = dbg->reg;
	RIOBind *bio = &dbg->iob;

	_rip = r_reg_get_value (reg, r_reg_get (reg, "rip", R_REG_TYPE_GPR));
	if (at == UT64_MAX) {
		_rsp = r_reg_get_value (reg, r_reg_get (reg, "rsp", R_REG_TYPE_GPR));
		_rbp = r_reg_get_value (reg, r_reg_get (reg, "rbp", R_REG_TYPE_GPR));
	} else {
		_rsp = _rbp = at;
	}

	list = r_list_new ();
	list->free = free;
	bio->read_at (bio->io, _rip, (ut8*)&buf, 8);
	/* %rbp=old rbp, %rbp+4 points to ret */
	/* Plugin before function prelude: push %rbp ; mov %rsp, %rbp */
	if (!memcmp (buf, "\x55\x89\xe5", 3) || !memcmp (buf, "\x89\xe5\x57", 3)) {
		if (!bio->read_at (bio->io, _rsp, (ut8*)&ptr, 8)) {
			eprintf ("read error at 0x%08"PFMT64x"\n", _rsp);
			r_list_purge (list);
			free (list);
			return false;
		}
		frame = R_NEW0 (RDebugFrame);
		frame->addr = ptr;
		frame->size = 0; // TODO ?
		r_list_append (list, frame);
		_rbp = ptr;
	}

	for (i=1; i<dbg->btdepth; i++) {
		// TODO: make those two reads in a shot
		bio->read_at (bio->io, _rbp, (ut8*)&ebp2, 8);
		if (ebp2 == UT64_MAX)
			break;
		bio->read_at (bio->io, _rbp+8, (ut8*)&ptr, 8);
		if (!ptr || !_rbp)
			break;
		frame = R_NEW0 (RDebugFrame);
		frame->addr = ptr;
		frame->size = 0; // TODO ?
		r_list_append (list, frame);
		_rbp = ebp2;
	}
	return list;
}
Esempio n. 3
0
static ut64 ws_find_label(int l, RIOBind iob) {
	RIO *io = iob.io;
	ut64 cur = 0, size = iob.desc_size (io->desc);
	ut8 buf[128];
	RAsmOp aop;
	iob.read_at (iob.io, cur, buf, 128);
	while (cur <= size && wsdis (&aop, buf, 128)) {
		const char *buf_asm = r_strbuf_get (&aop.buf_asm); // r_asm_op_get_asm (&aop);
		if (buf_asm && (strlen (buf_asm) > 4) && buf_asm[0] == 'm' && buf_asm[1] == 'a' && l == atoi (buf_asm + 5)) {
			return cur;
		}
		cur = cur + aop.size;
		iob.read_at (iob.io, cur, buf, 128);
	}
	return 0;
}
Esempio n. 4
0
static void ios_hwstep_enable32 (RDebug *dbg, task_t port, int enable) {
	int i;
	static ARMDebugState32 olds;
	ARMDebugState32 ds;

	mach_msg_type_number_t count = ARM_DEBUG_STATE32_COUNT;
	(void) thread_get_state (port,
	  		ARM_DEBUG_STATE32,
			(thread_state_t)&ds,
			&count);

	//static ut64 chainstep = UT64_MAX;
	if (enable) {
		RIOBind *bio = &dbg->iob;
		ut32 pc = r_reg_get_value (dbg->reg,
		  r_reg_get (dbg->reg, "pc", R_REG_TYPE_GPR));
		ut32 cpsr = r_reg_get_value (dbg->reg,
		  r_reg_get (dbg->reg, "cpsr", R_REG_TYPE_GPR));

		for (i = 0; i < 16 ; i++) {
			ds.bcr[i] = ds.bvr[i] = 0;
		}
		olds = ds;
		//chainstep = UT64_MAX;
		// state = old_state;
		ds.bvr[i] = pc & (UT32_MAX >> 2) << 2;
		ds.bcr[i] = BCR_M_IMVA_MISMATCH | S_USER | BCR_ENABLE;
		if (cpsr & 0x20) {
			ut16 op;
			if (pc & 2) {
				ds.bcr[i] |= BAS_IMVA_2_3;
			} else {
				ds.bcr[i] |= BAS_IMVA_0_1;
			}
			/* check for thumb */
			bio->read_at (bio->io, pc, (void *)&op, 2);
			if (isThumb32 (op)) {
				eprintf ("Thumb32 chain stepping not supported yet\n");
				//chainstep = pc + 2;
			} else {
				ds.bcr[i] |= BAS_IMVA_ALL;
			}
		} else {
			ds.bcr[i] |= BAS_IMVA_ALL;
		}
	} else {
Esempio n. 5
0
static ut64 ws_find_label(int l, RIOBind iob) {
	ut64 cur = 0, size = iob.size(iob.io);
	ut8 buf[128];
	RAsmOp *aop;
	aop = R_NEW0(RAsmOp);
	iob.read_at(iob.io, cur, buf, 128);
	while(cur <= size && wsdis(aop, buf, 128)) {
		if(	aop->buf_asm[0] == 'm' &&
			aop->buf_asm[1] == 'a' &&
			l == atoi(&aop->buf_asm[5])) {
				r_asm_op_free(aop);
				return cur;
		}
		cur = cur + aop->size;
		iob.read_at(iob.io, cur, buf, 128);
	}
	r_asm_op_free(aop);
	return 0;
}
Esempio n. 6
0
void gb_bankswitch_detect(RMeta *m, RIOBind iob, ut64 addr, ut16 ldarg) {
	ut8 rt;
	if(addr > 0x3fff)
		return;
	iob.read_at(iob.io, 0x147, &rt, 1);									//xxx: it won't change
	switch(gb_mbc_resolve(rt)) {
		case -1:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "unknown MBC!!!");
		case 0:
			return;
		default:
			meta_gb_bankswitch_cmt(m, addr, ldarg, (ut8)gb_mbc_resolve(rt));
	}
}
Esempio n. 7
0
static ut64 is_pointer(RAnal *anal, const ut8 *buf, int size) {
	ut64 n;
	ut8 buf2[32];
	RIOBind *iob = &anal->iob;
	if (size > sizeof (buf2))
		size = sizeof (buf2);
	n = r_mem_get_num (buf, size);
	if (!n) return 1; // null pointer
#if USE_IS_VALID_OFFSET
	int r = iob->is_valid_offset (iob->io, n, 0);
	return r? n: 0LL;
#else
	// optimization to ignore very low and very high pointers
	// this makes disasm 5x faster, but can result in some false positives
	// we should compare with current offset, to avoid
	// short/long references. and discard invalid ones
	if (n < 0x1000) return 0;	// probably wrong
	if (n > 0xffffffffffffLL) return 0; // probably wrong

	if (iob->read_at (iob->io, n, buf2, size) != size) return 0;
	return is_invalid (buf2, size)? 0: n;
#endif
}
Esempio n. 8
0
static int modify_trace_bit(RDebug *dbg, xnu_thread *th, int enable) {
	R_DEBUG_REG_T *state;
  	kern_return_t kr;
	int ret;
	ret = xnu_thread_get_drx (dbg, th);
	if (ret == R_FALSE) {
		eprintf ("error to get drx registers modificy_trace_bit arm\n");
		return R_FALSE;
	}
	state = (R_DEBUG_REG_T)th->drx;
	if (state->flavor == ARM_DEBUG_STATE64) {
		state->uds.ds64.__mdscr_el1 = (state->uds64.__mdscr_el1 \
					& SS_ENABLE) & (enable ? SS_ENABLE : 0);

	} else if (state->flavor == ARM_DEBUG_STATE32) {
		R_REG_T *regs;
		ret = xnu_thread_get_gpr (dbg, th);
		if (ret == R_FALSE) {
			eprintf ("error to get gpr register modificy_trace_bit arm\n");
			return R_FALSE;
		}
		regs = (R_REG_T)th->gpr;
		if (enable) {
			int r, i = 0;
			RIOBind *bio = &dbg->io;
			(R_DEBUG_REG_T)th->oldstate = state;
			//set a breakpoint that will stop when the PC doesn't
			//match the current one
			//set the current PC as the breakpoint address
			state->uds.ds32.__bvr[i] = regs->ts_32.__pc;
			state->uds.ds32.__bcr[i] = BCR_M_IMVA_MISMATCH | //stop on address mismatch
				S_USER | //stop only in user mode
				BCR_ENABLE; // enable this breakpoint
			if (regs->ts_32.__cpsr & 0x20) {
				ut16 op;
				// Thumb breakpoint
				if (regs->ts_32.__pc & 2) {
					state->uds.ds32.__bcr[i] |= BAS_IMVA_2_3;
				} else {
					state->uds.ds32.__bcr[i] |= BAS_IMVA_0_1;
				}
				if (bio->read_at (bio->io, regs->ts_32.__pc,
						(void *)&op, 2) < 1) {
					eprintf ("Failed to read opcode modify_trace_bit\n");
					return false;
				}
				if (is_thumb_32 (op)) {
					eprintf ("Thumb32 chain stepping not supported yet\n");
					return false;
				} else {
					// Extend the number of bits to ignore for the mismatch
					state->uds.ds32.__bcr[i] |= BAS_IMVA_ALL;
				}
			} else {
				// ARM breakpoint
				state->uds.ds32.__bcr[i] |= BAS_IMVA_ALL; // Stop when any address bits change
			}
			//disable bits
			for (i = i + 1; i < 16; i++) {
				//Disable all others
				state->uds.ds32.__bcr[i] = 0;
				state->uds.ds32.__bvr[i] = 0;
			}
		} else {
			state->uds.ds32 = ((R_DEBUG_REG_T)th->oldstate)->uds.ds32; //we set the old state
		}
	} else {
		eprintf ("Bad flavor modificy_trace_bit arm\n");
		return false;
	}
	//set state
	th->count = state->dsh.count;
	memcpy (th->state, state->uds, th->count);
	if (!xnu_thread_set_drx (dbg, th)) {
		eprintf ("error to set drx modificy_trace_bit arm\n");
		return false;
	}
	return true;
}
Esempio n. 9
0
static int modify_trace_bit(RDebug *dbg, xnu_thread_t *th, int enable) {
	int i = 0;
	int ret = xnu_thread_get_drx (dbg, th);
	if (!ret) {
		eprintf ("error to get drx registers modificy_trace_bit arm\n");
		return false;
	}
	if (th->flavor == ARM_DEBUG_STATE32) {
		arm_debug_state32_t *state = &th->debug.drx32;
		state->__mdscr_el1 = (state->__mdscr_el1 & SS_ENABLE) & (enable ? SS_ENABLE : 0);
	} else if (th->flavor == ARM_DEBUG_STATE) {
		arm_debug_state_t *state = &th->debug.drx;
		R_REG_T *regs;
		ret = xnu_thread_get_gpr (dbg, th);
		if (!ret) {
			eprintf ("error to get gpr register modificy_trace_bit arm\n");
			return false;
		}
		regs = (R_REG_T*)&th->gpr;
		if (enable) {
			static ut64 chained_address = 0;
			RIOBind *bio = &dbg->iob;
			//set a breakpoint that will stop when the PC doesn't
			//match the current one
			//set the current PC as the breakpoint address
			if (chained_address) {
				state->__bvr[i] = chained_address & 0xFFFFFFFCu;
				chained_address = 0;
			} else {
				state->__bvr[i] = regs->ts_32.__pc & 0xFFFFFFFCu;
			}
			state->__bcr[i] = BCR_M_IMVA_MISMATCH |  // stop on
								 // address
								 // mismatch
					  S_USER |  // stop only in user mode
					  BCR_ENABLE;  // enable this breakpoint
			if (regs->ts_32.__cpsr & 0x20) {
				ut16 op;
				// Thumb breakpoint
				if (regs->ts_32.__pc & 2)
					state->__bcr[i] |= BAS_IMVA_2_3;
				else
					state->__bcr[i] |= BAS_IMVA_0_1;
				if (bio->read_at (bio->io, regs->ts_32.__pc, (void *)&op, 2) < 1) {
					eprintf ("Failed to read opcode modify_trace_bit\n");
					return false;
				}
				if (is_thumb_32 (op)) {
					chained_address = regs->ts_32.__pc + 2;
				} else {
					// Extend the number of bits to ignore for the mismatch
					state->__bcr[i] |= BAS_IMVA_ALL;
				}
			} else {
				// ARM breakpoint
				state->__bcr[i] |= BAS_IMVA_ALL; // Stop when any address bits change
			}
			//disable bits
			for (i = i + 1; i < 16; i++) {
				//Disable all others
				state->__bcr[i] = 0;
				state->__bvr[i] = 0;
			}
		} else {
			if (state->__bcr[i] & BCR_ENABLE) {
				state->__bvr[i] = 0;
				state->__bcr[i] = 0;
			}
		}
	} else {
		eprintf ("Bad flavor modificy_trace_bit arm\n");
		return false;
	}
	//set state
	if (!xnu_thread_set_drx (dbg, th)) {
		eprintf ("error to set drx modificy_trace_bit arm\n");
		return false;
	}
	return true;
}
Esempio n. 10
0
static RList *backtrace_fuzzy(RDebug *dbg, ut64 at) {
	ut8 *stack, *ptr;
	int wordsize = dbg->bits; // XXX, dbg->bits is wordsize not bits
	ut64 sp;
	RIOBind *bio = &dbg->iob;
	int i, stacksize;
	ut64 *p64, addr = 0LL;
	ut32 *p32;
	ut16 *p16;
	ut64 cursp, oldsp;
	RList *list;

	stacksize = 1024*512; // 512KB .. should get the size from the regions if possible
	stack = malloc (stacksize);
	if (at == UT64_MAX) {
		RRegItem *ri;
		RReg *reg = dbg->reg;
		const char *spname = r_reg_get_name (reg, R_REG_NAME_SP);
		if (!spname) {
			eprintf ("Cannot find stack pointer register\n");
			free (stack);
			return NULL;
		}
		ri = r_reg_get (reg, spname, R_REG_TYPE_GPR);
		if (!ri) {
			eprintf ("Cannot find stack pointer register\n");
			free (stack);
			return NULL;
		}
		sp = r_reg_get_value (reg, ri);
	} else {
		sp = at;
	}

	list = r_list_new ();
	list->free = free;
	cursp = oldsp = sp;
	(void)bio->read_at (bio->io, sp, stack, stacksize);
	ptr = stack;
	for (i=0; i<dbg->btdepth; i++) {
		p64 = (ut64*)ptr;
		p32 = (ut32*)ptr;
		p16 = (ut16*)ptr;
		switch (wordsize) {
		case 8: addr = *p64; break;
		case 4: addr = *p32; break;
		case 2: addr = *p16; break;
		default:
			eprintf ("Invalid word size with asm.bits\n");
			r_list_free (list);
			return NULL;
		}
		if (iscallret (dbg, addr)) {
			RDebugFrame *frame = R_NEW0 (RDebugFrame);
			frame->addr = addr;
			frame->size = cursp - oldsp;
			frame->sp = cursp;
			frame->bp = oldsp; //addr + (i * wordsize); // -4 || -8
			// eprintf ("--------------> 0x%llx (%d)\n", addr, frame->size);
			r_list_append (list, frame);
			oldsp = cursp;
		}
		ptr += wordsize;
		cursp += wordsize;
	}
	return list;
}