Commit 16ef7f15 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar
Browse files

objtool,x86: Simplify register decode



Since the CFI_reg number now matches the instruction encoding order do
away with the op_to_cfi_reg[] and use direct assignment.

Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
Acked-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
Tested-by: default avatarNick Desaulniers <ndesaulniers@google.com>
Link: https://lkml.kernel.org/r/20210211173627.362004522@infradead.org
parent ffc7e74f
Loading
Loading
Loading
Loading
+39 −40
Original line number Diff line number Diff line
@@ -17,17 +17,6 @@
#include <objtool/arch.h>
#include <objtool/warn.h>

static unsigned char op_to_cfi_reg[][2] = {
	{CFI_AX, CFI_R8},
	{CFI_CX, CFI_R9},
	{CFI_DX, CFI_R10},
	{CFI_BX, CFI_R11},
	{CFI_SP, CFI_R12},
	{CFI_BP, CFI_R13},
	{CFI_SI, CFI_R14},
	{CFI_DI, CFI_R15},
};

static int is_x86_64(const struct elf *elf)
{
	switch (elf->ehdr.e_machine) {
@@ -94,7 +83,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
	unsigned char op1, op2,
		      rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0,
		      modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0,
		      sib = 0;
		      sib = 0 /* , sib_scale = 0, sib_index = 0, sib_base = 0 */;
	struct stack_op *op = NULL;
	struct symbol *sym;

@@ -130,23 +119,29 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
	if (insn.modrm.nbytes) {
		modrm = insn.modrm.bytes[0];
		modrm_mod = X86_MODRM_MOD(modrm);
		modrm_reg = X86_MODRM_REG(modrm);
		modrm_rm = X86_MODRM_RM(modrm);
		modrm_reg = X86_MODRM_REG(modrm) + 8*rex_r;
		modrm_rm  = X86_MODRM_RM(modrm)  + 8*rex_b;
	}

	if (insn.sib.nbytes)
	if (insn.sib.nbytes) {
		sib = insn.sib.bytes[0];
		/*
		sib_scale = X86_SIB_SCALE(sib);
		sib_index = X86_SIB_INDEX(sib) + 8*rex_x;
		sib_base  = X86_SIB_BASE(sib)  + 8*rex_b;
		 */
	}

	switch (op1) {

	case 0x1:
	case 0x29:
		if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) {
		if (rex_w && modrm_mod == 3 && modrm_rm == CFI_SP) {

			/* add/sub reg, %rsp */
			ADD_OP(op) {
				op->src.type = OP_SRC_ADD;
				op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
				op->src.reg = modrm_reg;
				op->dest.type = OP_DEST_REG;
				op->dest.reg = CFI_SP;
			}
@@ -158,7 +153,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
		/* push reg */
		ADD_OP(op) {
			op->src.type = OP_SRC_REG;
			op->src.reg = op_to_cfi_reg[op1 & 0x7][rex_b];
			op->src.reg = (op1 & 0x7) + 8*rex_b;
			op->dest.type = OP_DEST_PUSH;
		}

@@ -170,7 +165,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
		ADD_OP(op) {
			op->src.type = OP_SRC_POP;
			op->dest.type = OP_DEST_REG;
			op->dest.reg = op_to_cfi_reg[op1 & 0x7][rex_b];
			op->dest.reg = (op1 & 0x7) + 8*rex_b;
		}

		break;
@@ -223,7 +218,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
		break;

	case 0x89:
		if (rex_w && !rex_r && modrm_reg == 4) {
		if (rex_w && modrm_reg == CFI_SP) {

			if (modrm_mod == 3) {
				/* mov %rsp, reg */
@@ -231,17 +226,17 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
					op->src.type = OP_SRC_REG;
					op->src.reg = CFI_SP;
					op->dest.type = OP_DEST_REG;
					op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b];
					op->dest.reg = modrm_rm;
				}
				break;

			} else {
				/* skip nontrivial SIB */
				if (modrm_rm == 4 && !(sib == 0x24 && rex_b == rex_x))
				if ((modrm_rm & 7) == 4 && !(sib == 0x24 && rex_b == rex_x))
					break;

				/* skip RIP relative displacement */
				if (modrm_rm == 5 && modrm_mod == 0)
				if ((modrm_rm & 7) == 5 && modrm_mod == 0)
					break;

				/* mov %rsp, disp(%reg) */
@@ -249,7 +244,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
					op->src.type = OP_SRC_REG;
					op->src.reg = CFI_SP;
					op->dest.type = OP_DEST_REG_INDIRECT;
					op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b];
					op->dest.reg = modrm_rm;
					op->dest.offset = insn.displacement.value;
				}
				break;
@@ -258,12 +253,12 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
			break;
		}

		if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) {
		if (rex_w && modrm_mod == 3 && modrm_rm == CFI_SP) {

			/* mov reg, %rsp */
			ADD_OP(op) {
				op->src.type = OP_SRC_REG;
				op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
				op->src.reg = modrm_reg;
				op->dest.type = OP_DEST_REG;
				op->dest.reg = CFI_SP;
			}
@@ -272,13 +267,12 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,

		/* fallthrough */
	case 0x88:
		if (!rex_b &&
		    (modrm_mod == 1 || modrm_mod == 2) && modrm_rm == 5) {
		if ((modrm_mod == 1 || modrm_mod == 2) && modrm_rm == CFI_BP) {

			/* mov reg, disp(%rbp) */
			ADD_OP(op) {
				op->src.type = OP_SRC_REG;
				op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
				op->src.reg = modrm_reg;
				op->dest.type = OP_DEST_REG_INDIRECT;
				op->dest.reg = CFI_BP;
				op->dest.offset = insn.displacement.value;
@@ -286,12 +280,12 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
			break;
		}

		if (rex_w && !rex_b && modrm_rm == 4 && sib == 0x24) {
		if (rex_w && modrm_rm == CFI_SP && sib == 0x24) {

			/* mov reg, disp(%rsp) */
			ADD_OP(op) {
				op->src.type = OP_SRC_REG;
				op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
				op->src.reg = modrm_reg;
				op->dest.type = OP_DEST_REG_INDIRECT;
				op->dest.reg = CFI_SP;
				op->dest.offset = insn.displacement.value;
@@ -302,7 +296,10 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
		break;

	case 0x8b:
		if (rex_w && !rex_b && modrm_mod == 1 && modrm_rm == 5) {
		if (!rex_w)
			break;

		if (modrm_mod == 1 && modrm_rm == CFI_BP) {

			/* mov disp(%rbp), reg */
			ADD_OP(op) {
@@ -310,11 +307,12 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
				op->src.reg = CFI_BP;
				op->src.offset = insn.displacement.value;
				op->dest.type = OP_DEST_REG;
				op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
				op->dest.reg = modrm_reg;
			}
			break;
		}

		} else if (rex_w && !rex_b && sib == 0x24 &&
			   modrm_mod != 3 && modrm_rm == 4) {
		if (modrm_mod != 3 && modrm_rm == CFI_SP && sib == 0x24) {

			/* mov disp(%rsp), reg */
			ADD_OP(op) {
@@ -322,8 +320,9 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
				op->src.reg = CFI_SP;
				op->src.offset = insn.displacement.value;
				op->dest.type = OP_DEST_REG;
				op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
				op->dest.reg = modrm_reg;
			}
			break;
		}

		break;
@@ -339,11 +338,11 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
			break;

		/* skip nontrivial SIB */
		if (modrm_rm == 4 && !(sib == 0x24 && rex_b == rex_x))
		if ((modrm_rm & 7) == 4 && !(sib == 0x24 && rex_b == rex_x))
			break;

		/* skip RIP relative displacement */
		if (modrm_rm == 5 && modrm_mod == 0)
		if ((modrm_rm & 7) == 5 && modrm_mod == 0)
			break;

		/* lea disp(%src), %dst */
@@ -356,9 +355,9 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
				/* lea disp(%src), %dst */
				op->src.type = OP_SRC_ADD;
			}
			op->src.reg = op_to_cfi_reg[modrm_rm][rex_b];
			op->src.reg = modrm_rm;
			op->dest.type = OP_DEST_REG;
			op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
			op->dest.reg = modrm_reg;
		}
		break;