Module Name:    src
Committed By:   maxv
Date:           Fri Jan  4 10:25:40 UTC 2019

Modified Files:
        src/lib/libnvmm: libnvmm_x86.c

Log Message:
In !64bit mode RIP-relative is null+disp32, handle that correctly.


To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 src/lib/libnvmm/libnvmm_x86.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libnvmm/libnvmm_x86.c
diff -u src/lib/libnvmm/libnvmm_x86.c:1.8 src/lib/libnvmm/libnvmm_x86.c:1.9
--- src/lib/libnvmm/libnvmm_x86.c:1.8	Wed Jan  2 12:18:08 2019
+++ src/lib/libnvmm/libnvmm_x86.c	Fri Jan  4 10:25:39 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: libnvmm_x86.c,v 1.8 2019/01/02 12:18:08 maxv Exp $	*/
+/*	$NetBSD: libnvmm_x86.c,v 1.9 2019/01/04 10:25:39 maxv Exp $	*/
 
 /*
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -1826,9 +1826,16 @@ has_sib(struct x86_instr *instr)
 }
 
 static inline bool
-is_rip_relative(struct x86_instr *instr)
+is_rip_relative(struct x86_decode_fsm *fsm, struct x86_instr *instr)
 {
-	return (instr->strm->disp.type == DISP_0 &&
+	return (fsm->is64bit && instr->strm->disp.type == DISP_0 &&
+	    instr->regmodrm.rm == RM_RBP_DISP32);
+}
+
+static inline bool
+is_disp32_only(struct x86_decode_fsm *fsm, struct x86_instr *instr)
+{
+	return (!fsm->is64bit && instr->strm->disp.type == DISP_0 &&
 	    instr->regmodrm.rm == RM_RBP_DISP32);
 }
 
@@ -1905,7 +1912,7 @@ node_regmodrm(struct x86_decode_fsm *fsm
 	/* The displacement applies to RM. */
 	strm->disp.type = get_disp_type(instr);
 
-	if (is_rip_relative(instr)) {
+	if (is_rip_relative(fsm, instr)) {
 		/* Overwrites RM */
 		strm->type = STORE_REG;
 		strm->u.reg = &gpr_map__rip;
@@ -1914,6 +1921,15 @@ node_regmodrm(struct x86_decode_fsm *fsm
 		return 0;
 	}
 
+	if (is_disp32_only(fsm, instr)) {
+		/* Overwrites RM */
+		strm->type = STORE_REG;
+		strm->u.reg = NULL;
+		strm->disp.type = DISP_4;
+		fsm_advance(fsm, 1, node_disp);
+		return 0;
+	}
+
 	reg = get_register_rm(instr, opcode);
 	if (reg == NULL) {
 		return -1;
@@ -2405,7 +2421,11 @@ store_to_gva(struct nvmm_x64_state *stat
 			gva += sib->scale * reg;
 		}
 	} else if (store->type == STORE_REG) {
-		gva = gpr_read_address(instr, state, store->u.reg->num);
+		if (store->u.reg == NULL) {
+			/* The base is null. Happens with disp32-only. */
+		} else {
+			gva = gpr_read_address(instr, state, store->u.reg->num);
+		}
 	} else {
 		gva = store->u.dmo;
 	}

Reply via email to