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