diff options
Diffstat (limited to 'tools/objtool/arch/x86/decode.c')
| -rw-r--r-- | tools/objtool/arch/x86/decode.c | 54 | 
1 files changed, 40 insertions, 14 deletions
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c index cde9c36e40ae..549813cff8ab 100644 --- a/tools/objtool/arch/x86/decode.c +++ b/tools/objtool/arch/x86/decode.c @@ -11,11 +11,11 @@  #include "../../../arch/x86/lib/inat.c"  #include "../../../arch/x86/lib/insn.c" -#include "../../check.h" -#include "../../elf.h" -#include "../../arch.h" -#include "../../warn.h"  #include <asm/orc_types.h> +#include <objtool/check.h> +#include <objtool/elf.h> +#include <objtool/arch.h> +#include <objtool/warn.h>  static unsigned char op_to_cfi_reg[][2] = {  	{CFI_AX, CFI_R8}, @@ -222,15 +222,38 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,  		break;  	case 0x89: -		if (rex_w && !rex_r && modrm_mod == 3 && modrm_reg == 4) { +		if (rex_w && !rex_r && modrm_reg == 4) { -			/* mov %rsp, reg */ -			ADD_OP(op) { -				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]; +			if (modrm_mod == 3) { +				/* mov %rsp, reg */ +				ADD_OP(op) { +					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]; +				} +				break; + +			} else { +				/* skip nontrivial SIB */ +				if (modrm_rm == 4 && !(sib == 0x24 && rex_b == rex_x)) +					break; + +				/* skip RIP relative displacement */ +				if (modrm_rm == 5 && modrm_mod == 0) +					break; + +				/* mov %rsp, disp(%reg) */ +				ADD_OP(op) { +					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.offset = insn.displacement.value; +				} +				break;  			} +  			break;  		} @@ -259,8 +282,10 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,  				op->dest.reg = CFI_BP;  				op->dest.offset = insn.displacement.value;  			} +			break; +		} -		} else if (rex_w && !rex_b && modrm_rm == 4 && sib == 0x24) { +		if (rex_w && !rex_b && modrm_rm == 4 && sib == 0x24) {  			/* mov reg, disp(%rsp) */  			ADD_OP(op) { @@ -270,6 +295,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,  				op->dest.reg = CFI_SP;  				op->dest.offset = insn.displacement.value;  			} +			break;  		}  		break; @@ -563,8 +589,8 @@ void arch_initial_func_cfi_state(struct cfi_init_state *state)  	state->cfa.offset = 8;  	/* initial RA (return address) */ -	state->regs[16].base = CFI_CFA; -	state->regs[16].offset = -8; +	state->regs[CFI_RA].base = CFI_CFA; +	state->regs[CFI_RA].offset = -8;  }  const char *arch_nop_insn(int len)  | 
