Пример #1
0
/*
 * Read address at location and return updated location.
 */
db_addr_t
db_read_address(db_addr_t loc, int short_addr, int regmodrm, int rex,
    struct i_addr *addrp)
{
	int		mod, rm, sib, index, disp, size;

	size = (short_addr ? LONG : QUAD);
	mod = f_mod(regmodrm);
	rm  = f_rm(regmodrm, rex);

	if (mod == 3) {
		addrp->is_reg = TRUE;
		addrp->disp = rm;
		return (loc);
	}
	addrp->is_reg = FALSE;
	addrp->index = 0;

	if (rm == 4 || rm == 12) {
		get_value_inc(sib, loc, 1, FALSE);
		rm = sib_base(sib, rex);
		index = sib_index(sib, rex);
		if (index != 4)
			addrp->index = db_reg[size][index];
		addrp->ss = sib_ss(sib);
	}

	switch (mod) {
	case 0:
		if (rm == 5) {
		get_value_inc(addrp->disp, loc, 4, FALSE);
			addrp->base = 0;
		} else {
			addrp->disp = 0;
			addrp->base = db_reg[size][rm];
		}
		break;
	case 1:
		get_value_inc(disp, loc, 1, TRUE);
		addrp->disp = disp;
		addrp->base = db_reg[size][rm];
		break;
	case 2:
		get_value_inc(disp, loc, 4, FALSE);
		addrp->disp = disp;
		addrp->base = db_reg[size][rm];
		break;
	}
	return (loc);
}
Пример #2
0
/*
 * Disassemble 3DNow! instruction and return updated location.
 */
db_addr_t
db_disasm_3dnow(db_addr_t loc, int short_addr, int size, int rex, char *seg)
{
	int regmodrm, sib, displacement, opcode;

	get_value_inc(regmodrm, loc, 1, FALSE);
	get_value_inc(sib, loc, 1, FALSE);
	get_value_inc(displacement, loc, 1, FALSE);
	get_value_inc(opcode, loc, 1, FALSE);

	/* XXX fix later... */ 
	db_printf("<3DNow! instruction>");

	return (loc);
}
Пример #3
0
/*
 * Disassemble floating-point ("escape") instruction
 * and return updated location.
 */
db_addr_t
db_disasm_esc(db_addr_t loc, int inst, int short_addr, int size, int rex,
    char *seg)
{
	int		regmodrm;
	struct finst	*fp;
	int		mod;
	struct i_addr	address;
	char *		name;

	get_value_inc(regmodrm, loc, 1, FALSE);
	fp = &db_Esc_inst[inst - 0xd8][f_reg(regmodrm, 0)];
	mod = f_mod(regmodrm);
	if (mod != 3) {
		if (*fp->f_name == '\0') {
			db_printf("<bad instruction>");
			return (loc);
		}

		/*
		 * Normal address modes.
		 */
		loc = db_read_address(loc, short_addr, regmodrm, rex, &address);
		db_printf("%s", fp->f_name);
		switch (fp->f_size) {
		case SNGL:
			db_printf("s");
			break;
		case DBLR:
			db_printf("l");
			break;
		case EXTR:
			db_printf("t");
			break;
		case WORD:
			db_printf("s");
			break;
		case LONG:
			db_printf("l");
			break;
		case QUAD:
			db_printf("q");
			break;
		default:
			break;
		}
		db_printf("\t");
		db_print_address(seg, BYTE, &address);
	} else {
		/*
		 * 'reg-reg' - special formats
		 */
		switch (fp->f_rrmode) {
		case op2(ST,STI):
			name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
			db_printf("%s\t%%st,%%st(%d)",name, f_rm(regmodrm, 0));
			break;
		case op2(STI,ST):
			name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
			db_printf("%s\t%%st(%d),%%st",name, f_rm(regmodrm, 0));
			break;
		case op1(STI):
			name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
			db_printf("%s\t%%st(%d)",name, f_rm(regmodrm, 0));
			break;
		case op1(X):
			name = ((char * const *)fp->f_rrname)[f_rm(regmodrm,0)];
			if (*name == '\0')
				goto bad;
			db_printf("%s", name);
			break;
		case op1(XA):
			name = ((char * const *)fp->f_rrname)[f_rm(regmodrm,0)];
			if (*name == '\0')
				goto bad;
			db_printf("%s\t%%ax", name);
			break;
		default:
		bad:
			db_printf("<bad instruction>");
			break;
		}
	}

	return (loc);
}
Пример #4
0
/*
 * Disassemble instruction at 'loc'.  'altfmt' specifies an
 * (optional) alternate format.  Return address of start of
 * next instruction.
 */
