commit c3db2bda113dff501862928bcf4f2efbc531f520 (from 9d5a42622dfd95dcefccc1de756f42ac3a7ee352) Merge: 9d5a42622dfd 2ef16d809162 Author: Josh Stone Date: Tue Aug 30 12:08:52 2016 -0700 Merge pull request #163 from cuviper/modify-data-64 fix insnCodeGen::modifyData's 64-bit conversion diff --git a/dyninstAPI/src/codegen-x86.C b/dyninstAPI/src/codegen-x86.C index ef8a6b0b4731..ad9ac8ec90ba 100644 --- a/dyninstAPI/src/codegen-x86.C +++ b/dyninstAPI/src/codegen-x86.C @@ -1196,10 +1196,6 @@ bool insnCodeGen::modifyData(Address targetAddr, instruction &insn, codeGen &gen /* get the prefix count */ size_t pref_count = instruct.getSize(); - - /* copy the prefix */ - memcpy(newInsn, origInsn, pref_count); - newInsn += pref_count; origInsn += pref_count; /* Decode the opcode */ @@ -1208,27 +1204,31 @@ bool insnCodeGen::modifyData(Address targetAddr, instruction &insn, codeGen &gen /* Calculate the amount of opcode bytes */ size_t opcode_len = instruct.getSize() - pref_count; - - /* Copy the opcode bytes */ - memcpy(newInsn, origInsn, opcode_len); - newInsn += opcode_len; origInsn += opcode_len; /* Get the value of the Mod/RM byte */ - unsigned char mod_rm = *origInsn; - origInsn++; + unsigned char mod_rm = *origInsn++; +#if defined(arch_x86_64) if (!is_disp32(newDisp+insnSz) && !is_addr32(targetAddr)) { // Case C: replace with 64-bit. + // This preamble must come before any writes to newInsn! is_data_abs64 = true; -#if defined(arch_x86_64) pointer_reg = (mod_rm & 0x38) != 0 ? 0 : 3; SET_PTR(newInsn, gen); emitPushReg64(pointer_reg, gen); emitMovImmToReg64(pointer_reg, targetAddr, true, gen); REGET_PTR(newInsn, gen); + } +#endif + + /* copy the prefix and opcode bytes */ + memcpy(newInsn, origInsnStart, pref_count + opcode_len); + newInsn += pref_count + opcode_len; + if (is_data_abs64) + { // change ModRM byte to use [pointer_reg]: requires // us to change last three bits (the r/m field) // to the value of pointer_reg @@ -1236,7 +1236,6 @@ bool insnCodeGen::modifyData(Address targetAddr, instruction &insn, codeGen &gen mod_rm = (mod_rm & 0xf8) | pointer_reg; /* Set the new ModR/M byte of the new instruction */ *newInsn++ = mod_rm; -#endif } else if (is_disp32(newDisp + insnSz)) { /* Instruction can remain a 32 bit instruction */