brintos

brintos / linux-shallow public Read only

0
0
Text · 18.2 KiB · ab5cdc3 Raw
771 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * x86 instruction analysis4 *5 * Copyright (C) IBM Corporation, 2002, 2004, 20096 */7 8#include <linux/kernel.h>9#ifdef __KERNEL__10#include <linux/string.h>11#else12#include <string.h>13#endif14#include "../include/asm/inat.h" /* __ignore_sync_check__ */15#include "../include/asm/insn.h" /* __ignore_sync_check__ */16#include "../include/linux/unaligned.h" /* __ignore_sync_check__ */17 18#include <linux/errno.h>19#include <linux/kconfig.h>20 21#include "../include/asm/emulate_prefix.h" /* __ignore_sync_check__ */22 23#define leXX_to_cpu(t, r)						\24({									\25	__typeof__(t) v;						\26	switch (sizeof(t)) {						\27	case 4: v = le32_to_cpu(r); break;				\28	case 2: v = le16_to_cpu(r); break;				\29	case 1:	v = r; break;						\30	default:							\31		BUILD_BUG(); break;					\32	}								\33	v;								\34})35 36/* Verify next sizeof(t) bytes can be on the same instruction */37#define validate_next(t, insn, n)	\38	((insn)->next_byte + sizeof(t) + n <= (insn)->end_kaddr)39 40#define __get_next(t, insn)	\41	({ t r = get_unaligned((t *)(insn)->next_byte); (insn)->next_byte += sizeof(t); leXX_to_cpu(t, r); })42 43#define __peek_nbyte_next(t, insn, n)	\44	({ t r = get_unaligned((t *)(insn)->next_byte + n); leXX_to_cpu(t, r); })45 46#define get_next(t, insn)	\47	({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); })48 49#define peek_nbyte_next(t, insn, n)	\50	({ if (unlikely(!validate_next(t, insn, n))) goto err_out; __peek_nbyte_next(t, insn, n); })51 52#define peek_next(t, insn)	peek_nbyte_next(t, insn, 0)53 54/**55 * insn_init() - initialize struct insn56 * @insn:	&struct insn to be initialized57 * @kaddr:	address (in kernel memory) of instruction (or copy thereof)58 * @buf_len:	length of the insn buffer at @kaddr59 * @x86_64:	!0 for 64-bit kernel or 64-bit app60 */61void insn_init(struct insn *insn, const void *kaddr, int buf_len, int x86_64)62{63	/*64	 * Instructions longer than MAX_INSN_SIZE (15 bytes) are invalid65	 * even if the input buffer is long enough to hold them.66	 */67	if (buf_len > MAX_INSN_SIZE)68		buf_len = MAX_INSN_SIZE;69 70	memset(insn, 0, sizeof(*insn));71	insn->kaddr = kaddr;72	insn->end_kaddr = kaddr + buf_len;73	insn->next_byte = kaddr;74	insn->x86_64 = x86_64;75	insn->opnd_bytes = 4;76	if (x86_64)77		insn->addr_bytes = 8;78	else79		insn->addr_bytes = 4;80}81 82static const insn_byte_t xen_prefix[] = { __XEN_EMULATE_PREFIX };83static const insn_byte_t kvm_prefix[] = { __KVM_EMULATE_PREFIX };84 85static int __insn_get_emulate_prefix(struct insn *insn,86				     const insn_byte_t *prefix, size_t len)87{88	size_t i;89 90	for (i = 0; i < len; i++) {91		if (peek_nbyte_next(insn_byte_t, insn, i) != prefix[i])92			goto err_out;93	}94 95	insn->emulate_prefix_size = len;96	insn->next_byte += len;97 98	return 1;99 100err_out:101	return 0;102}103 104static void insn_get_emulate_prefix(struct insn *insn)105{106	if (__insn_get_emulate_prefix(insn, xen_prefix, sizeof(xen_prefix)))107		return;108 109	__insn_get_emulate_prefix(insn, kvm_prefix, sizeof(kvm_prefix));110}111 112/**113 * insn_get_prefixes - scan x86 instruction prefix bytes114 * @insn:	&struct insn containing instruction115 *116 * Populates the @insn->prefixes bitmap, and updates @insn->next_byte117 * to point to the (first) opcode.  No effect if @insn->prefixes.got118 * is already set.119 *120 * * Returns:121 * 0:  on success122 * < 0: on error123 */124int insn_get_prefixes(struct insn *insn)125{126	struct insn_field *prefixes = &insn->prefixes;127	insn_attr_t attr;128	insn_byte_t b, lb;129	int i, nb;130 131	if (prefixes->got)132		return 0;133 134	insn_get_emulate_prefix(insn);135 136	nb = 0;137	lb = 0;138	b = peek_next(insn_byte_t, insn);139	attr = inat_get_opcode_attribute(b);140	while (inat_is_legacy_prefix(attr)) {141		/* Skip if same prefix */142		for (i = 0; i < nb; i++)143			if (prefixes->bytes[i] == b)144				goto found;145		if (nb == 4)146			/* Invalid instruction */147			break;148		prefixes->bytes[nb++] = b;149		if (inat_is_address_size_prefix(attr)) {150			/* address size switches 2/4 or 4/8 */151			if (insn->x86_64)152				insn->addr_bytes ^= 12;153			else154				insn->addr_bytes ^= 6;155		} else if (inat_is_operand_size_prefix(attr)) {156			/* oprand size switches 2/4 */157			insn->opnd_bytes ^= 6;158		}159found:160		prefixes->nbytes++;161		insn->next_byte++;162		lb = b;163		b = peek_next(insn_byte_t, insn);164		attr = inat_get_opcode_attribute(b);165	}166	/* Set the last prefix */167	if (lb && lb != insn->prefixes.bytes[3]) {168		if (unlikely(insn->prefixes.bytes[3])) {169			/* Swap the last prefix */170			b = insn->prefixes.bytes[3];171			for (i = 0; i < nb; i++)172				if (prefixes->bytes[i] == lb)173					insn_set_byte(prefixes, i, b);174		}175		insn_set_byte(&insn->prefixes, 3, lb);176	}177 178	/* Decode REX prefix */179	if (insn->x86_64) {180		b = peek_next(insn_byte_t, insn);181		attr = inat_get_opcode_attribute(b);182		if (inat_is_rex_prefix(attr)) {183			insn_field_set(&insn->rex_prefix, b, 1);184			insn->next_byte++;185			if (X86_REX_W(b))186				/* REX.W overrides opnd_size */187				insn->opnd_bytes = 8;188		} else if (inat_is_rex2_prefix(attr)) {189			insn_set_byte(&insn->rex_prefix, 0, b);190			b = peek_nbyte_next(insn_byte_t, insn, 1);191			insn_set_byte(&insn->rex_prefix, 1, b);192			insn->rex_prefix.nbytes = 2;193			insn->next_byte += 2;194			if (X86_REX_W(b))195				/* REX.W overrides opnd_size */196				insn->opnd_bytes = 8;197			insn->rex_prefix.got = 1;198			goto vex_end;199		}200	}201	insn->rex_prefix.got = 1;202 203	/* Decode VEX prefix */204	b = peek_next(insn_byte_t, insn);205	attr = inat_get_opcode_attribute(b);206	if (inat_is_vex_prefix(attr)) {207		insn_byte_t b2 = peek_nbyte_next(insn_byte_t, insn, 1);208		if (!insn->x86_64) {209			/*210			 * In 32-bits mode, if the [7:6] bits (mod bits of211			 * ModRM) on the second byte are not 11b, it is212			 * LDS or LES or BOUND.213			 */214			if (X86_MODRM_MOD(b2) != 3)215				goto vex_end;216		}217		insn_set_byte(&insn->vex_prefix, 0, b);218		insn_set_byte(&insn->vex_prefix, 1, b2);219		if (inat_is_evex_prefix(attr)) {220			b2 = peek_nbyte_next(insn_byte_t, insn, 2);221			insn_set_byte(&insn->vex_prefix, 2, b2);222			b2 = peek_nbyte_next(insn_byte_t, insn, 3);223			insn_set_byte(&insn->vex_prefix, 3, b2);224			insn->vex_prefix.nbytes = 4;225			insn->next_byte += 4;226			if (insn->x86_64 && X86_VEX_W(b2))227				/* VEX.W overrides opnd_size */228				insn->opnd_bytes = 8;229		} else if (inat_is_vex3_prefix(attr)) {230			b2 = peek_nbyte_next(insn_byte_t, insn, 2);231			insn_set_byte(&insn->vex_prefix, 2, b2);232			insn->vex_prefix.nbytes = 3;233			insn->next_byte += 3;234			if (insn->x86_64 && X86_VEX_W(b2))235				/* VEX.W overrides opnd_size */236				insn->opnd_bytes = 8;237		} else {238			/*239			 * For VEX2, fake VEX3-like byte#2.240			 * Makes it easier to decode vex.W, vex.vvvv,241			 * vex.L and vex.pp. Masking with 0x7f sets vex.W == 0.242			 */243			insn_set_byte(&insn->vex_prefix, 2, b2 & 0x7f);244			insn->vex_prefix.nbytes = 2;245			insn->next_byte += 2;246		}247	}248vex_end:249	insn->vex_prefix.got = 1;250 251	prefixes->got = 1;252 253	return 0;254 255err_out:256	return -ENODATA;257}258 259/**260 * insn_get_opcode - collect opcode(s)261 * @insn:	&struct insn containing instruction262 *263 * Populates @insn->opcode, updates @insn->next_byte to point past the264 * opcode byte(s), and set @insn->attr (except for groups).265 * If necessary, first collects any preceding (prefix) bytes.266 * Sets @insn->opcode.value = opcode1.  No effect if @insn->opcode.got267 * is already 1.268 *269 * Returns:270 * 0:  on success271 * < 0: on error272 */273int insn_get_opcode(struct insn *insn)274{275	struct insn_field *opcode = &insn->opcode;276	int pfx_id, ret;277	insn_byte_t op;278 279	if (opcode->got)280		return 0;281 282	ret = insn_get_prefixes(insn);283	if (ret)284		return ret;285 286	/* Get first opcode */287	op = get_next(insn_byte_t, insn);288	insn_set_byte(opcode, 0, op);289	opcode->nbytes = 1;290 291	/* Check if there is VEX prefix or not */292	if (insn_is_avx(insn)) {293		insn_byte_t m, p;294		m = insn_vex_m_bits(insn);295		p = insn_vex_p_bits(insn);296		insn->attr = inat_get_avx_attribute(op, m, p);297		/* SCALABLE EVEX uses p bits to encode operand size */298		if (inat_evex_scalable(insn->attr) && !insn_vex_w_bit(insn) &&299		    p == INAT_PFX_OPNDSZ)300			insn->opnd_bytes = 2;301		if ((inat_must_evex(insn->attr) && !insn_is_evex(insn)) ||302		    (!inat_accept_vex(insn->attr) &&303		     !inat_is_group(insn->attr))) {304			/* This instruction is bad */305			insn->attr = 0;306			return -EINVAL;307		}308		/* VEX has only 1 byte for opcode */309		goto end;310	}311 312	/* Check if there is REX2 prefix or not */313	if (insn_is_rex2(insn)) {314		if (insn_rex2_m_bit(insn)) {315			/* map 1 is escape 0x0f */316			insn_attr_t esc_attr = inat_get_opcode_attribute(0x0f);317 318			pfx_id = insn_last_prefix_id(insn);319			insn->attr = inat_get_escape_attribute(op, pfx_id, esc_attr);320		} else {321			insn->attr = inat_get_opcode_attribute(op);322		}323		goto end;324	}325 326	insn->attr = inat_get_opcode_attribute(op);327	while (inat_is_escape(insn->attr)) {328		/* Get escaped opcode */329		op = get_next(insn_byte_t, insn);330		opcode->bytes[opcode->nbytes++] = op;331		pfx_id = insn_last_prefix_id(insn);332		insn->attr = inat_get_escape_attribute(op, pfx_id, insn->attr);333	}334 335	if (inat_must_vex(insn->attr)) {336		/* This instruction is bad */337		insn->attr = 0;338		return -EINVAL;339	}340end:341	opcode->got = 1;342	return 0;343 344err_out:345	return -ENODATA;346}347 348/**349 * insn_get_modrm - collect ModRM byte, if any350 * @insn:	&struct insn containing instruction351 *352 * Populates @insn->modrm and updates @insn->next_byte to point past the353 * ModRM byte, if any.  If necessary, first collects the preceding bytes354 * (prefixes and opcode(s)).  No effect if @insn->modrm.got is already 1.355 *356 * Returns:357 * 0:  on success358 * < 0: on error359 */360int insn_get_modrm(struct insn *insn)361{362	struct insn_field *modrm = &insn->modrm;363	insn_byte_t pfx_id, mod;364	int ret;365 366	if (modrm->got)367		return 0;368 369	ret = insn_get_opcode(insn);370	if (ret)371		return ret;372 373	if (inat_has_modrm(insn->attr)) {374		mod = get_next(insn_byte_t, insn);375		insn_field_set(modrm, mod, 1);376		if (inat_is_group(insn->attr)) {377			pfx_id = insn_last_prefix_id(insn);378			insn->attr = inat_get_group_attribute(mod, pfx_id,379							      insn->attr);380			if (insn_is_avx(insn) && !inat_accept_vex(insn->attr)) {381				/* Bad insn */382				insn->attr = 0;383				return -EINVAL;384			}385		}386	}387 388	if (insn->x86_64 && inat_is_force64(insn->attr))389		insn->opnd_bytes = 8;390 391	modrm->got = 1;392	return 0;393 394err_out:395	return -ENODATA;396}397 398 399/**400 * insn_rip_relative() - Does instruction use RIP-relative addressing mode?401 * @insn:	&struct insn containing instruction402 *403 * If necessary, first collects the instruction up to and including the404 * ModRM byte.  No effect if @insn->x86_64 is 0.405 */406int insn_rip_relative(struct insn *insn)407{408	struct insn_field *modrm = &insn->modrm;409	int ret;410 411	if (!insn->x86_64)412		return 0;413 414	ret = insn_get_modrm(insn);415	if (ret)416		return 0;417	/*418	 * For rip-relative instructions, the mod field (top 2 bits)419	 * is zero and the r/m field (bottom 3 bits) is 0x5.420	 */421	return (modrm->nbytes && (modrm->bytes[0] & 0xc7) == 0x5);422}423 424/**425 * insn_get_sib() - Get the SIB byte of instruction426 * @insn:	&struct insn containing instruction427 *428 * If necessary, first collects the instruction up to and including the429 * ModRM byte.430 *431 * Returns:432 * 0: if decoding succeeded433 * < 0: otherwise.434 */435int insn_get_sib(struct insn *insn)436{437	insn_byte_t modrm;438	int ret;439 440	if (insn->sib.got)441		return 0;442 443	ret = insn_get_modrm(insn);444	if (ret)445		return ret;446 447	if (insn->modrm.nbytes) {448		modrm = insn->modrm.bytes[0];449		if (insn->addr_bytes != 2 &&450		    X86_MODRM_MOD(modrm) != 3 && X86_MODRM_RM(modrm) == 4) {451			insn_field_set(&insn->sib,452				       get_next(insn_byte_t, insn), 1);453		}454	}455	insn->sib.got = 1;456 457	return 0;458 459err_out:460	return -ENODATA;461}462 463 464/**465 * insn_get_displacement() - Get the displacement of instruction466 * @insn:	&struct insn containing instruction467 *468 * If necessary, first collects the instruction up to and including the469 * SIB byte.470 * Displacement value is sign-expanded.471 *472 * * Returns:473 * 0: if decoding succeeded474 * < 0: otherwise.475 */476int insn_get_displacement(struct insn *insn)477{478	insn_byte_t mod, rm, base;479	int ret;480 481	if (insn->displacement.got)482		return 0;483 484	ret = insn_get_sib(insn);485	if (ret)486		return ret;487 488	if (insn->modrm.nbytes) {489		/*490		 * Interpreting the modrm byte:491		 * mod = 00 - no displacement fields (exceptions below)492		 * mod = 01 - 1-byte displacement field493		 * mod = 10 - displacement field is 4 bytes, or 2 bytes if494		 * 	address size = 2 (0x67 prefix in 32-bit mode)495		 * mod = 11 - no memory operand496		 *497		 * If address size = 2...498		 * mod = 00, r/m = 110 - displacement field is 2 bytes499		 *500		 * If address size != 2...501		 * mod != 11, r/m = 100 - SIB byte exists502		 * mod = 00, SIB base = 101 - displacement field is 4 bytes503		 * mod = 00, r/m = 101 - rip-relative addressing, displacement504		 * 	field is 4 bytes505		 */506		mod = X86_MODRM_MOD(insn->modrm.value);507		rm = X86_MODRM_RM(insn->modrm.value);508		base = X86_SIB_BASE(insn->sib.value);509		if (mod == 3)510			goto out;511		if (mod == 1) {512			insn_field_set(&insn->displacement,513				       get_next(signed char, insn), 1);514		} else if (insn->addr_bytes == 2) {515			if ((mod == 0 && rm == 6) || mod == 2) {516				insn_field_set(&insn->displacement,517					       get_next(short, insn), 2);518			}519		} else {520			if ((mod == 0 && rm == 5) || mod == 2 ||521			    (mod == 0 && base == 5)) {522				insn_field_set(&insn->displacement,523					       get_next(int, insn), 4);524			}525		}526	}527out:528	insn->displacement.got = 1;529	return 0;530 531err_out:532	return -ENODATA;533}534 535/* Decode moffset16/32/64. Return 0 if failed */536static int __get_moffset(struct insn *insn)537{538	switch (insn->addr_bytes) {539	case 2:540		insn_field_set(&insn->moffset1, get_next(short, insn), 2);541		break;542	case 4:543		insn_field_set(&insn->moffset1, get_next(int, insn), 4);544		break;545	case 8:546		insn_field_set(&insn->moffset1, get_next(int, insn), 4);547		insn_field_set(&insn->moffset2, get_next(int, insn), 4);548		break;549	default:	/* opnd_bytes must be modified manually */550		goto err_out;551	}552	insn->moffset1.got = insn->moffset2.got = 1;553 554	return 1;555 556err_out:557	return 0;558}559 560/* Decode imm v32(Iz). Return 0 if failed */561static int __get_immv32(struct insn *insn)562{563	switch (insn->opnd_bytes) {564	case 2:565		insn_field_set(&insn->immediate, get_next(short, insn), 2);566		break;567	case 4:568	case 8:569		insn_field_set(&insn->immediate, get_next(int, insn), 4);570		break;571	default:	/* opnd_bytes must be modified manually */572		goto err_out;573	}574 575	return 1;576 577err_out:578	return 0;579}580 581/* Decode imm v64(Iv/Ov), Return 0 if failed */582static int __get_immv(struct insn *insn)583{584	switch (insn->opnd_bytes) {585	case 2:586		insn_field_set(&insn->immediate1, get_next(short, insn), 2);587		break;588	case 4:589		insn_field_set(&insn->immediate1, get_next(int, insn), 4);590		insn->immediate1.nbytes = 4;591		break;592	case 8:593		insn_field_set(&insn->immediate1, get_next(int, insn), 4);594		insn_field_set(&insn->immediate2, get_next(int, insn), 4);595		break;596	default:	/* opnd_bytes must be modified manually */597		goto err_out;598	}599	insn->immediate1.got = insn->immediate2.got = 1;600 601	return 1;602err_out:603	return 0;604}605 606/* Decode ptr16:16/32(Ap) */607static int __get_immptr(struct insn *insn)608{609	switch (insn->opnd_bytes) {610	case 2:611		insn_field_set(&insn->immediate1, get_next(short, insn), 2);612		break;613	case 4:614		insn_field_set(&insn->immediate1, get_next(int, insn), 4);615		break;616	case 8:617		/* ptr16:64 is not exist (no segment) */618		return 0;619	default:	/* opnd_bytes must be modified manually */620		goto err_out;621	}622	insn_field_set(&insn->immediate2, get_next(unsigned short, insn), 2);623	insn->immediate1.got = insn->immediate2.got = 1;624 625	return 1;626err_out:627	return 0;628}629 630/**631 * insn_get_immediate() - Get the immediate in an instruction632 * @insn:	&struct insn containing instruction633 *634 * If necessary, first collects the instruction up to and including the635 * displacement bytes.636 * Basically, most of immediates are sign-expanded. Unsigned-value can be637 * computed by bit masking with ((1 << (nbytes * 8)) - 1)638 *639 * Returns:640 * 0:  on success641 * < 0: on error642 */643int insn_get_immediate(struct insn *insn)644{645	int ret;646 647	if (insn->immediate.got)648		return 0;649 650	ret = insn_get_displacement(insn);651	if (ret)652		return ret;653 654	if (inat_has_moffset(insn->attr)) {655		if (!__get_moffset(insn))656			goto err_out;657		goto done;658	}659 660	if (!inat_has_immediate(insn->attr))661		/* no immediates */662		goto done;663 664	switch (inat_immediate_size(insn->attr)) {665	case INAT_IMM_BYTE:666		insn_field_set(&insn->immediate, get_next(signed char, insn), 1);667		break;668	case INAT_IMM_WORD:669		insn_field_set(&insn->immediate, get_next(short, insn), 2);670		break;671	case INAT_IMM_DWORD:672		insn_field_set(&insn->immediate, get_next(int, insn), 4);673		break;674	case INAT_IMM_QWORD:675		insn_field_set(&insn->immediate1, get_next(int, insn), 4);676		insn_field_set(&insn->immediate2, get_next(int, insn), 4);677		break;678	case INAT_IMM_PTR:679		if (!__get_immptr(insn))680			goto err_out;681		break;682	case INAT_IMM_VWORD32:683		if (!__get_immv32(insn))684			goto err_out;685		break;686	case INAT_IMM_VWORD:687		if (!__get_immv(insn))688			goto err_out;689		break;690	default:691		/* Here, insn must have an immediate, but failed */692		goto err_out;693	}694	if (inat_has_second_immediate(insn->attr)) {695		insn_field_set(&insn->immediate2, get_next(signed char, insn), 1);696	}697done:698	insn->immediate.got = 1;699	return 0;700 701err_out:702	return -ENODATA;703}704 705/**706 * insn_get_length() - Get the length of instruction707 * @insn:	&struct insn containing instruction708 *709 * If necessary, first collects the instruction up to and including the710 * immediates bytes.711 *712 * Returns:713 *  - 0 on success714 *  - < 0 on error715*/716int insn_get_length(struct insn *insn)717{718	int ret;719 720	if (insn->length)721		return 0;722 723	ret = insn_get_immediate(insn);724	if (ret)725		return ret;726 727	insn->length = (unsigned char)((unsigned long)insn->next_byte728				     - (unsigned long)insn->kaddr);729 730	return 0;731}732 733/* Ensure this instruction is decoded completely */734static inline int insn_complete(struct insn *insn)735{736	return insn->opcode.got && insn->modrm.got && insn->sib.got &&737		insn->displacement.got && insn->immediate.got;738}739 740/**741 * insn_decode() - Decode an x86 instruction742 * @insn:	&struct insn to be initialized743 * @kaddr:	address (in kernel memory) of instruction (or copy thereof)744 * @buf_len:	length of the insn buffer at @kaddr745 * @m:		insn mode, see enum insn_mode746 *747 * Returns:748 * 0: if decoding succeeded749 * < 0: otherwise.750 */751int insn_decode(struct insn *insn, const void *kaddr, int buf_len, enum insn_mode m)752{753	int ret;754 755#define INSN_MODE_KERN (enum insn_mode)-1 /* __ignore_sync_check__ mode is only valid in the kernel */756 757	if (m == INSN_MODE_KERN)758		insn_init(insn, kaddr, buf_len, IS_ENABLED(CONFIG_X86_64));759	else760		insn_init(insn, kaddr, buf_len, m == INSN_MODE_64);761 762	ret = insn_get_length(insn);763	if (ret)764		return ret;765 766	if (insn_complete(insn))767		return 0;768 769	return -EINVAL;770}771