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;
}