Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libnvmm In !64bit mode RIP-relative is null+disp32, hand...



details:   https://anonhg.NetBSD.org/src/rev/e3bfabb53d5c
branches:  trunk
changeset: 447208:e3bfabb53d5c
user:      maxv <maxv%NetBSD.org@localhost>
date:      Fri Jan 04 10:25:39 2019 +0000

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

diffstat:

 lib/libnvmm/libnvmm_x86.c |  30 +++++++++++++++++++++++++-----
 1 files changed, 25 insertions(+), 5 deletions(-)

diffs (66 lines):

diff -r 26d583eefc56 -r e3bfabb53d5c lib/libnvmm/libnvmm_x86.c
--- a/lib/libnvmm/libnvmm_x86.c Fri Jan 04 05:35:24 2019 +0000
+++ b/lib/libnvmm/libnvmm_x86.c Fri Jan 04 10:25:39 2019 +0000
@@ -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 @@
 }
 
 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 @@
        /* 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 @@
                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 @@
                        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;
        }



Home | Main Index | Thread Index | Old Index