db_addr_t
db_disasm(db_addr_t loc, boolean_t altfmt)
{
	int	inst;
	int	size;
	int	short_addr;
	char *	seg;
	struct inst *	ip;
	char *	i_name;
	int	i_size;
	int	i_mode;
	int	regmodrm = 0;
	boolean_t	first;
	int	displ;
	int	prefix;
	long	imm;
	int	imm2;
	int	len;
	int	rex = 0;
	int	segovr_grp;
	int	repe, repne;
	struct i_addr	address;
	db_addr_t	loc_orig = loc;
	char	tmpfmt[28];

	get_value_inc(inst, loc, 1, FALSE);
	short_addr = FALSE;
	size = LONG;
	seg = 0;
	segovr_grp = 0;
	repe = 0;
	repne = 0;

	/*
	 * Get prefixes
	 */
	prefix = TRUE;
	do {
		switch (inst) {
		case 0x66:		/* data16 */
			size = WORD;
			break;
		case 0x67:
			short_addr = TRUE;
			break;
		case 0x26:
			segovr_grp++;
			db_printf(" <segment override prefix ignored>");
			break;
		case 0x36:
			db_printf(" <segment override prefix ignored>");
			segovr_grp++;
			break;
		case 0x2e:
			db_printf(" <segment override prefix ignored>");
			segovr_grp++;
			break;
		case 0x3e:
			db_printf(" <segment override prefix ignored>");
			segovr_grp++;
			break;
		case 0x64:
			segovr_grp++;
			seg = "%fs";
			break;
		case 0x65:
			segovr_grp++;
			seg = "%gs";
			break;
		case 0xf0:
			db_printf("lock ");
			break;
		case 0xf2:
			repne++;
			break;
		case 0xf3:
			repe++;
			break;
		default:
			prefix = FALSE;
			break;
		}
		if (prefix)
			get_value_inc(inst, loc, 1, FALSE);
	} while (prefix);
	if (segovr_grp > 1)
		seg = "<bad segment override prefix combination> ";
	if (repe > 0 && repne > 0)
		db_printf("<bad repeat prefex combination> ");
	else if (repe > 0)
		db_printf("repe ");	/* XXX "rep" if not CMPSx or SCASx */
	else if (repne > 0)
		db_printf("repne ");

	if (inst >= 0x40 && inst <= 0x4f) {
		// rex page 14
		rex = inst;
		if (REX_W(rex))
			size = QUAD;
		get_value_inc(inst, loc, 1, FALSE);
	}

	if (inst >= 0xd8 && inst <= 0xdf) {
		loc = db_disasm_esc(loc, inst, short_addr, size, rex, seg);
		goto done;
	}

	if (inst == 0x0f) {
		get_value_inc(inst, loc, 1, FALSE);
		if (inst == 0x0f) {
			loc = db_disasm_3dnow(loc, short_addr, size, rex, seg);
			goto done;
		}
		ip = db_inst_0f[inst>>4];
		if (ip == 0)
			ip = &db_bad_inst;
		else
			ip = &ip[inst&0xf];
	} else {
Пример #5
0
/*
 * Read address at location and return updated location.
 */
db_addr_t
db_read_address(db_addr_t loc, int short_addr, int regmodrm,
    struct i_addr *addrp)
{
	int		mod, rm, sib, index, disp;

	mod = f_mod(regmodrm);
	rm  = f_rm(regmodrm);

	if (mod == 3) {
		addrp->is_reg = TRUE;
		addrp->disp = rm;
		return (loc);
	}
	addrp->is_reg = FALSE;
	addrp->index = 0;

	if (short_addr) {
		addrp->index = 0;
		addrp->ss = 0;
		switch (mod) {
		    case 0:
			if (rm == 6) {
				get_value_inc(disp, loc, 2, FALSE);
				addrp->disp = disp;
				addrp->base = 0;
			} else {
				addrp->disp = 0;
				addrp->base = db_index_reg_16[rm];
			}
			break;
		    case 1:
			get_value_inc(disp, loc, 1, TRUE);
			disp &= 0xffff;
			addrp->disp = disp;
			addrp->base = db_index_reg_16[rm];
			break;
		    case 2:
			get_value_inc(disp, loc, 2, FALSE);
			addrp->disp = disp;
			addrp->base = db_index_reg_16[rm];
			break;
		}
	} else {
		if (rm == 4) {
			get_value_inc(sib, loc, 1, FALSE);
			rm = sib_base(sib);
			index = sib_index(sib);
			if (index != 4)
				addrp->index = db_reg[LONG][index];
			addrp->ss = sib_ss(sib);
		}

		switch (mod) {
		    case 0:
			if (rm == 5) {
				get_value_inc(addrp->disp, loc, 4, FALSE);
				addrp->base = 0;
			} else {
				addrp->disp = 0;
				addrp->base = db_reg[LONG][rm];
			}
			break;
		    case 1:
			get_value_inc(disp, loc, 1, TRUE);
			addrp->disp = disp;
			addrp->base = db_reg[LONG][rm];
			break;
		    case 2:
			get_value_inc(disp, loc, 4, FALSE);
			addrp->disp = disp;
			addrp->base = db_reg[LONG][rm];
			break;
		}
	}
	return (loc);
}
Пример #6
0
/*
 * Disassemble instruction at 'loc'.  'altfmt' specifies an
 * (optional) alternate format.  Return address of start of
 * next instruction.
 */
db_addr_t
db_disasm(db_addr_t loc, boolean_t altfmt)
{
	int	inst;
	int	size;
	int	short_addr;
	char *	seg;
	struct inst *	ip;
	char *	i_name;
	int	i_size;
	int	i_mode;
	int	regmodrm = 0;
	boolean_t	first;
	int	displ;
	int	prefix;
	int	imm;
	int	imm2;
	int	len;
	struct i_addr	address;
	char	tmpfmt[24];

	get_value_inc(inst, loc, 1, FALSE);
	short_addr = FALSE;
	size = LONG;
	seg = 0;

	/*
	 * Get prefixes
	 */
	prefix = TRUE;
	do {
		switch (inst) {
		    case 0x66:		/* data16 */
			size = WORD;
			break;
		    case 0x67:
			short_addr = TRUE;
			break;
		    case 0x26:
			seg = "%es";
			break;
		    case 0x36:
			seg = "%ss";
			break;
		    case 0x2e:
			seg = "%cs";
			break;
		    case 0x3e:
			seg = "%ds";
			break;
		    case 0x64:
			seg = "%fs";
			break;
		    case 0x65:
			seg = "%gs";
			break;
		    case 0xf0:
			db_printf("lock ");
			break;
		    case 0xf2:
			db_printf("repne ");
			break;
		    case 0xf3:
			db_printf("repe ");	/* XXX repe VS rep */
			break;
		    default:
			prefix = FALSE;
			break;
		}
		if (prefix)
			get_value_inc(inst, loc, 1, FALSE);
	} while (prefix);

	if (inst >= 0xd8 && inst <= 0xdf) {
		loc = db_disasm_esc(loc, inst, short_addr, size, seg);
		db_printf("\n");
		return (loc);
	}

	if (inst == 0x0f) {
		get_value_inc(inst, loc, 1, FALSE);
		ip = db_inst_0f[inst>>4];
		if (ip == 0)
			ip = &db_bad_inst;
		else
			ip = &ip[inst&0xf];
	} else {
Пример #7
0
/*
 * Read address at location and return updated location.
 */
static db_addr_t
db_read_address(db_addr_t loc, int short_addr, int rex, int regmodrm,
    struct i_addr *addrp)
{
	int		mod, rm, sib, index, disp, size, have_sib;

	mod = f_mod(rex, regmodrm);
	rm  = f_rm(rex, regmodrm);

	if (mod == 3) {
	    addrp->is_reg = TRUE;
	    addrp->disp = rm;
	    return (loc);
	}
	addrp->is_reg = FALSE;
	addrp->index = NULL;

	if (short_addr)
	    size = LONG;
	else
	    size = QUAD;

	if ((rm & 0x7) == 4) {
	    get_value_inc(sib, loc, 1, FALSE);
	    rm = sib_base(rex, sib);
	    index = sib_index(rex, sib);
	    if (index != 4)
		addrp->index = db_reg[1][size][index];
	    addrp->ss = sib_ss(rex, sib);
	    have_sib = 1;
	} else
	    have_sib = 0;

	switch (mod) {
	    case 0:
		if (rm == 5) {
		    get_value_inc(addrp->disp, loc, 4, FALSE);
		    if (have_sib)
			addrp->base = NULL;
		    else if (short_addr)
			addrp->base = "%eip";
		    else
			addrp->base = "%rip";
		} else {
		    addrp->disp = 0;
		    addrp->base = db_reg[1][size][rm];
		}
		break;

	    case 1:
		get_value_inc(disp, loc, 1, TRUE);
		addrp->disp = disp;
		addrp->base = db_reg[1][size][rm];
		break;

	    case 2:
		get_value_inc(disp, loc, 4, FALSE);
		addrp->disp = disp;
		addrp->base = db_reg[1][size][rm];
		break;
	}
	return (loc);
}
Пример #8
0
/*
 * Disassemble instruction at 'loc'.  'altfmt' specifies an
 * (optional) alternate format.  Return address of start of
 * next instruction.
 */
db_addr_t
db_disasm(
    db_addr_t	loc,
    bool	altfmt)
{
	int	inst;
	int	size;
	int	short_addr;
	const char *	seg;
	const struct inst *	ip;
	const char *	i_name;
	int	i_size;
	int	i_mode;
	int	regmodrm = 0;
	bool	first;
	int	displ;
	int	prefix;
	int	imm;
	int	imm2;
	int	len;
	struct i_addr	address;

#ifdef _KERNEL
	pt_entry_t *pte, *pde;

	/*
	 * Don't try to disassemble the location if the mapping is invalid.
	 * If we do, we'll fault, and end up debugging the debugger!
	 * in the case of largepages, "pte" is really the pde and "pde" is
	 * really the entry for the pdp itself.
	 */
	if ((vaddr_t)loc >= VM_MIN_KERNEL_ADDRESS)
		pte = kvtopte((vaddr_t)loc);
	else
		pte = vtopte((vaddr_t)loc);
	pde = vtopte((vaddr_t)pte);
	if ((*pde & PG_V) == 0 || (*pte & PG_V) == 0) {
		db_printf("invalid address\n");
		return (loc);
	}
#endif

	get_value_inc(inst, loc, 1, false);
	short_addr = false;
	size = LONG;
	seg = 0;

	/*
	 * Get prefixes
	 */
	prefix = true;
	do {
		switch (inst) {
		    case 0x66:		/* data16 */
			size = WORD;
			break;
		    case 0x67:
			short_addr = true;
			break;
		    case 0x26:
			seg = "%es";
			break;
		    case 0x36:
			seg = "%ss";
			break;
		    case 0x2e:
			seg = "%cs";
			break;
		    case 0x3e:
			seg = "%ds";
			break;
		    case 0x64:
			seg = "%fs";
			break;
		    case 0x65:
			seg = "%gs";
			break;
		    case 0xf0:
			db_printf("lock ");
			break;
		    case 0xf2:
			db_printf("repne ");
			break;
		    case 0xf3:
			db_printf("repe ");	/* XXX repe VS rep */
			break;
		    default:
			prefix = false;
			break;
		}
		if (prefix)
			get_value_inc(inst, loc, 1, false);
	} while (prefix);

	if (inst >= 0xd8 && inst <= 0xdf) {
		loc = db_disasm_esc(loc, inst, short_addr, size, seg);
		db_printf("\n");
		return (loc);
	}

	if (inst == 0x0f) {
		get_value_inc(inst, loc, 1, false);
		ip = db_inst_0f[inst>>4];
		if (ip == 0)
			ip = &db_bad_inst;
		else
			ip = &ip[inst&0xf];
	} else {